0

So I've been messing around with simple game development for a while and just found an interesting game idea on squidi.net/three/entry.php?id=85 . I'm using SFML 2.1 with C++ and I have a tilemap in a VertexArray that displays the level. Here is what I have so far and you can see my simple tileset: LINK. I am pretty lost in terms of how to handle collisions between the submarine (which is not on a grid based movement system) and the walls. The problem is that say the sub approaches tile 2 (check the tileset image) from the bottom, if I check a collision between the sub and the whole tile the sub will stop before it even gets to the actual wall in the image. Here is an image to help explain this: LINK.

Sorry for the previous confusion and I hope this isn't as bad as before.

Any help is greatly appreciated.

Thanks,

Karel

Edit: Rewrote the question to try to make it clearer.

Karel
  • 19
  • 1

2 Answers2

1

I will warn you that simple grid based collision breaks down horribly if the object in question moves faster than the resolution of your collsiion tiles. Pretend that your collision boxes are 8x8 pixels in size. Now, what happens when the submarine moves say 16 pixles per tic? You can see that it can jump through single thickness collision walls if you are not very careful on how you check for collision - checking every tile the submarine hits while moving instead of updating the position by the velocity directly. It is even worse than this though - image that you are moving only 2 pixles per second and just clip the edge of a tile, but end on the other side - again the tile based collision, without code that traces every block you touch while moving, will fail.

A more generic way is to use line or vector based collision. Basically, instead of a tile map, use a list of vectors that represent wall edges. To check for a collision in 2D, you can check the sign of the perpdot (perpendicular dot product) of your starting point versus the collsion vector and the sign against the end point of your movement against the collision vector. If they are different, you crossed the line and a collision occured. If either are 0, you are on the collision line. Be sure to check for the end point of the line as well which involves a few more dot products.

The added benefit of this method is that it makes it really easy to 'slide' your character along walls when the collide instead of just backing them up to the previous position which causes wall sticking and vibration. It also is really really fast being just a few multiplies and subtracts. It also scales easily to SIMD style code as well.

See this question for a bit more info.

Community
  • 1
  • 1
Michael Dorgan
  • 12,453
  • 3
  • 31
  • 61
0

Your submarine is smaller than a tile, so the submarine will be covering at most 4 tiles at any given time.

  1. Identify the tiles that the submarine overlaps. At least 1, at most 4.
  2. For each overlapping tile, call a function that corresponds to that tile's type (0 through 6)

You can pass to each function how far the sub is from that tile's center.

Here's the easiest:

bool collided_with_tile_0( int x_offset, int y_offset )
{
  return false;  // Nothing to collide with
}

This one's pretty easy too:

bool collided_with_tile_1( int x_offset, int y_offset )
{
  return std::abs( y_offset ) < SUB_SIZE;  // Collision if y_offset is close to 0
}

Good luck!

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180