collision inside a map?

Blitz3D Forums/Blitz3D Programming/collision inside a map?

matthews_30(Posted 2006) [#1]
maybe my questioin is wrong, pease clarify.

i have created a 2d scrolling map (based on tiles), now i have to assign collisions to the walls and some things that exist in the map i created, can i assing collisions in this way or do i have to add the walls and objects manually via programming?

because i know that imagescollide if i have the handle and test it against the character, but i dont know how this thing works in a map file.

thanks for any comment.


Matty(Posted 2006) [#2]
Is your 2d scrolling map isometric or top down?
A fairly simple way is to create a 2d array which is arranged in a grid storing a value at each element - either 0 or 1 for 'walkable/not walkable'. You can then load in the array from a file you may create in an editor you can simply put together. Each array index refers to a specific location on the map.

There are many ways of testing for collisions, this is just one example.


matthews_30(Posted 2006) [#3]
it is an isometric map but anyway i would like to hear your comments about both techniques, please.

matt.


Matty(Posted 2006) [#4]
If you are going the traditional way of having a grid array representing the play area then you can also use a grid, perhaps of higher resolution, to store your collision information in. I will try to give an outline below:

You may have a room which looks something like this:

0000000
0 0
0 0 0
0 0 0
0 X 0
0000000

Note the two obstacles in the middle '0' (and the walls 'O') as well as the creature 'X'.

This could be similar in style to your tilemap.

The above room could be stored as a 2 dimensional array such as:

Dim MapArray(6,5) ;dimensions of room (usually this array could be quite large if you have a large level.  If you think about it each element is 4 bytes, so even an array of Dim MapArray(1024,1024) is only 4 Megabytes of system memory - pretty small these days.


You would then read in the array element values, in this case either a 0 or a blank- although I would suggest more obvious values such as 0 or 1.

Let us assume that we are using 1s for walls/obstacles and 0s for free walkable areas.

Let us also assume that we are storing the player x and z position in a variable 'playerx' and 'playerz'. Also store a value such as 'playerradius' for the player.

When you perform your movement routine, you would perform a simple check to see first of all if you are moving to a new grid square (which you may not be if each grid square in the array represents a large area, say of similar size to the player). If you not moving to a new grid square then allow the move.

If you are moving to a new grid square then check if the new grid square is a '0' (free) or a '1' (blocked). If it is blocked then disallow the move. If it is '0' then allow the move.

Note this does not take into consideration creature-creature collisions, although they can be implemented similar. The least efficient way is to loop through each other creature, check if your new move will bring you to within creature 1's radius + creaure 2's radius and if so disallow the move. A more efficient way is to first check the grid squares around you (as well as the one you are in if the grid squares are large enough to hold more than 1 unit (advisable)).

Some sample code, which will need modification - this is just as an example of how you might go about doing it, is this:

(only showing how to do collisions in tilemap not between creatures with other creatures)

;in your player movement function/code part

newplayerx#=currentplayerx#+moveinxdirection#
newplayerz#=currentplayerz#+moveinzdirection#

currentgridx%=currentplayerx*MaximumGridXSizeInArray%/TotalPlayingAreaXSize#
currentgridz%=currentplayerz*MaximumGridZSizeInArray%/TotalPlayingAreaZSize#

;calculate newgridx, newgridz the same way using newplayerx , newplayerz in place of currentplayerx and currentplayerz

newgridx%=newplayerx*MaximumGridXSizeInArray/TotalPlayingAreaXSize
newgridz%=newplayerz*MaximumGridZSizeInArray/TotalPlayingAreaZSize

;assume MapArray() is an array with dimensions MAximumGridXSizeInArray,MaximumGridZSizeInArray

if newgridx=currentgridx and newgridz=currentgridz then 
;okay to move there, unless a creature is collided with (check next)

else
  if newgridx>=0 and newgridz>=0 and newgridx<=MaximumGridXSizeInArray and newgridz<=MAximumGridZSizeInArray and currentgridx>=0 and currentgridz>=0 and currentgridx<=MaximumGridXSizeInArray and currentgridz<=MAximumGridZSizeInArray then 

;okay we are about to cross into a new grid square, so check if it is occupied by an obstacle or a wall
If MapArray(NewGridX,NewGridZ)=0 then 
;grid square is empty so okay to move there, assuming of course there are no other creatures who will need to be tested against..
else
;grid square is occupied by a wall so cannot move there

endif 

else
;not okay to move there as we would be leaving the map
endif 

endif 




Something like that is fairly simple, but works well.
What I did not include was the 'radius' of the player. To do this you would simply add the radius to the player's move in the direction of the player's move.

Hope this is of some help.


matthews_30(Posted 2006) [#5]
ok, understood.

thanks a lot.

matt.