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

1

12.11.2008, 22:57

2D Kollision

Hallo, hab ein Problem bei einer Kollisionserkennung von 2D Objekten.

Das erste Objekt wird in die Liste geschoben. Sobald eine Kolission stattfindet verschwindet das Objekt, wenn jetzt aber mehrere Objekt e erscheinen (ab ca. 2-3) Kollidieren sie nicht richtig und machen was sie wollen.
Hier mal der Quellcode von der Kollisionsabfrage:

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
33
34
// ****** Check Collisions (Kollisionen überprüfen und entsprechender Wert zurückgeben) ****** //

        // Iteratoren für den Enemy holen

        list<CEnemies>::iterator ItEnemy = EnemyListDown.begin();

        // Rects für die Enemies und den Player erzeugen

        SDL_Rect RectEnemy;
        SDL_Rect RectPlayer;

        // Alle Enemies durchlaufen

        while (ItEnemy != EnemyListDown.end()) 
        {                   
            // Rects für die Enemies und den Player holen

            RectEnemy  = ItEnemy->GetRect();
            RectPlayer = pPlayer->GetRect();

            // Kollisionserkennung für alle Enemies durchführen

            if (RectPlayer.x + RectPlayer.w > RectEnemy.x &&
                RectPlayer.x < RectEnemy.x + RectEnemy.w  &&
                RectPlayer.y + RectPlayer.h > RectEnemy.y &&
                RectPlayer.y < RectEnemy.y + RectEnemy.h)
            {
                // Es gab eine Kollision

                cout << "\a";

                // Enemy deaktivieren

                ItEnemy->SetAlive(false);
            }

            // Enemy löschen falls deaktiviert

            if (ItEnemy->IsAlive())
                ItEnemy++;
            else
                ItEnemy = EnemyListDown.erase(ItEnemy);                 
        }

K-Bal

Alter Hase

Beiträge: 703

Wohnort: Aachen

Beruf: Student (Elektrotechnik, Technische Informatik)

  • Private Nachricht senden

2

12.11.2008, 23:13

Zitat


Quellcode

1
2
3
4
5
// Kollisionserkennung für alle Enemies durchführen
            if (RectPlayer.x + RectPlayer.w > RectEnemy.x &&
                RectPlayer.x < RectEnemy.x - RectEnemy.w  &&
                RectPlayer.y + RectPlayer.h > RectEnemy.y &&
                RectPlayer.y < RectEnemy.y - RectEnemy.h)


Müsste es nicht so heißen? Also in der zweiten und vierten Zeile jeweils ein Minus? So ganz ist mir noch nicht klar was du genau überprüfst aber ich kenne mich auch nicht mit SDL aus. Ist SDL_Rect.w und SDL_Rect.h die halbe oder die gesamte Kantenlänge?

3

12.11.2008, 23:22

Was darf man sich unter kollidieren nicht richtig vorstellen?

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

4

13.11.2008, 09:42

Schau doch mal mit dem Debugger duch. Der Code ist, wenn ich mich richtig erinnere aus Heikos Buch und sollte ja in Ordnung sein..

Stimmen den die Positionen der Rects?

5

13.11.2008, 12:02

Ja, die Positionen der Rects sollte ich nochmal überprüfen aber die müssten ja stimmen, denn bei ersten Enemy stimmen sie ja auch ...

achja, SDL_Rect.w und .h ist einfach die Höhe und Breite des Rects.

Zitat von »"Genion"«

Was darf man sich unter kollidieren nicht richtig vorstellen?


Der Enemy CEnemyList.begin (also 0) Kollidiert richtig. Enemies die 2. oder höher aus der Liste sind kollidieren nur wenn

C-/C++-Quelltext

1
2
RectPlayer.x == RectEnemy.x &&
Rectplayer.y + RectPlayer.h > RectEnemy.y + RectEnemy.h


also wenn der Spieler auf der selben X-Achse wie der Enemy ist und wenn die Unterkante vom Player unterhalb von der Unterkante vom Enemy ist.
Das ist eigentlich totaler Schwachsinn, aber genau das passiert.

// Edit: Ich glaub ich weiß wo der Fehler ist: In der Zeit. Umso kürzer die Spawn Zeit desto umgenauer um Schwachsinniger die Kollisionen.
Jetzt muss ich nur noch schaun wie ich den fehler beheb.

K-Bal

Alter Hase

Beiträge: 703

Wohnort: Aachen

Beruf: Student (Elektrotechnik, Technische Informatik)

  • Private Nachricht senden

6

13.11.2008, 16:46

Ich glaube du musst auch nicht in jedem Iterationsschritt das PlayerRect aktualisieren.

7

13.11.2008, 17:20

Sooo, ich glaub ich hab den Fehler gefunden, weiß aber noch nicht wie ich ihn behebe. Ich erzeug von CEnemies für jede Richtung indenen die Gegner kommen eine neue Instanz. Wenn ich jetzt einfach mal die Gegner die von rechts nach links und von unten nach oben kommen auskommentiere funktioniert plötzlich die Kollisionserkennung Reibungslos.
Ich vermute das es kein Zufall sein kann, dass die Rects, die von x-- und y-- kommen den Fehler verursachen und vlt die Rects die von x++ und y++ kommen beeinflussen. Da ich aber von alle verschiedene Instanzen hab kann ich mir das nur schwer vorstellen:

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
33
// Nach einer Sekunde neue enemies von oben spawnen

        if (fEnemyTimer >= 2.0f)
        {

            // Es gab eine Kollision

                cout << EnemyListDown.size() << endl;;

            // Neue Enemies

            CEnemies EnemyDown;
            CEnemies EnemyLeft;
            CEnemies EnemyRight;
            CEnemies EnemyUp;

            // Zufällige XPos

            int XPos = rand()%730;
            // Zufällige YPos

            int YPos = rand()%530;

            // Enemies initialisieren

            EnemyDown.Init(pEnemy, static_cast<float>(XPos), -60.0f);
            EnemyRight.Init(pEnemy, -60.0f , static_cast<float>(YPos));
            EnemyLeft.Init(pEnemy, 860.0f , static_cast<float>(YPos));
            EnemyUp.Init(pEnemy, static_cast<float>(XPos), 660.0f);

            // Enemies in Liste einfügen

            EnemyListDown.push_back(EnemyDown);
            EnemyListRight.push_back(EnemyRight);
            //EnemyListLeft.push_back(EnemyLeft);

            //EnemyListUp.push_back(EnemyUp);


            // Zeit zurücksetzen

            fEnemyTimer= 0.0f;
        }

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

8

14.11.2008, 09:21

Hmm. Dann mach mal nur 1/2 Objekte, dann kannst du das besser beobachten mit dem Debuger.

Aber ich sehe da nicht so wirklich, was das Problem sein sollte.. Du hast nicht zufällig irgendwo was komisches mit unsigned gemacht, oder?

9

30.11.2008, 15:46

So, nach Tagen von verweifelten Versuchen meld ich mich mal wieder.

Der Fehler ist scheinbar verschwunden - tritt aber ab und zu noch auf. Und gerade das "ab und zu" versteh ich nicht. Wie kann ein Fehler nur "manchmal" auftreten?

Und wie können Objekte verschwinden die nur auf der Y Achse kollidieren, obwohl die Kollissionsabfrage das doch explizit ausschließt?

also ich komm echt nicht mehr weiter :(

Zitat von »"drakon"«

Hmm. Dann mach mal nur 1/2 Objekte, dann kannst du das besser beobachten mit dem Debuger.

Aber ich sehe da nicht so wirklich, was das Problem sein sollte.. Du hast nicht zufällig irgendwo was komisches mit unsigned gemacht, oder?


Nein, ich hab nichts mit unsigned gemacht.

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

10

01.12.2008, 08:20

Hmm. "Ab und zu" ist tatsächlich ein Problem. ;)

Da bleibt dir eigenlich nix anderes überig, als zuerst einmal sehr oft versuchen die Situation nachzustellen. (Da hilft ein sehr feiner Logger sehr viel,oder auch gleich Live-Daten). Und dann wenn du weisst, wie du den Fehler erzeugen kannst das ganze mal mit dem Debugger nachzustellen.

Hmm. Ich würde mal sagen, dass das ganze mit einem Fehler zu tun hat, der irgendwie 0 vermukst und darauf ev. einen extremen Wert macht und das Objekt somit zu verschwinden scheint. (Wird dann wohl eher irgendwo im Nirvana deines Screens rumschwirren..)

Werbeanzeige