   Perfect collision in a tile based platform game?
  I'm working on a little tile based platform game in c++ but I'm having some problems with the collision. All the tiles and the player are 16 pixels width and 16 pixels high.This is a function that I call upon for checking the collision.//Handle the collision of the mapsint Handle_mapcollision(int x, int y) {    //Variables    int ofs, tile, tilex, tiley;   //Tiles divided by object's x and y position    tilex=x/16;    tiley=y/16;   //Tile counter is * width    ofs=(tiley*20)+tilex;   //Checks what the current map is    if (currentmap==0) {  tile=leveltestcol[ofs];    }    return tile;}and I use this for the player//Handle inputvoid Handle_player() {//================VARIABLES====================//Initialize keysint key,keytrig,keyl,keyu,keyr,keyd;int tile_left,tile_up,tile_right,tile_down;//===================KEYS===================//Initialize keysCML_GetKeys(&key,&keytrig);//Binds they keys to variableskeyl=CML_INPUT_KEY_LEFT;keyu=CML_INPUT_KEY_UP;keyr=CML_INPUT_KEY_RIGHT;keyd=CML_INPUT_KEY_DOWN;//=============COLLISION==============//Check for collisiontile_left=Handle_mapcollision(int(player.x-1),int(player.y+8));tile_up=Handle_mapcollision(int(player.x+8),int(player.y-1));tile_right=Handle_mapcollision(int(player.x+17),int(player.y+8));tile_down=Handle_mapcollision(int(player.x+8),int(player.y+17));//Checks for a solid tile beneath the playerif (tile_down==1) {   //Stop falling   player.gravity=0; //Reset jumping   player.jumping=false; //Set the player on the right spot, stops it from clipping slightly in solid tiles   player.y=floor(player.y/16)*16;   //floor((player.y+1)/16)*16;}//==================INPUT=========================//Checks if the left key is pressedif (key & keyl) {   //Checks for non solid tile   if (tile_left!=1) { //Move the player player.x-=player.speed;   }   //Sets the direction   player.direction=0;}//Checks if the right key is pressedif (key & keyr) {   //Checks for non solid tile   if (tile_right!=1) { //Move the player player.x+=player.speed;   }   //Sets the direction   player.direction=2;}//Checks if the up key is pressedif ((key & keyu) && (player.jumping==false)) {   //Checks for non solid tile   if (tile_up!=1) { //Let the player jump player.gravity=-6; player.jumping=true;  }}//===================GRAVITY======================//Sets gravityplayer.y+=player.gravity;if (tile_down!=1) {   player.gravity+=0.6f;   if (player.gravity>7)player.gravity=7;}}The result of this is that it kinda works, but not really well! You can download a compiled version of all the code herehttp://www.mediafire.com/?ynjn2ctknmwYou can jump through some blocks sometimes, get stuck and so on. You'll notice it quick enough by just jumping around.[Edited by - MoonChild1607 on May 18, 2009 3:29:11 AM]
  I'd take a good hard look at these four lines:tile_left=Handle_mapcollision(int(player.x-1),int(player.y+8));tile_up=Handle_mapcollision(int(player.x+8),int(player.y-1));tile_right=Handle_mapcollision(int(player.x+17),int(player.y+8));tile_down=Handle_mapcollision(int(player.x+8),int(player.y+17)); First, you're going "left" and "right" by modifying the y value, which I find counterintuitive. But second, while it's true that every object can only overlap at most four tiles at a time, I don't think this setup will check the four tiles you need to check. At the moment, my brain isn't quite up to describing what you need to do here, so I suggest drawing out a diagram with your player and some blocks, noting down X and Y values, and then figuring out which blocks you'll actually be checking for collision with.   ;  Those 4 lines check the points of the player as marked with magnenta colored lines in the picture below.;  Ah, my mistake. I thought you were doing rect-rect detection, but your Handle_mapcollision function is only looking at one point. Shows what I get for trying to debug unfamiliar code while I have a migraine. Slide your red box over to the right a bit (in your second diagram) and I think you'll see the problem. Its upper-right corner will intersect a terrain block well before one of the lines notices it.   ;  I'm working on a similar platform game at present, and the way I do the map collision (which works fine) is to check horizontal and vertical collision separately. I pass a RECT structure containing the sprite's current position and a reference to the x or y displacement which will result if there is no collision.COLLIDETYPE CheckHorzCollide(RECT& current_position, int& x_displacement);COLLIDETYPE CheckVertCollide(RECT& current_position, int& y_displacement);If there is a collision the x or y displacement is reduced to the amount which puts the sprite up against the tile or tiles. I'm checking against upper and lower tiles horizontally and left and right tiles vertically. I think this is better than checking x and y collisions together. You could return a bool value but I'm returning information about the collision that I can use such as whether the sprite collided with the top or bottom of the tile. Hope this helps.   