Help with tile collision check with a loop

Ecd731b2aae3d61370b32d4d17dc4bc9
0
hope_industries 101 Apr 18, 2013 at 22:33 c++ devmaster terrain collision programming

Hey there guys! I am following a tutorial on game development “Introduction to C++ with game development” and currently on the self assignment of part 11. The assignment is to assign collision checks on certain tiles and I came with the following loop in the ticker function:

for(int i = 0; i < count; i++)
{
  if((newTankX + 50) >= blockX[i] && newTankX <= (blockX[i] + 64) && (newTankY + 50) >= blockY[i] && newTankY <= (blockY[i] + 64))
  {
   newTankX = tankX;
   newTankY = tankY;
   tankX = tankX;
   tankY = tankY;
   printf("Collision!");
  }else{
   tankX = newTankX;
   tankY = newTankY;
   printf("NO!!");
  }
}

What happens here is whenever I move my tank, I save the upcoming X and Y coords in a temporary variable. I use the temporary variable to check whether the x and y as come in contact with the x and y coords of the tile.

The x and y coords of the tiles are saved in blockX and blockY arrays.

So whenever there is contact, my tank should stop moving, which works fine!

The only problem is that it only works with one tile, specifically the first one being added to the screen. The tank moves through the other tiles, but I do get a collision, but the tank does not stop.

My question is.. why does the tank only stop at one tile and not the others?

Optional question, is there a better way to solve collision problems? (Only hints on this one please)

4 Replies

Please log in or register to post a reply.

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Apr 18, 2013 at 22:57

I guess you probably want to stop the loop when a collision occurs. As written, the code will only work correctly for the last block in the list, since tankX and tankY are overwritten in every iteration.

You could do this by adding the statement “break;” after the printf(“Collision!”). That makes the loop stop early and go to whatever’s next after the loop, as soon as the first collision is detected.

By the way, this code:

   tankX = tankX;
   tankY = tankY;

doesn’t do anything.

Finally, the code in your else clause:

   tankX = newTankX;
   tankY = newTankY;

is being executed every time through the loop (unless there’s a collision), but it only needs to be done once after the loop is finished.

Hope that helps.

Ecd731b2aae3d61370b32d4d17dc4bc9
0
hope_industries 101 Apr 19, 2013 at 09:33

No luck with the break. Here is my full code to understand it a bit better ( It’s not much so should be easy to read):

//Global vairiables
Sprite tank(new Surface("assets/ctankbase.tga"), 16);
int tankX = 0;
int tankY = 0;
int speed = 1;
//New x and y coords
int newTankX = 0;
int newTankY = 0;
//Tiles
int tileBlock = 5;
int count = 0;
int blockX[64];
int blockY[64];
Surface* tileSet[8];
int landTile[8][8] ={{0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0},
      {0,0,0,0,5,5,0,0},
      {0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0},
      {0,0,0,0,5,0,0,0},
      {0,0,0,0,0,0,0,0},
      {0,0,0,0,0,0,0,0}};
void Game::Init()
{
// put your initialization code here; will be executed once
tileSet[0] = new Surface("assets/tiles/tile1.png");
tileSet[1] = new Surface("assets/tiles/tile2.png");
tileSet[2] = new Surface("assets/tiles/tile3.png");
tileSet[3] = new Surface("assets/tiles/tile4.png");
tileSet[4] = new Surface("assets/tiles/tile5.png");
tileSet[5] = new Surface("assets/tiles/tile6.png");
tileSet[6] = new Surface("assets/tiles/tile7.png");
tileSet[7] = new Surface("assets/tiles/tile8.png");
for(int x = 0; x < 8; x++)
{
  for(int y = 0; y < 8; y++)
  {
   if(landTile[y][x] == tileBlock){
    blockX[count] = x * 64;
    blockY[count] = y * 64;
   
    //printf("ResultX: %i \n", blockX[count]);
    //printf("ResultY: %i \n", blockY[count]);
    count++;
   }
  }
}
}
//Function keeps refreshing the screen
void Game::Tick( float a_DT )
{
m_Screen->Clear(0);
for(int x = 0; x < 8; x++)
{
  for(int y = 0; y < 8; y++)
  {
   int tile = landTile[y][x];
   //64 = tile size
   tileSet[tile]->CopyTo(m_Screen, x * 64, y * 64);
  }
}

if(GetAsyncKeyState(VK_UP)){ newTankY -= speed; }
if(GetAsyncKeyState(VK_DOWN)){ newTankY += speed; }
if(GetAsyncKeyState(VK_RIGHT)){ newTankX += speed; }
if(GetAsyncKeyState(VK_LEFT)){ newTankX -= speed; }

for(int i = 0; i < count; i++)
{
  if((newTankX + 50) >= blockX[i] && newTankX <= (blockX[i] + 64) && (newTankY + 50) >= blockY[i] && newTankY <= (blockY[i] + 64))
  {
   newTankX = tankX;
   newTankY = tankY;
   tankX = tankX;
   tankY = tankY;
   printf("Collision");
  }else{
   tankX = newTankX;
   tankY = newTankY;
   printf("NO!!");
  }
}

tank.Draw(tankX, tankY, m_Screen);
//Sleep = Slows down the fps (Need more explenation)
Sleep(5);
}
B5262118b588a5a420230bfbef4a2cdf
0
Stainless 151 Apr 19, 2013 at 13:33

count == 0

you never give it a value

Ecd731b2aae3d61370b32d4d17dc4bc9
0
hope_industries 101 Apr 19, 2013 at 15:47

@Stainless

count == 0 you never give it a value

The count is given a value on top. Around global variables under tiles ( int count = 0; )

And for each tileBlock, I get a count. ( Count++; )