I thought it might be worth briefly sharing my approach to handling grid movement. It’s by no means finalised but just now is giving some very satisfactory results.
In every game that I make I employ a fairly basic box based method for collision detection. In reasonably fast paced arcade games where the sprites are deliberately designed to fill the box this really isn’t a problem since gamers won’t notice a couple of pixels in error. Besides I always weight the collision routine in favour of the player where relevant.
With the maze game I’ve adopted a slightly different approach to handling whether or not the player sprite is about to collide with the maze walls. ( Visit this link to read an earlier blog post on the construction of the maze walls )
The game is laid out on a 10 x 15 grid of 32 x 32 pixel blocks. The blocks are actually sprites since I want to animate them (i.e. cycle through animation frames, move in to position on level load, resize and move during the game). But unlike all other sprites in the game I won’t be using the standard collision routines.
At any given moment in the game the player will be either a) sat at a precise location that can be converted in to a grid reference or b) in transit between two grid references. This is the key to my handling of wall collision.
The graphics above should illustrate these points.
In illustration b) the player has swiped the screen to initiate movement. The game recognises the fact that the player sprite is currently not moving ( m.player.moving = false ) and is therefore cleared to attempt movement. But first we perform a test by translating the player sprite’s x,y co-ordinates in to a grid reference.
e.g. m.player.x = 128, m.player.y = 192 = the player sprite is sat at grid reference 4 , 6 (128/32, 192/32)
We can now determine which way the player wishes the sprite to travel and test the corresponding grid location to see whether a wall is sat in the way. We can perform this test against the leveldata array that stores our wall locations. You can see more on this in the blog post I linked to above.
So fairly basic so far. If a wall is in the way the move request is rejected – see below.
Player sprite is sat at grid 4, 1. He wants to move to 5, 1. A quick lookup on the leveldata array shows us that for element 1 of the leveldata array there is an “+” sat in position 5. See below.
var leveldata = ; leveldata = [ "+,+,+,+,+,+,+,+,+,+", "+, , , , ,+,+, , ,+", "+, , , , , , , , ,+", "+, ,+,+,+,+,+,+, ,+", "+, , , , , , , , ,+", "+,+,+, ,+,+, ,+,+,+", "+, , , , , , , , ,+", "+, , , , , , , , ,+", "+, , , , , , , , ,+", "+,+,+,+, , ,+,+,+,+", "+, , , , , , , , ,+", "+, , , , , , , , ,+", "+,+,+,+,+,+,+,+,+,+", "+,+,+,+,+,+,+,+,+,+", "+,+,+,+,+,+,+,+,+,+" ];
Where the fun begins is in the handling of new direction requests once the sprite is in motion.
A couple of things need to happen here.
First I need the player’s sprite to just keep going until a wall is hit.
In order to do this I let the sprite walk the grid only passing through the test function once its co-ordinates perfectly resolve to a grid reference. ( This my sound a bit hit and miss but I can, by initially setting the player sprite to an x and y that is divisible by 32, guarantee that this will always happen. )
My sprite walks at 8 pixel increments so moving from grid location A to grid location B takes 4 steps. This is a deliberately short timeframe between grid points. It is important for me that the player is able to register quite frequently by way of a swipe on the screen an intended next direction.
This intended next direction is stored and when the player’s sprite falls perfectly in to position at the next grid reference I test this new direction instead of the actual direction. If the new direction fails the sprite just carries on on its prefered course until a) a new direction request is received or b) it hits a wall.
Of course at any point in transit the player has the freedom to “turn his sprite around”. There is nothing to stop this since the game is testing for precise locations the sprite will just fall back in to a previous grid location.
So finally a word on what happens with the other objects in the game.
Monsters will follow the same code path as the player sprite. When they hit a wall they will make a decision based on their definitions. In most cases I expect that the monsters will “hunt” for the player since this is where the challenge should be. But in some cases I will completely randomise things such that the monster will quite happily retread his footsteps. This should add enough of a mix to the game to keep the player guessing.
Other entities such as gems, powerups, bonuses, magic weapons etc will be initially placed by the leveldata definitions but will actually be tested for collision against the player using my standard collision routine. That way I am free to move the sprites around the maze if I wish.
So that’s it ! Nothing overly complicated at all. Of course this is all just theory written here. I’ve not posted code since the code isn’t finished. Once it is I’ll revisit some of this.
Thanks for reading.