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

28.09.2011, 23:40

Wand erstellen (Kollisionsabfrage)

Hallo Leute!
Seit ein paar Tagen hänge ich beim Spiel an einer Stelle fest. Ich habe vor eine Wand zu erstellen, aber das Programm will nicht so wie ich will :D .
Und zwar soll der Spieler von einer Seite der Wand nicht durchkommen (z.b. links).

Die 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
// CheckCollision
//
// Aufgabe: Kollision überprüfen
//
void CGame::CheckCollision ()
{
    // Iterator der Listen laden
    list<CFloor>::iterator ItFloor = m_FloorList.begin ();

    // Rect laden
    SDL_Rect RectPlayer;
    SDL_Rect RectFloor;

    // Alle Boden-Instanzen durchlaufen
    while (ItFloor != m_FloorList.end () )
    {
        // Rect holen
        RectPlayer = m_pPlayer->GetRect ();
        RectFloor = ItFloor->GetRect ();

        // Kollision zwischen Spieler und Boden abfragen
        // RectPlayer.y = der obere Rand, RectPlayer.x = der linke Rand
        if (RectPlayer.y < RectFloor.y + RectFloor.h &&
            RectPlayer.y + RectPlayer.h > RectFloor.y &&
            RectPlayer.x < RectFloor.x + RectFloor.w &&
            RectPlayer.x + RectPlayer.w > RectFloor.x)
        {
            // Hier komme ich nicht weiter
        }

        ItFloor++;
    }
    
} // CheckCollision


Ich bin über jede Hilfe dankbar.

Mit freundlichen Grüßen
Tramt

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

2

29.09.2011, 15:16

Naja erst mal zwei Anmerkungen zu deinem Code.

C-/C++-Quelltext

1
RectPlayer = m_pPlayer->GetRect ();
kannst du vor die Schleife schieben. Du musst es nicht in jedem Schleifendurchlauf neu setzen, es sei denn, es ändert sich hier dran was, im Schleifendurchlauf, wovon ich nicht ausgehe.
Dann deine Kollisionsabfrage. Bei dir wird nur eine Kollision festgestellt, wenn RectPlayer komplett innerhalb von RectFloor liegt. Deine eigentliche Frage musst du noch mal erläutern. Du willst jetzt wissen, wie du löst, dass man nicht durch Wände gehen kann?
Es sieht für mich so aus, als wenn du eine Tilemap umsetzen möchtest. Die Welt besteht aus vielen Rects. Dabei ist jedes Rect dann ein Wandstück, oder ein Bodenstück oder was auch immer. Wenn du so etwas haben willst, dann benutz mal die Suchfunktion des Forums. Hier sind einige Themen zu TileBased-Maps. Google wird dir da auch weiter helfen.
„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.“

3

29.09.2011, 15:46

Vielen Dank, werde ich machen.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

4

29.09.2011, 17:18

Also lag ich richtig mit deinem TileBased-Ansatz? Ansonsten gibt es natürlich noch andere Ansätze. Man kann auch einzelne Objekte halten. So hat man zum Beispiel eine Liste für alle Wände und überprüft nun mit diesen auf Kollision. Dann gehst du einfach diese Objekte durch und prüfst einfach dagegen. Lede Wand könnte dann zum Beispiel durch eine Linie dargestellt werden oä. Jedoch sind Tile-Maps meiner Meinung nach sehr einfach umzusetzen und vielleicht solltest du es erst mal damit versuchen.
„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.“

5

29.09.2011, 17:43

Eine Liste für die Wände habe ich bereits erstellt.

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// LoadFloor
//
// Aufgabe: Boden laden
//
void CGame::LoadFloor ()
{
    // Falls die Objekte noch nicht geladen sind sie laden,
    // andernfalls Sperren
    while (m_bLoadObjectLock != true)
    {
        // Neuer Boden
        CFloor Floor;

        // Boden Initialisiren
        // und in Liste einfügen
        Floor.Init (m_pSpriteFloor, 100.0f, 100.0f);
        m_FloorList.push_back (Floor);

        Floor.Init (m_pSpriteFloor, 200.0f, 100.0f);
        m_FloorList.push_back (Floor);

        Floor.Init (m_pSpriteFloor, 300.0f, 100.0f);
        m_FloorList.push_back (Floor);

        Floor.Init (m_pSpriteFloor, 400.0f, 100.0f);
        m_FloorList.push_back (Floor);

        // Vor Sprite-Überladung schützen (Laden Sperren)
        m_bLoadObjectLock = true;

    }

} // LoadFloor


// RenderFloor
//
// Aufgabe: Boden Rendern
//
void CGame::RenderFloor ()
{
    // Iterator für die Boden-Liste
    list<CFloor>::iterator It;

    // Boden-Liste durchlaufen
    for (It = m_FloorList.begin (); It != m_FloorList.end (); ++It)
    {
        // Boden rendern
        It->Render ();

    }
    
} // RenderFloor


Kannst du mir sagen wie du die Kollisionsabfrage ungefähr machen würdest?

Im Buch gab es ja ein Beispiel, damit das Raumschiff nicht außerhalb des Bildschirms landet

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// CheckPosition
//
// Aufgabe: Position und Animationsphase prüfen
//
void CPlayer::CheckPosition ()
{
  // Linker und rechter Rand
  if (m_fXPos < 0.0f)
    m_fXPos = 0.0f;
  else if (m_fXPos > 752.0f)
    m_fXPos = 752.0f;

  // Animationsphase prüfen
  if (m_fAnimPhase < 0.0f)
    m_fAnimPhase = 0.0f;
  else if (m_fAnimPhase > 10.0f)
    m_fAnimPhase = 10.0f;

} // CheckPosition


Kann ich allerdings so nicht umsetzen.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

6

29.09.2011, 18:12

Du verstehst da was falsch. In deiner Version hast du Bodenkacheln in deiner Liste. Eine Wand ist aber nun kein Boden, oder versteh ich dich da grad falsch? Ich würde also eine Klasse für Objekte oder Wände oder was auch immer anlegen. Und wenn du deinen Spieler dann bewegen willst, prüfst du einfach, ob der Spieler nach der Bewegung mit einer der Wände, bzw. mit einem der Objekte kollidiert. Wenn dass der Fall ist, wird der Spieler dann nicht bewegt. Wenn keine Kollision vorhanden ist, wird der Spieler bewegt. Wenn deine Spielwelt jetzt aber eh nur aus Kacheln besteht, dann ist ein Ansatz mit Tiles vermutlich einfacher. Dann kachelst du deine ganze Welt. Je nach Kachelart, kann man die Kachel betreten oder halt eben nicht. Hier baust du dir deine Wände dann aus einer Reihe von Kacheln zusammen. Du hast sicherlich mal Legend of Zelda auf dem GameBoy oder dem Super Nintendo oä gespielt. Oder Pokemon auf dem Gameboy. Bei diesen Spielen ist die Welt auch in Kacheln aufgeteilt.
Wie du dann auf eine Kollision prüfst sollte nicht schwer sein. Für die Variante, mit Wänden in einer Liste, könntest du zum Beispiel wieder mit Rechtecken überprüfen, ob sich diese schneiden. Dafür hattest du ja schon einen Ansatz, der ein bisschen berichtigt werden müsste. TileBased-Maps prüfen dann die Kollision nur mit den Tiles, auf denen sich dein Spieler zur Zeit befindet und nicht mehr mit jeder Wand. Du musst dich also möglichst für eine Variante entscheiden. Ich kenne das Buch jetzt nicht, gehe aber davon aus, dass Heiko wohl darauf eingehen wird. Vielleicht solltest du es sonst erst weiter durcharbeiten und deine Probleme lösen sich von selbst.
„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.“

7

30.09.2011, 19:03

OK, ich werde etwas mit der Methode rumprobieren :)

Werbeanzeige