Tiles and collision

Blitz3D Forums/Blitz3D Beginners Area/Tiles and collision

David819(Posted 2004) [#1]
Hi, I'm currently working on a clone of mega bomberman, and i have got the basic scene to display, but i dont have a clue on how to apply collision to certain tiles and not on others. i'm using the data command to layout the scene, and i need certain values used in the data command to have collision applied.
please can someone help.
thanks.
p.s. please say if this does not make any sense.


Rob Farley(Posted 2004) [#2]
Have you looked at the alien breed threads?

Take a look at the first ever thread that's got basic tile collision, an editor, and other stuff that may interest you.

This was the whole point of the alien breed project to help people learn.


David819(Posted 2004) [#3]
I have looked at the alien breed threads, but doesn't seem to help me with my project, abit confusing really to be honest. I think my problem is that i'm not used to other peoples coding methods, which doesn't really help me. i've added the page to my favorites for future reference but i need a get my own understanding of this stuff first if you see what i mean.


smilertoo(Posted 2004) [#4]
Dont use the display to detect collisions, build an array that matches the tiles on screen and move the player around the array; you just check the array cell you want to move into and if its a tile that blocks you then you dont move.


WolRon(Posted 2004) [#5]
There are many ways to achieve what you want.

As mentioned you could use arrays to store extra information about each tile.

You could also use Types or Arrays of Types to store extra information.

Or you could simply use some kind of simple coding scheme in your Data statements. Say for example that all of your tiles are enumerated from 0-37. You know that you will never use more than 64 tiles, so you can set flags for certain tiles by adding the number 64 to any tile (ex. A number 5 tile would equal 69). You can check if the tile is collidable by doing either
If tile > 63
  col_tile = True ;tile is collidable, so note that
  tile = tile - 64
  ;now tile equals what it really is
EndIf
or
col_tile = (tile AND $40) Shr 6
;col_tile now equals a 0 or 1
tile = tile - 64
If you need to add more bits of information to your tiles, you can use other 'multiples of 2' numbers like 128, 256, 512, etc. and compare those with $80, $100, and $200 respectively.
energy_tile = (tile AND $200) Shr 9
;energy_tile now equals a 0 or 1
tile = tile - 512


Alternatively, you could leave tile to equal what it is (don't subtract the 64 or 512 part) and just do a compare like the following when you want to check what type of tile it is. This will only return the value below 64.
tiletype = (tile AND $3F)



David819(Posted 2004) [#6]
sorry for taking so long to post back, i sort of know what to do now, but not really in the coding sense, are there any simple examples of tile maps and collision with a player. just need some example to study to learn which doesn't have to much coding.
please help if possible.
thanks


Henrik(Posted 2004) [#7]
Hi try this great tileengine from the blitz2d samples
folder(i donīt know who coded this).
I have added a few lines of collisionscode
Bye Henrik
Const width=640,height=480
Const map_width=96,map_height=48

Global tiles
Dim map(map_width,map_height)

Graphics 640,480
SetBuffer BackBuffer()

CreateTiles()
CreateMap()
;stars=LoadImage( "graphics/stars.bmp" )
max_x=map_width*32-width
max_y=map_height*32-height

While Not KeyDown(1)

	If KeyDown( 203 )
		scroll_x=scroll_x-8:If scroll_x<0 Then scroll_x=0
	Else If KeyDown( 205 )
		scroll_x=scroll_x+8:If scroll_x>max_x Then scroll_x=max_x
	EndIf
	If KeyDown( 200 )
		scroll_y=scroll_y-8:If scroll_y<0 Then scroll_y=0
	Else If KeyDown( 208 )
		scroll_y=scroll_y+8:If scroll_y>max_y Then scroll_y=max_y
	EndIf
	
	Cls
	;TileBlock stars,-scroll_x/2,-scroll_y/2
	RenderMap( scroll_x,scroll_y )
	Color 200,0,0
	Text 220,200,"Move your mouse and scroll with arrows"
	Line MouseX(),MouseY()-10,MouseX(),MouseY()+10
	Line MouseX()-10,MouseY(),MouseX()+10,MouseY()
	If map(((MouseX()+scroll_x)/32),((MouseY())+scroll_y)/32)=0 Text 320,240,"collision"
	Flip
Wend

End

Function RenderMap( x_offset,y_offset )
	ty=y_offset/32
	sy=-(y_offset Mod 32)
	While sy<height
		ty=ty Mod map_height
		tx=x_offset/32
		sx=-(x_offset Mod 32)
		While sx<width
			DrawImage tiles,sx,sy,map( tx Mod map_width,ty )
			tx=tx+1:sx=sx+32
		Wend
		ty=ty+1:sy=sy+32
	Wend
End Function

Function CreateMap()
	Color 255,255,255
	Rect 0,0,map_width,map_height
	Color 0,0,0
	Rect 1,1,map_width-2,map_height-2
	Color 255,255,255
	Text map_width/2,map_height/4,"YEEEHHHAAA!",1,1
	Text map_width/2,map_height/2,"ALLRIGHTY!",1,1
	Text map_width/2,map_height*3/4,"TILEMAPDEMO",1,1
	For x=0 To map_width-1
		For y=0 To map_height-1
			GetColor x,y
			If ColorRed()>0 Then map(x,y)=0 Else map(x,y)=1
		Next
	Next
End Function

Function CreateTiles()
	tiles=CreateImage( 32,32,2 )
	
	Color 128,128,128
	Rect 0,0,32,32
	Color 192,192,192
	Rect 0,0,31,1:Rect 0,0,1,31
	Color 32,32,32
	Rect 31,1,1,31:Rect 1,31,31,1
	
	GrabImage tiles,0,0,0
	
	Color 0,0,0
	Rect 0,0,32,32
	For k=7 To 31 Step 16
		Color 192,192,192
		Rect k,0,1,32
		Color 32,32,32
		Rect k+1,0,1,32
	Next
	For k=7 To 31 Step 16
		Color 192,192,192
		Rect 0,k,32,1
		Color 32,32,32
		Rect 0,k+1,32,1
	Next
	
	GrabImage tiles,0,0,1
	
End Function



David819(Posted 2004) [#8]
Henrik, thanks for the example, i still varies from my code alot though. here is my coding so far:
AppTitle "Mega Bomberman Clone v0.0 - Test 1","Do you wish to return to your desktop?"
Graphics 640,510,32,2
SetBuffer BackBuffer()

Global Tiles
Dim Map(16,16)
Load_Map()

While Not KeyHit(1)

Cls
Update()
Flip
Wend
End

Function Load_Map()
Restore Map
For y=000 To 16
For x=000 To 16
Read Map(x,y)
Next
Next
tiles =LoadAnimImage("TileMap.png",29,29,0,13)
End Function

Function Update()
For y= 000 To 16
For x= 000 To 16
DrawImage tiles,x*30,y*30,map(x,y)
Next
Next
End Function

.map
Data 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4
Data 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4

Dunno how collision fits into this sort of thing.
hope somebody can help.


Henrik(Posted 2004) [#9]
Maybe you can use this
Bye Henrik

AppTitle "Mega Bomberman Clone v0.0 - Test 1","Do you wish to return to your desktop?" 
Graphics 640,510,32,2 
SetBuffer BackBuffer() 

Global Tiles 
Dim Map(16,16) 
Load_Map() 

While Not KeyHit(1) 

Cls 
Update() 
collisiontest()
	
Flip 
Wend 
End 

Function collisiontest()
	testnumber=4;or 12 or 0 or whatever tile you would like to test!!!
	If MouseX()<30*17 And MouseY()<30*17 Then;donīt test if your mouse is outside your mapsize (30*17)
		Color 200,0,0
		Text 220,200,"Move your mouse"
		Line MouseX(),MouseY()-10,MouseX(),MouseY()+10
		Line MouseX()-10,MouseY(),MouseX()+10,MouseY()
		If Map(MouseX()/30,MouseY()/30)=testnumber Text 180,240,"  Collision with tile nr:"+testnumber
	EndIf 
End Function

Function Load_Map() 
Restore Map 
For y=000 To 16 
For x=000 To 16 
Read Map(x,y) 
Next 
Next 
tiles =LoadAnimImage("TileMap.png",29,29,0,13) 
End Function 

Function Update() 
For y= 000 To 16 
For x= 000 To 16 
DrawImage tiles,x*30,y*30,map(x,y) 
Next 
Next 
End Function 

.map 
Data 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4 
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4 
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4 
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4 
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4 
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4 
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4 
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4 
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4 
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4 
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4 
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4 
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4 
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4 
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4 
Data 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 



David819(Posted 2004) [#10]
Cool, works well, thanks for all the help :), i shouldn't be back for a while know :), thanks again, bye.


David819(Posted 2004) [#11]
Ok, i thought i wouldn't be back for a while, well, i tried to apply collision so the mouse stoped when it hit a tile but doesn't work can someone tell me what i am doing wrong. i suck at 2d programing.
Here is my code:
AppTitle "Mega Bomberman Clone v0.0 - Test 1","Do you wish to return to your desktop?"
Graphics 640,510,32,2
SetBuffer BackBuffer()

Global Tiles
Dim Map(16,16)
Load_Map()

While Not KeyHit(1)

Cls
Update()
collisiontest()

Flip
Wend
End

Function collisiontest()
OldX=MouseX()
Oldy=MouseY()
testnumber=0;or 12 or 0 or whatever tile you would like to test!!!
If MouseX()<30*17 And MouseY()<30*17 Then;donīt test if your mouse is outside your mapsize (30*17)
Color 200,0,0
Text 220,200,"Move your mouse"
Line MouseX(),MouseY()-10,MouseX(),MouseY()+10
Line MouseX()-10,MouseY(),MouseX()+10,MouseY()
If Map(MouseX()/30,MouseY()/30)=testnumber Text 180,240," Collision with tile nr:"+testnumber

If RectsOverlap(MouseX()-10,MouseY()-10,MouseX()+10,MouseY()+10,Map(x,y)=0,Map(x,y)=0,Map(x,y)=29,Map(x,y)=29) Then
MouseX=OldX
MouseY=OldY
EndIf


EndIf
End Function

Function Load_Map()
Restore Map
For y=000 To 16
For x=000 To 16
Read Map(x,y)
Next
Next
tiles =LoadAnimImage("TileMap.png",29,29,0,13)
End Function

Function Update()
For y= 000 To 16
For x= 000 To 16
DrawImage tiles,x*30,y*30,map(x,y)
Next
Next
End Function

.map
Data 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4
Data 4,12,0,12,0,12,0,12,0,12,0,12,0,12,0,12,4
Data 4,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,4
Data 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4


Henrik(Posted 2004) [#12]
Hi
I found another great example of tile collision/slideing
on my harddisk i think you can use.
It is made by "Norc" (i think he use another nickname now)
Bye
Henrik
;Demonstration of very simple Non-Image-Collision-based "Wall-Detection"

Graphics 640,480,16;,2
nux#=0
oldx#=0
oldy#=0
x#=100
y#=100
a#=0

Dim tiles(15,15) ; Read the Wall information
For j=0 To 15
For i=0 To 15
Read tiles(i,j)
Next
Next

; MAINLOOP
While KeyHit(1)=0
Cls

For j=0 To 15 ; draw all walls for test purposes
For i=0 To 15 ; use your favorite Picture instead
If tiles(i,j)=1 Then
Color 120,120,120
Rect i*40,j*30,40,30,0
EndIf
Next
Next

oldx=x ; remember old player pos
oldy=y

; Keys
If KeyDown(200)=1 ; fwd
x=x+Sin(a)
y=y+Cos(a)
EndIf
If KeyDown(208)=1 ; back
x=x-Sin(a)
y=y-Cos(a)
EndIf
If KeyDown(203)=1 ; Player angle <
a=a+2
If a> 360 Then a=a-360
EndIf
If KeyDown(205)=1 ; Player angle >
a=a-2
If a< 0 Then a=a+360
EndIf

; dont allow walking tru walls, but allow sliding along
If tiles(((x-20)/40),((y-15)/30))=1 Then ; try new x, new y
nux#=x ; remeber nu x
x=oldx ; reset x to old x
EndIf
If tiles(((x-20)/40),((y-15)/30))=1 Then ; try old x, new y
x=nux#
y=oldy
EndIf
If tiles(((x-20)/40),((y-15)/30))=1 Then ; try new x, old y
x=oldx ; no, no chance, reset x and y both to old pos
y=oldy
EndIf

Color 255,0,0 ; Show a graphical Player
Oval x-5,y-5,10,10,1
Color 255,255,255
; show also wich direction Player is facing
Line x+Sin(a)*10,y+Cos(a)*10,x-Sin(a)*10,y-Cos(a)*10

Flip
Wend
End

; Walls = "1", Air = "0" 
; you can also use bigger levels - just keep 
; the relation (ie. 640/16=40) to check the Collision
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1
Data 1,1,0,1,1,1,1,1,0,1,1,1,1,0,1,1
Data 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1



David819(Posted 2004) [#13]
Ok, that should help me alot, thanks for the help :).


David819(Posted 2004) [#14]
Hi again :(, I have just been doing more coding and got the player to move and such, and tried to apply collision to the scene, i know sort of what i am suposed to do thanks to Henrik's coding sample, the only problem is i'm completly new to 2d programing and i'm not good at array programing, in other words i'm a crap programer at present. i know this is asking alot in the eyes of some people, but i was wandering if there was anyone here who is really good with 2d programing in blitz3d and has some free time available, if i could send my code via email to be checks and then get help on where i'm going wrong, please. sorry if i'm being really annoying. thanks.


BlackD(Posted 2004) [#15]
I haven't spent too much time looking (as I'm about to go to bed), but noticed one big flaw in your code.
MouseX=OldX 
MouseY=OldY
First of all, these would need to be MouseX() and MouseY() but even then, it wouldn't work. MouseX() and MouseY() are read-only functions. You can't use them to position the cursor.

Instead, replace those two lines with:
MoveMouse OldX,OldY
Rather than trying to re-write your entire program each time you have a new idea, keep working on your program as it is until it WORKS. :) This is called bug-hunting. Yes, its a long process and can be very frustrating, but you'll learn a lot more in the process for next time. If you start again however, you'll have a whole new set of bugs. Unless you're a very professional programmer, you'll always run into bugs in any program over a few lines.

So, add in extra lines to print the results of your equations to the screen, etc, to see if they're working the way you mean them to. Note: we can't actually run this code without the tilemap.png file. Sure someone like sswift or halo could come along, read all your code, and find exactly what mistake you're making and tell you how to fix it, but they won't necessarily be there the next time theres a bug, or the time after, or the time after that. :)

Anyway, I fixed one bug for you. ;) Keep working at it till you eliminate them all! :)

+BlackD

[EDIT: PS - I recommend going to the Blitz manual (download the latest documentation update too!) and clicking on 2D - Category, then going through one by one and reading up on what EVERY instruction does. You're not expected to remember them all right away, but some time later you'll remember "hey - wasn't there a command to move the mouse?" (or whatever) and look it up. The categories to concentrate on first are BASIC, INPUT, GRAPHICS and IMAGES. You NEED to know pretty much all the commands in those categories by heart, to write even a beginners 2D game.)


David819(Posted 2004) [#16]
Thanks for the tip BlackD, the only main problem i'm having is know where the errors are. i took your advise on adding lines for code to print the results but where ever i place it i get some kind of error like : array index out of range or variable must be a type ??? the code i put in is:
If Map(player\x,player\y)=0 Then Text 0,0,"Player has collided with the scene!"
i placed it in the update_player function which give me the first message i quoted and also in the main loop of the program which give the seconds error, i haven't placed the code in the two places at once. and i dunno where the code has gone wrong.