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

Geheim

Treue Seele

  • »Geheim« ist der Autor dieses Themas

Beiträge: 202

Wohnort: Salzburg

Beruf: Schüler

  • Private Nachricht senden

1

03.12.2011, 23:07

SFML Kollisionserkennung für Plattformen

Hallo Leute,

Ich hab ein nerviges Problem mit meinem kleinem TestSpiel. Ich hoffe die Überschrift passt halbwegs^^
Ich habe eine Spieler und Hindernisse! Der Spieler kann sich frei bewegen und springen und soll natürlich an den Hindernissen vorbei!
Aber, ich weiß nicht wie ich das genau programmieren muss, um wenn ich oben draufspring dass ich dann oben bleibe, wenn ich von unten draufspring "abpralle" und wenn ich rechts oder links dagegen laufe nicht weiter kann. (Einzeln gehts ja, aber nicht zusammen^^)
Habs soweit geschafft dass alles geht, bis auf wenn ich wieder runterfalle und mich nach links oder rechts bewege: Dann werde ich entweder nach oben oder unten "teleportiert" xD Also GetFall() = ein float der sagt wie schnell ich falle & GetOben() hab ich true gemacht wenn man eben oben drauf springt.

Das ist mein Code dafür:

C-/C++-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
for(i=vDaten.begin();i!=vDaten.end();++i)   //KOLLISIONSKONTROLLE (WICHTIG!)
        {
            if((_Player->GetPosition().x + _Player->GetBreite() > (*i).GetPosition().x) &&
                (_Player->GetPosition().x < (*i).GetPosition().x + (*i).GetBreite()) &&
                (_Player->GetPosition().y + _Player->GetHoehe() > (*i).GetPosition().y) &&
                (_Player->GetPosition().y < (*i).GetPosition().y + (*i).GetHoehe()))
            {
                if((_Player->GetPosition().y + _Player->GetHoehe() < (*i).GetPosition().y + (*i).GetHoehe()) && _Player->GetFall() >= 0)
                {
                    _Player->SetPosition(_Player->GetPosition().x, (*i).GetPosition().y - _Player->GetHoehe());
                    _Player->SetSpringen(false);    //Wenn man OBEN drauffällt!!!
                    (*i).SetOben(true);
                }

                if(_Player->GetPosition().y > (*i).GetPosition().y) //Wenn man von UNTEN springt!!!
                {
                    _Player->SetPosition(_Player->GetPosition().x, (*i).GetPosition().y + (*i).GetHoehe());
                    _Player->SetSpringen(true);
                    (*i).SetOben(true);
                }

                if((_Player->GetPosition().x + _Player->GetBreite() < (*i).GetPosition().x + (*i).GetBreite()) && (*i).GetOben() == false)
                    _Player->SetPosition((*i).GetPosition().x - _Player->GetBreite(), _Player->GetPosition().y); //LINKS dagegen!!!

                if((_Player->GetPosition().x > (*i).GetPosition().x) && (*i).GetOben() == false)    //RECHTS dagegen!!!
                    _Player->SetPosition((*i).GetPosition().x + (*i).GetBreite(), _Player->GetPosition().y);

                (*i).SetOben(false);
            }
        }


Ich weiß, dass ich es sicher ganz falsch angegangen bin, aber ich hab solange schon rumprobiert und weiß echt nicht mehr weiter!

Wär subba wenn ihr wisst was mein Problem ist und ihr mir weiterhelfen könnt!

MfG Geheim!

2

04.12.2011, 21:08

Oder ein 11-Jahre altes Kind was es 'cool' findet hier zu nerven.

MfG
Check

Crazy007

Treue Seele

Beiträge: 186

Wohnort: Tirol

  • Private Nachricht senden

3

04.12.2011, 22:41

Entschuldigung wenn ich was falsch gemacht habe aber ich habe eigendlich ganichts gepostet
Ich weiß nicht einmal was ich geschrieben habe
Sorry
Der Error sitzt meistens vor dem Bildschirm! :D

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

4

05.12.2011, 12:30

Kurzer Blackout? :D Ich hab nicht gesehen was hier abgelaufen ist aber gut. Mal zurück zum Thema. Ich habe deinen Code grad aus Zeitgründen nur überfliegen können. Er sieht aber relativ kompliziert aus. Ich vermute du möchtest ein Jump 'n' Run machen? Ich finde es dort oft einfacher, wenn man die Bewegung auf beiden Achsen einzeln betrachtet. Du bewegst den Spieler zum Beispiel erst auf auf der Y-Achse, und dann auf der X-Achse. Das könntest du zum Beispiel so angehen:
Du fragst die Steuerung ab. Dann überprüfst du ob du kollidierst, wenn du deine Position auf der Y-Achse verschiebst. Wenn es zu einer Kollision kommt, machst du die Verschiebung Schrittweise Rückgängig, bis keine Kollision mehr vorhanden ist.
pos = Spielerposition
y_bewegung
while pos + y_bewegung = kollision
y_bewegung--;

Wobei das jetzt nur als Pseudocode zu sehen ist;) Genau so funktioniert es natürlich nicht. Wenn das erledigt ist, dann machst du das selbe für die X-Achse. Ob du nun nach oben springst oder nach unten fällst ist eigentlich erst mal egal. Nach einer Kollision guckst du einfach, ob du grad springst und lässt den Spieler danach fallen, damit er nach unten abprallt.
„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.“

Geheim

Treue Seele

  • »Geheim« ist der Autor dieses Themas

Beiträge: 202

Wohnort: Salzburg

Beruf: Schüler

  • Private Nachricht senden

5

05.12.2011, 18:57

Hey Schorsch,

Danke für deine Antwort!
Also ich weiß genau was du meinst und ich weiß dass es auch so funktioniert, nur bin ich immer noch dran das umzusetzen^^
Hab nämlich die Hindernisse und den Spieler in verschiedenen Klassen und vergleiche die Kollision wieder in einer anderen...
Aber ich denk mal jetz schaff ichs ;) Wenn nicht werd ich wohl wieder deinen Rat brauchen :thumbsup:

MfG Geheim!

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

6

05.12.2011, 19:42

Das ist ja auch alles an sich kein Problem. Du musst ja nur dafür sorgen, dass die Klasse die die Kollision berechnet, alle nötigen Informationen bekommt. Ich denke auch dass du das schon schaffen wirst;) Ansonsten einfach fragen.
„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.“

Geheim

Treue Seele

  • »Geheim« ist der Autor dieses Themas

Beiträge: 202

Wohnort: Salzburg

Beruf: Schüler

  • Private Nachricht senden

7

05.12.2011, 19:54

Ja die Infos besorgen ist nicht schwer, aber ich hab noch nicht ganz den Durchblick, weil die Kollisionsabfrage ja "nur" die 4 ecken erkennt?
Und wenn mein Spieler auf der Y-Achse "kollidiert" dann tut er das auch, wenn er auf der X-Achse "kollidiert" ? Wie soll man denn ohne der Y-Achse wissen, ob der Spieler überhaupt das Hindernis berühren? Verstehst du mein Problem?^^ Dann setz ich auch, wenn ich nicht genau von oben oder unten komme die Position für die Y-Achse?^^
Bräuchte nur mal den Denkansatz pls, will nicht dass du mir den Code postest und ich checks dann nicht ;)

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

8

05.12.2011, 20:26

Du hast da glaube ich etwas falsch verstanden. Die Idee ist, die neue Position zu berechnen und im Falle einer Kollision, langsam von der neuen Position zur Ausgangsposition zurück zu gehen. Das macht man so lange, bis keine Kollision mehr vorhanden ist. Das muss dir erst mal bewusst werden. Jetzt splittet man die Bewegung in 2 Parts auf.
Du bewegst deine Figur nur auf der X-Achse. Das wäre quasi nach links oder nach rechts laufen. Dabei änderst du an der Position von deinem Spieler halt nur den X-Wert. Jetzt überprüfst du ob der Spieler mit irgendeinem Objekt kollidiert. Wenn das der Fall ist, dann wird schrittweise zur Ausgangsposition zurück bewegt, bis keine Kollision mehr vorhanden ist. Danach machst du das gleiche für die Y-Achse.
Danach hast du dann deine gewünschte Position für den Spieler. Um eine Kollision zu erkennen gibt es viele Möglichkeiten. Zum Beispiel über die Eckpunkte, wie du schon richtig erkannt hast.
Wenn du einen Ansatz wählst, wie ich ihn hier beschrieben habe, musst du dir bei der Kollisionserkennung keine Gedanken machen, von wo ein Spieler kommt. Du berechnest einfach ob der Spieler mit der Welt kollidiert. Du kannst quasi die gleiche Kollisionserkennung für beide Fälle benutzen.
„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.“

Geheim

Treue Seele

  • »Geheim« ist der Autor dieses Themas

Beiträge: 202

Wohnort: Salzburg

Beruf: Schüler

  • Private Nachricht senden

9

06.12.2011, 22:15

So ich hab mein Problem dank Schorsch gelöst!
Für alle die, die ein ähnliches oder dasselbe Problem haben gibt es hier nochmal den kompletten Code für die Kollisionskontrolle für Plattformen^^

Also zuerst wird die X-Position neu gesetzt, heißt dass man sich schon vorher ausrechnet wie die neue X-Position sein wird!
Danach wird geprüft, ob die NEUE X-Position mit einem Hindernis, Boden, Plattform, ect. kollidiert.
Wenn JA, dann setzt man die NEUE X-Position solange zurück, bis es zu keiner Kollision mehr kommt.
(Natürlich muss man darauf achten wie man zurücksetzt! Dürfte aber kein Problem sein?^^)

Wichtig! Dann wird die Position des Spielers gesetzt! (und zwar die Position = die vorher zurechtgemachte "neue" Position)

Danach wird die Y-Position neu gesetzt und man prüft wieder, ob die NEUE Y-Position kollidiert!
Wenn JA, setzt man auch die Position solange zurück bis nix mehr kollidiert.

Wichtig! Nochmal die Position des Spielers setzen!

Ich hab manches Fett gedruckt, weil man da besonders aufpassen sollte um keine blöden Fehler zu bekommen! Mein größtes Problem war, dass ich anstatt der neuen Position die alte zurückgesetzt hab^^ Das erziehlt nicht das was man will!^^ Also für alle die auch denselben Feher haben ;)

Hier jetz der Code:

C-/C++-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
_Player->NewXPosition();    //Man holt sich die neue X_Position

        for(i=Vektor.begin();i!=Vektor.end();++i)   //Kollisionskontrolle für die X-Position
        {
            while(Collision((*i).GetPosition().x, (*i).GetPosition().y, (*i).GetWidth(), (*i).GetHeight()) == true)
            {
                if(_Player->GetNewPosition().x > _Player->GetPosition().x)  //Wenn die X-Achse schneidet
                    _Player->Move(0.1f, 0);     //Die Werte zurücksetzen
                else
                    _Player->Move(-0.1f, 0);    //0.1 ist viel genauer als 1 oder 0.5
            }
        }
        _Player->SetNewPosition();  //Man setzt den Spieler (die X-Position)
        _Player->NewYPosition();    //Man holt sich die neue Y_Position

        for(i=Vektor.begin();i!=Vektor.end();++i)       //Kollisionskontrolle für die Y-Position
        {
            while(Collision((*i).GetPosition().x, (*i).GetPosition().y, (*i).GetWidth(), (*i).GetHeight()) == true)
            {
                if(_Player->GetNewPosition().y > _Player->GetPosition().y)  //Dasselbe für die Y-Achse
                {
                    _Player->Move(0, 0.1f);
                    _Player->SetJump(false);    //Wenn man OBEN drauf ist, darf man wieder springen
                }
                else
                {
                    _Player->Move(0, -0.1f);
                    _Player->SetJump(true);     //Wenn man nur unten dagegenkracht natürlich nicht
                }
            }
        }
        _Player->SetNewPosition();  //Man setzt den Spieler (die Y-Position)


Falls jemand nicht genau weiß wie man eine Kollisionsabfrage macht hier ist mein Vorschlag:

C-/C++-Quelltext

1
2
3
4
5
6
7
bool Funktion::Collision(float PosX, float PosY, float Width, float Height)
{
return _Player->GetNewPosition().x < PosX + Width  &&
PosX < _Player->GetNewPosition().x + _Player->GetWidth()  &&
_Player->GetNewPosition().y < PosY + Height &&
PosY < _Player->GetNewPosition().y + _Player->GetHeight();
}


Falls ich etwas falsch gemacht habe oder sehr umständlich pls sagen, möcht mich gern verbessern!
Sonnst hoff ich mal, dass euch das vielleicht weiterhelfen kann?! Danke nochmal an Schorsch, der es mir erklärt hat^^

MfG Geheim!

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Geheim« (06.12.2011, 22:23)


Werbeanzeige