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

25.01.2015, 16:31

C++ Kollisionsabfrage Problem

Guten Tag an die Community,

Im Sinne meines Abschlussprojektes programmiere ich ein 2D-Platformer mit Microsoft Visual Studio 2010, C++, Der Bibliothek "Allegro 4". Das ganze natürlich objektorientiert.

Ich habe folgendes Problem:

mit dieser Methode:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void Collision::LoadCollisionMap(const char *filename)
{
   ifstream openfile(filename);
   if(openfile.is_open())
   {
    openfile >> mapSizeX >> mapSizeY;
    while (!openfile.eof())
    {
    openfile >> ColMapFile[loadCounterX][loadCounterY];
    loadCounterX++;
    if(loadCounterX >= mapSizeX)
    {
        loadCounterX = 0;
        loadCounterY ++;
    }
    }
    loadCounterX = loadCounterY = 0;
     
   }
}


lade ich meine Map:

10 8
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0

in das zweidimensionale Array "ColMapFile[loadCounterX][loadCounterY]"
die ersten zwei Werte sollen inr mapSizeX und mapSizeY geladen werden.

Das funktioniert auch, da ich genau die selbe Logik angewandt habe, um meine Map mittels Tiles zu gestalten.

Nun zu dem Problem:

mit folgender Methode:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void Collision:: PlatformCollision(BITMAP *buffer, Player &player)
{
   for (int i = 0; i < mapSizeX; i++)
   {
    for (int j = 0; j < mapSizeY; j++)
    {
     
    if(ColMapFile[i][j] != 0)
    {
        if(player.y+player.animation->h<j*BlockSize || player.x > i*BlockSize+BlockSize || player.y > j*BlockSize+BlockSize || player.x+player.animation->w < i* BlockSize)
        {
        player.Platform = false;
         
        }
        else
        {
        player.Platform = true;
         
        }
    }
    }
   }   
}

prüfe ich das o.g. Array auf einsen, wenn eine gefunden wird, soll die oben zusehende if-Abfrage durchgeführt werden usw.

Auch das funktioniert soweit, ich habe aus Testzwecken erstmals ein einziges Tile, also eine einzige 1, geladen, die Kollisions-Erkennung funktionierte dann auch einwandfrei, aber sobald ich eine zweite eins in die Map packe, wird nur eine eins erkannt und auf Kollision überprüft. Es scheint mir so als würde sich mein Code immer auf die eins festlegen, welche am nächsten zum Spieler spawn ist.

Syntaktischer oder logischer Fehler?

schonmal vielen lieben Dank,
mit freundlichen Grüßen,
flohdieter

PROBLEM HAT SICH ERLEDIGT,
LÖSUNG WAR FOLGENDES:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void Collision:: PlatformCollision(BITMAP *buffer, Player &player)
{
player.Platform = false;
for (int i = 0; i < mapSizeX; i++)
{
for (int j = 0; j < mapSizeY; j++)
{

if(ColMapFile[i][j] != 0)
{
if(!(player.y+player.animation->h<j*BlockSize || player.x > i*BlockSize+BlockSize || player.y > j*BlockSize+BlockSize || player.x+player.animation->w < i* BlockSize))
{
player.Platform = true;

}

}
}
} 
}
[/i]

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »flohdieter« (25.01.2015, 19:33)


Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

2

28.01.2015, 15:17

Du kannst das ganze noch optimieren. Du iterierst über alle Tiles und prüfst dann für die 1er Felder ob sie den Spieler berühren. Du brauchst aber doch nur die Tiles zu durchlaufen die den Spieler wirklich berühren. Da du die Position und die Größe des Spielers kennst, sowie die Größe eines Tiles, kannst du dir daraus doch die passenden Tiles berechnen.
Als einfaches Beispiel um auf das Tile zu schließen welches sich direkt unter der Position vom Spieler befindet:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int tileWidth = 64;
int tileHeight = 64;

int playerX = 315;
int playerY = 649;
int playerWidth = 64;
int playerHeight = 128;


tileX = playerX / tileWidth;
tileY = playerY / tileHeight;

if(ColMapFile[tileX, tileY] != 0) {
    // Collision
}


Mithilfe der Größe des Spielers kannst du so alle Tiles die sich unter ihm befinden berechnen. So musst du nicht mehr über die gesamte Tilemap iterieren sondern nur noch über die die überhaupt in Frage kommen.
„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.“