Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Sc4v

Alter Hase

  • »Sc4v« ist der Autor dieses Themas

Beiträge: 376

Beruf: Student

  • Private Nachricht senden

1

29.09.2011, 19:18

2D: Isometrischer Schuss

Hi Leute,

ich entwickel seit einiger Zeit einen kleinen isometrischen 2D Shooter (wird noch umfangreicher vorgestellt) mit SFML. Bin jetzt an dem Punkt angelangt an dem ich den Schuss des Spielers zeichnen will. Ich habe die letzte Zeit viel rumprobiert und mir auch die mathematische Grundidee erarbeitet. Bei der Umsetzung stoße ich jedoch auf einige Probleme. Vielleicht habe ich in meiner Idee auch einen Denkfehler. Am besten bebilder ich meine derzeitige Vorgehensweise zunächst:

Drückt der Spieler auf die linke Maustaste erscheint ein Schuss sprite auf Höhe der Pistole:

(Link)

Nun setze ich den geometrischen Ursprung des Schusses, also den Origin, auf den Spieler


(Link)


Nun erstelle ich einen Richtungsvektor des Schusssprites mit x=1 und y=0, sowie einen Richtungsvektor direction vom geometrischen Ursprung des Schusses zur Mausposition
Der Winkel Alpha zwischen diesen beiden Vektoren ist der Rotationswinkel des Sprites


(Link)


Und dann wird das Schusssprite um den geometrischen Ursprung gedreht

(Link)


Soweit die Theorie.
Allerdings rotiert sich der Schuss nicht immer in die richtige Richtung und fliegt auch nicht immer in Richtung Fadenkreuz und wenn doch dann eher an diesem vorbei.
Hier einige Codeausschnitte:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//in class Level 

private:
Player* actualPlayer;

//....

//Beim Mausklick:
levelContent.push_back(new Shot(25,
                                            actualPlayer->actualSprite->GetPosition().x,
                                            actualPlayer->actualSprite->GetPosition().y,
                                            sf::Mouse::GetPosition()));

//LevelContent ist eine std::list<Object*> die sich immer richtig sortiert, damit die Objekte in richtiger Reihenfolge gerendert werden, also zB hinter oder vor einen Baum
//Alle gezeichneten Elemente, also Player, Bäume oder auch Schüsse sind irgendwie von Object abgeleitet. Gebrauche hier viel Polymorphismus
//25 ist hier nur die Stärke des Schusses also total irrelevant


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//in class Shot
//Konstruktor

//...

sprite.SetOrigin(-59,0);
//der Schuss wird 59 pixel rechts neben dem Spieler(ursprung) gerendert

fDirection.x = mousePos.x - playerCenterX;
fDirection.y = mousePos.y - playerCenterY;
fDirection = normalize(fDirection);
//playerCenter ist der Origin

float ang = angle(fDirection,sf::Vector2<float>(1.0,0.0));
    if(fDirection.y < 0.f)
        ang *= -1;  //Keine Ahnung ob das Sinn so macht
sprite.Rotate(ang);


C-/C++-Quelltext

1
2
3
//bewegungsfunktion des Schusses
sprite.Move(fSpeed*fDirection*fTime);
//fTime ist hierbei: sf::RenderWindow.getFrameTime() / 1000.f


Vielleicht auch noch interessant:

C-/C++-Quelltext

1
2
3
4
5
float Shot::angle(sf::Vector2<float> first, sf::Vector2<float> second)
{
    return acos((first.x * second.x + first.y * second.y) / 
                (sqrt(pow(first.x,2) + pow(first.y,2)) * sqrt(pow(second.x,2) + pow(second.y,2)))) * 180.0f / 3.14159265f;
}


C-/C++-Quelltext

1
2
3
4
5
sf::Vector2<float> Shot::normalize(sf::Vector2<float> vector)
{
    float f = sqrt(pow(vector.x,2) + pow(vector.y,2));
    return sf::Vector2<float>(1/f * vector.x, 1/f * vector.y);
}




Ich weiß nicht genau wo ich einen Fehler mache und genauso wenig weiß ich ob meine Idee stimmt oder diese verständlich ist.

Vielleicht kann mir ja einer helfen ^^

Lg und Danke schonmal

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

2

29.09.2011, 19:49

Ist jetzt etwas schwer zu erklären. Bin mir grad auch bei den Mathematischen Grundlagen nicht 100% sicher. Acos ist periodisch, dass heisst ab einem bestimmten Punkt wiederholt sich die Funktion. Das sind immer 180° Schritte. Dein Winkel wird vermutlich für einen Halbkreis stimmen und für die andere Hälfte nicht. Das Problem sollten die y-Werte darstellen. Du hast ja 2 Punkte first und second. Du musst quasi unterscheiden ob first.Y < second.Y und je nachdem dann den Winkel anpassen. In dem Fall, das der Winkel falsch ist, müsste ein Vorzeichenwechsel reichen. Also einfach * -1. Ich hoffe ich habe jetzt nicht völligen quatsch erzählt. Habe jetzt nicht noch mal genauer nach gesehen.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Sc4v

Alter Hase

  • »Sc4v« ist der Autor dieses Themas

Beiträge: 376

Beruf: Student

  • Private Nachricht senden

3

29.09.2011, 19:53

deswegen hab ich im Quellcode das hier stehen:

C-/C++-Quelltext

1
2
if(fDirection.y < 0.f)         
ang *= -1;  //Keine Ahnung ob das Sinn so macht


hab ich deswegen gemacht, weil es nur für den unteren Halbkreis einigermaßen (wenn auch schlecht) funktioniert hat.
mhhh trotzdem danke =)

//edit
Vielleicht liegts auch an der rotate() funktion von sf :: Sprite... oder so?

BurningWave

Alter Hase

Beiträge: 1 106

Wohnort: Filderstadt/Konstanz

Beruf: Student

  • Private Nachricht senden

4

29.09.2011, 20:13

Ich bin mir nicht sicher, aber kann es sein, dass acos den Winkel im Bogenmaß zurückliefert und sprite.Rotate() das Gradmaß erwartet?

Sc4v

Alter Hase

  • »Sc4v« ist der Autor dieses Themas

Beiträge: 376

Beruf: Student

  • Private Nachricht senden

5

29.09.2011, 20:16

das ist auch tatsächlich so, deswegen multipliziere ich das Ergebnis von acos ja auch mit 180.0f / 3.14159265f 8)

BurningWave

Alter Hase

Beiträge: 1 106

Wohnort: Filderstadt/Konstanz

Beruf: Student

  • Private Nachricht senden

6

29.09.2011, 20:31

OK, habe ich übersehen. Wie sieht es mit Rundungsfehlern aus? Hast du deine Formel schonmal zerlegt und Schritt für Schritt debuggt?

Sc4v

Alter Hase

  • »Sc4v« ist der Autor dieses Themas

Beiträge: 376

Beruf: Student

  • Private Nachricht senden

7

29.09.2011, 20:52

hab mal ein wenig ausprobiert...
rundungsfehler gibts wohl keine und der Debugger hilft mir da leider auch nicht wirklich.
Wenn ich mit meiner Figur ein wenig in der Welt rumlaufe gibt es immer eine Stelle bei der es funktioniert.. bei anderen jedoch nicht.
Da ich eine sf::View benutze wird es hier irgendwelche Probleme geben...vermute ich...
Wenn ich die Figur weiter nach rechts bewege wird der Winkel steiler, nach links flacher. Mhhhh
was trotz allem auf keinen Fall stimmt ist die Ausrichtung des Schusses... also das Rotieren misslingt irgendwie trotz anscheinend korrektem Winkel.
Habe ich vielleicht irgendwie die setOrigin() Funktion falsch verstanden?
Ohne setzen des Origins spawned der Schuss näher am Spieler ... 8|

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

8

29.09.2011, 21:38

Da habe ich eine Vermutung. Wenn du deine Sicht durch eine View änderst, musst du auch bei den Koordinaten umrechnen. Ich bin mir nicht sicher, wie es bei SFML abläuft, aber ich gehe davon aus, dass die Maus immer in Bildschirmkoordinaten angegeben wird. Das heisst, Ursprung ist immer oben links. Die Position deines Spielers ist jetzt aber nicht mehr relativ zum Bildschirmursprung gesehen, sondern um die View verschoben. Das heisst, du musst zwischen beiden Systemen umrechnen.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Sc4v

Alter Hase

  • »Sc4v« ist der Autor dieses Themas

Beiträge: 376

Beruf: Student

  • Private Nachricht senden

9

29.09.2011, 21:49

Ich habs geschafft... Daran lags auch tatsächlich allerdings habe ich die Maus Koordinaten jetzt in View Koordinaten umgerechnet.
Schorchs Antwort kam allerdings nachdem ich das gemacht habe aber trotzdem super herzlichen Dank auch euch! :thumbsup:

Jetzt klappts astrein... die nächsten Tage stell ich mein Spiel mal unter Projekte vor ;)

lg Sc4v

Werbeanzeige