Collision DetectionCollision detection in a tile engine like this one is so simple it hardly deserves such an important-sounding name. All we have to do is look at the map at the place to which we want to move. If there's an object there, movement is not allowed. If the spot is open, movement is OK. How hard can that be? Basically there are three things we must check:
The first one is a complete triviality. The second and third and pretty easy as well, as long as we have a way to keep track of that information, which we do! For detecting objects on the map, we have only to look at our tileset, which is represented by the For checking characters, we look at the main character and all the NPCs, to see if any of them are standing on that tile. This is why, when a character begins moving, we change their tile location immediately instead of waiting until movement is done. This way, walking onto a tile that another character is moving towards is not allowed, whereas walking onto a tile that another character is currently walking away from is all right. Now all we need is an array of NPCs so we can keep track of them: LPNPC lpnpc[100]; I've allowed for a lot of NPCs here; change the array size to match what you're going to need. Or you can always use a linked list. Remember that we've got a data member in our map structure to keep track of NPCs and we could use that too; I'm declaring it here separately to keep things a little clearer. Finally, you'll notice that I've declared pointers to structures instead of structures themselves. Why would I do that? Well, it's because we're going to have to sort NPCs later on, and it's faster to swap pointers than to swap entire functions. Anyway, now we can write a function that checks the validity of a space. We'll pass it an x and y coordinate for the space to check, and have it return int MoveOK(int x, int y) { int z; // first check the map boundaries if ((x < 0) || (y < 0) || (x > mapdata.xMax) || (y > mapdata.yMax)) return(FALSE); // now check if the main character is already there if ((x == player.move.xTile) && (y == player.move.yTile)) return(FALSE); // check all the NPCs for (z=0; z<mapdata.nNPCCount; z++) { if ((x == lpnpc[z]->move.xTile) && (y == lpnpc[z]->move.yTile)) return(FALSE); } // the tile itself is now the deciding factor, so just return that return(tileData[byMap[x][y][0]].bWalkOK); } If you're wondering where Now all we have to do is add a call to if (KEYSTATE(VK_UP) && (player.move.xMove == 0) && (player.move.yMove == 0) && MoveOK(player.move.xTile, player.move.yTile - 1)) { player.move.yMove = -1; player.move.yTile--; player.move.yOffset += 32; } And we're all set! Now the game responds to keypresses by first checking whether or not a player is allowed to move in that particular direction, then changes the player's location settings if appropriate. The only thing left is the character's visual representation on the screen, and so we move to animation. |