Autor Beitrag
knittel
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 71
Erhaltene Danke: 2

Win XP, Win7, openSUSE
Delphi 7
BeitragVerfasst: Mi 08.12.10 12:34 
Hallo allerseits,
Ich entwickle ein Strategie-Spiel. Dabei soll eine Einheit mehrere Waffen habe. Ich habe die Relativen Koordinaten zum Mittelpunkt (und der oberen linken Ecke). Wenn sich jetzt die Einheit dreht kommen die Schüsse immer noch von der selben position her, nicht mehr da wohin sich jetzt die Kanone gedreht hat.

Ich habe versucht dieses Problem zu lösen, aber irgendwie kommen die Schüsse jetzt nur noch zufällig irgendwoher. Könnte mir jemand helfen den Fehler zu finden?
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
// In der Shoot Funktion steht folgendes:

ListOfShots.Add(TShot.Create(                     // Create
(Xpos+Unitsize/2) + (cos(FWeapons[Weapon].SetAlpha + QAngle) * FWeapons[Weapon].Hypotenuse),  // PosX
(Ypos+Unitsize/2) - (sin(FWeapons[Weapon].SetAlpha + QAngle) * FWeapons[Weapon].Hypotenuse),  // PosY
(ToX / StepsNeeded),(ToY / StepsNeeded),QAngle,   // Various
FWeapons[Weapon].UnitBullet,                      // UnitBullet
FWeapons[Weapon].ATK,                             // Damage
OnUnit));     

// Die AlphaCalculation rufe ich am Ende des constructors auf (Ich definiere darin bereits die Werte der Einheit).
procedure TMilitaryUnitMultiWeapon.AlphaCalculation();
var Quotient: single;
    i: integer;
begin
for i:= 0 To FWeaponCount do
  begin
  // SETALPHA:
  // Ermitteln von New Relation Position
  FWeapons[i].RelX := round(FWeapons[i].RelX - Unitsize / 2);
  FWeapons[i].RelY := round(FWeapons[i].RelX - Unitsize / 2);

  // Keine Division durch 0
  if FWeapons[i].RelY = 0 then
    begin
    if (FWeapons[i].RelX < 0then FWeapons[i].SetAlpha:=180
    else FWeapons[i].SetAlpha:=0;
    end
  // Quotienten berechnen -> Winkel
  else
    begin
    Quotient := FWeapons[i].RelY / FWeapons[i].RelX;
    if FWeapons[i].RelX < 0 then FWeapons[i].SetAlpha := round(arctan(Quotient)*180/Pi+180)
    else FWeapons[i].SetAlpha := round(arctan(Quotient)*180/Pi);
    end;
  // HYPOTENUSE:
  FWeapons[i].Hypotenuse :=
  sqrt((FWeapons[i].RelX * FWeapons[i].RelX) + (FWeapons[i].RelY * FWeapons[i].RelY));
  end;
end// of procedure


Hier eine Erklärung der Variablen.

user defined image

RelX: X Abstand vom Mittelpunkt zur Waffe
RelY: Y Abstand vom Mittelpunkt zur Waffe
Hypotenuse: Abstand zur Waffe und Radius des Kreises
Der Mittelpunkt: Xpos (Absolute Position der Einheit) + Unitsize (Einheitengröße insgeamt) / 2 (weil wir zum Mittelpunkt wollen.
SetAlpha: Der Winkel indem die Hypotenuse zur X-Achse steht.
Der Winkel unter dem sich die Einheit gedreht hat.
Den Punkt an dem der Schuss letztendlich erscheinen soll.

Wenn irgendjemand ein Problem sieht, bitte posten!

_________________
"Wir können nicht fliehen!" "Wieso nicht?" "Sie haben mir die Schnürsenkel zusammengebunden!" "Die Schweine."
Tilo
ontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic starofftopic star
Beiträge: 1098
Erhaltene Danke: 13

Win7 geg. WInXP oder sogar Win98
Rad2007
BeitragVerfasst: Mi 08.12.10 13:50 
Hallo knittel,

Bei dem gezeigtem Programmtext kann ich keinen Fehler entdecken.
In TMilitaryUnitMultiWeapon.AlphaCalculation(); berechnest Du aber auch nur die Hypothenuse und den Winkel. Wie sieht der Programmcode beim "Schießen" aus? Dort müsstest Du zum Winkel der Waffe die Rotation des Gefährst hinzurechnen und dann mit Hilfe des momentanen Waffenwinkel und der Hypothenuse Xrel und yrel ausrechnen.

Mein Tipp zur Lösungsfindung: Erstell ein Fahrzeug bei dem du die Hypothenuse und anfänglichen Waffenwinkel nicht berechnest sondern auf Wunschwerte setzt.

MFG
Tilo
knittel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 71
Erhaltene Danke: 2

Win XP, Win7, openSUSE
Delphi 7
BeitragVerfasst: Mi 08.12.10 18:24 
Der obere Teil des Quell Text ist aus der Procedure TMilitaryUnit.Shoot()
Ich poste sie hier nochmal komplett.
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
procedure TMilitaryUnitMultiWeapon.ShootWith(Weapon, ToX, ToY, OnUnit:integer);
var QAngle: integer;
    Quotient, NDistance, StepsNeeded: single;
begin
FWeapons[Weapon].CurrentReload := FWeapons[Weapon].ReloadTimeOut ;
// Keine Division durch 0
if ToX = 0 then
  begin
  if (ToY < 0then QAngle:=180
  else QAngle:=0;
  end
// Quotienten berechnen -> Winkel
else
  begin
  Quotient := ToY / ToX;
  if ToX < 0 then QAngle := round(arctan(Quotient)*180/Pi+180)
  else QAngle := round(arctan(Quotient)*180/Pi);
  QAngle := QAngle + 180;
  end;
// X und Y Geschwindigkeit berechnen
NDistance:=sqrt((ToX*ToX)+(ToY*ToY));
StepsNeeded := NDistance / Shotlist[FUnitBullet].Speed;
case FWeapons[Weapon].WeaponKind of
Shot:
ListOfShots.Add(TShot.Create(                     // Create
(Xpos+Unitsize/2) + FWeapons[Weapon].RelX (cos(FWeapons[Weapon].SetAlpha + QAngle) * 
FWeapons[Weapon].Hypotenuse),  // PosX
(Ypos+Unitsize/2) + FWeapons[Weapon].RelY (sin(FWeapons[Weapon].SetAlpha + QAngle) * 
FWeapons[Weapon].Hypotenuse),  // PosY
(ToX / StepsNeeded),(ToY / StepsNeeded),QAngle,   // Various
FWeapons[Weapon].UnitBullet,                      // UnitBullet
FWeapons[Weapon].ATK,                             // Damage
OnUnit));                                         // Attacking On

Missile:
ListOfShots.Add(TMissile.Create(                     // Create
(Xpos+Unitsize/2) + FWeapons[Weapon].RelX (cos(FWeapons[Weapon].SetAlpha + QAngle) * 
FWeapons[Weapon].Hypotenuse),  // PosX
(Ypos+Unitsize/2) + FWeapons[Weapon].RelY (sin(FWeapons[Weapon].SetAlpha + QAngle) * 
FWeapons[Weapon].Hypotenuse),  // PosY
(ToX / StepsNeeded),(ToY / StepsNeeded),QAngle,   // Various
FWeapons[Weapon].UnitBullet,                      // UnitBullet
FWeapons[Weapon].ATK,                             // Damage
OnUnit));                                         // Attacking On
end;
end;

_________________
"Wir können nicht fliehen!" "Wieso nicht?" "Sie haben mir die Schnürsenkel zusammengebunden!" "Die Schweine."
Tilo
ontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic starofftopic star
Beiträge: 1098
Erhaltene Danke: 13

Win7 geg. WInXP oder sogar Win98
Rad2007
BeitragVerfasst: Do 09.12.10 23:30 
Irgendwie scheint der Wurm bei der Winkelberechnung drin zu sein:

Unter der Annahme das Tox und Toy Koordinatendifferenzen sind und die Weg richtung deines Fahrzeuges angeben folgendes auf leerer Form mit ein paar Labels in der Mitte folgendes in das OnMouseMove gesetzt:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  Quotient: Real;
  ToX: Integer;
  ToY: Integer;

begin
ToX:=x-Label1.Left;
ToY:=Y-label1.Top;
if ToX = 0 then
 begin
  if (ToY < 0then
    QAngle:=180
  else
   QAngle:=0;
end
// Quotienten berechnen -> Winkel
else
begin
  Quotient := ToY / ToX;
  if ToX < 0 then
   QAngle := round(arctan(Quotient)*180/Pi+180)
  else
    QAngle := round(arctan(Quotient)*180/Pi);

  QAngle := QAngle + 180;
end;

Label1.Caption:= Floattostr( QAngle);
Label5.Caption:=inttostr(Tox);
label6.Caption:=inttostr(ToY);
end;


Schiebe ich die Maus nach rechts steigt Tox,
Schiebe ich die Maus nach unten steigt Toy.
Irgenwie bekomme ich nun in der oberen Linken Ecke Werte um 400 und oberen rechts nie unter 90.
Ändere ich "QAngle := QAngle + 180;" auf "QAngle := QAngle + 90;" erhalte ich ein schönen Vollkreis mit 0° Oben und dann im Uhrzeigersinn steigend.
Vielleicht liegt dein Problem ja hier drin, oder ich hab bei meinen Beispiel das Koordiatensystem verbogen.

Ich denke letzteres dürfte der Fall sein. Ich denke dein Fehler liegt bei den Koordinatenberechnungen. Versuche mal statt

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
ListOfShots.Add(TShot.Create(                     // Create
(Xpos+Unitsize/2) + FWeapons[Weapon].RelX (cos(FWeapons[Weapon].SetAlpha + QAngle) * 
FWeapons[Weapon].Hypotenuse),  // PosX
(Ypos+Unitsize/2) + FWeapons[Weapon].RelY (sin(FWeapons[Weapon].SetAlpha + QAngle) * 
FWeapons[Weapon].Hypotenuse),  // PosY
(ToX / StepsNeeded),(ToY / StepsNeeded),QAngle,   // Various
FWeapons[Weapon].UnitBullet,                      // UnitBullet
FWeapons[Weapon].ATK,                             // Damage
OnUnit));


lieber dass hier:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
NewRelX:=(cos(FWeapons[Weapon].SetAlpha + QAngle) * FWeapons[Weapon].Hypotenuse)
NewRelY:=(sin(FWeapons[Weapon].SetAlpha + QAngle) * FWeapons[Weapon].Hypotenuse)
ListOfShots.Add(TShot.Create(                     // Create
(Xpos+Unitsize/2) + NewRelX,  // PosX
(Ypos+Unitsize/2) + NewRelY,  // PosY
(ToX / StepsNeeded),(ToY / StepsNeeded),QAngle,   // Various
FWeapons[Weapon].UnitBullet,                      // UnitBullet
FWeapons[Weapon].ATK,                             // Damage
OnUnit));


Begründung:
Die Alten Relativen Koordinaten X und Y stecken in Hypotenuse und altem Winkel. Du brauchst aber die neuen Relativen Koordinaten.


Um weiteren Fehlersuche lass dir doch mal die berechnten Koordinaten ausgeben, z.B. farbige Kreise dort setzten wo die Waffen sein sollten und dann gucken ob die Kreise sich mit dem Fahrezug korrekt mitbewegen.
1. Schritt: Fahrzeug horizontal und vertikal verschieben -> nicht drehen. Folgenden die Kreise korrekt ist die Mittelpunktberechnung korrekt.
2. Schritt Fahrzeug nur drehen -> Bewegung der Kreise korrekt -> Relativ koordinaten korrekt berechnet.

Noch ein kleiner Hinweis: Du hast Die doppelten Code. Für jeden Waffentyp berechnest du die Parameter separat.
Besser sind hier Zwischenvariablen vor der Case-Anweisung. Vorteil: Sollte in den Parameterberechnungen ein Fehler sein muss dieser nur an einer Stelle behoben werden.

Ich hoffe ich konnte helfen.

Für diesen Beitrag haben gedankt: knittel
knittel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 71
Erhaltene Danke: 2

Win XP, Win7, openSUSE
Delphi 7
BeitragVerfasst: Fr 10.12.10 14:56 
Vielen Dank! Das ist sehr ausführlich. Ich denke das kann mir bestimmt helfen. Leider kann ichs immoment grade nicht ausprobieren, weil nach einem Antivir Update plötzlich Andorra 2D sich nicht mehr initalisieren lässt. Hab schon im Sourceforge Andorra 2D Forum nachgefragt. Ich hoffe ich kann bald weiter arbeiten und deine Tipps nutzen. :)

Danke nochmal.

_________________
"Wir können nicht fliehen!" "Wieso nicht?" "Sie haben mir die Schnürsenkel zusammengebunden!" "Die Schweine."