Tiled data maps & collision

Blitz3D Forums/Blitz3D Beginners Area/Tiled data maps & collision

Tobo(Posted 2006) [#1]
Wotcha, folks.

I've always been jealous of this piece of code, created by a user called Nebula (or something).

;
Graphics 640,480,16,2
SetBuffer BackBuffer()

Dim map(15,10)

Type player
	Field x,y
	Field fall,jump
	Field fallspeed#
End Type
Global p.player = New player

readlevel(1)

While KeyDown(1) = False
	Cls
	If MouseDown(1) = True Then
		p\x = MouseX()
		p\y = MouseY()
	EndIf
	drawlevel	
	drawplayer
	moveplayer
	world
	gravity
	Text 0,0,playermapcollision(0,0)
	Flip
Wend
End

Function world()
	If playerspringcollision() = True Then
		p\fallspeed = -5 : p\fall = True : p\jump = True
	EndIf
End Function

Function playerspringcollision()
	px = (p\x+8)/32
	py = p\y/32
	If map(px,py) = 2 Then Return True
End Function


Function moveplayer()
	If KeyDown(205) = True Then
		If playermapcollision(1,0) = False Then
		p\x = p\x + 1
		End If
	End If
	If KeyDown(203) = True Then
		If playermapcollision(-1,0) = False Then
		p\x = p\x - 1
		End If
	End If
	If KeyDown(57) = True Then
		If p\jump = False Then
			p\jump = True
			p\fallspeed = -3
			p\fall = True
		End If
	End If
End Function

Function gravity()
	;
	;
	If playermapcollision(0,p\fallspeed) = True And p\jump = True Then
		p\fallspeed = 0
		p\y = p\y/32*32
	End If
	;
	If playermapcollision(0,1) = False And p\fall = False
		p\fall = True 
		p\fallspeed = 1
	End If
	;
	If p\fall = True Then
		p\y = p\y + p\fallspeed
		p\fallspeed = p\fallspeed + .1
		For i=0 To p\fallspeed
			If playermapcollision(0,i) = True Then
				p\y = p\y+i/32*32
				p\fall = False
				p\jump = False
				Exit
			End If
		Next
	End If
End Function


Function playermapcollision(x1,y1)
	px = (p\x+x1) / 32
	py = (p\y+y1) / 32
	For x=-1 To 1
	For y=-1 To 1
		If RectsOverlap(px+x,py+y,1,1,0,0,15,10) = True Then
			Rect px*32+x*32,py*32+y*32,32,32,False
			If map(px+x,py+y) = 1 Then 
				If RectsOverlap(p\x+x1,p\y+y1,16,16,px*32+x*32,py*32+y*32,32,32) = True Then Return True
			End If
		EndIf
	Next:Next
	If RectsOverlap(p\x+x1,p\y+y1,16,16,15,15,14*32,9*32) = False Then
		Return True
	End If
End Function

Function drawplayer()
	Color 255,255,0
	Oval p\x,p\y,16,16,True
End Function

Function drawlevel()
	For x=0 To 15-1
	For y=0 To 10-1
		Select map(x,y)
		Case 1
		Color 255,255,255:Rect x*32,y*32,32,32,True
		Case 2
		Color 255,0,0 : Rect x*32,y*32+32-8,32,8,True
	End Select
	Next:Next
End Function

Function readlevel(level)
	Select level
		Case 1
		Restore level1
	End Select
	For y=0 To 10-1
	For x=0 To 15-1
		Read a
		map(x,y) = a
	Next:Next
End Function

.level1
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,2,0,0,0,0,0,0,0,0,0
Data 0,0,1,1,1,1,1,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,2,0,0,0,0,0,0,0
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1


Try as I might, I've never really been able to get my head around his playermapcollision() function. Which is a shame as his routine seems so neat and effective.

I understand that it checks the map data array 1 position all around the player, and that this is then used to check the rectsoverlap of actual blocks and the player .....but I'm just not quite there.

Here's my code:

Graphics 640,480,32,2
SetBuffer BackBuffer()
 

Dim map(9,9)
 
Global px=20
Global py=20
Global gpx=0
Global gpy=0
Global cgpx=False
Global cgpy=False
 

readmap()
 
; main loop
While Not KeyHit(1)
 Cls
 
 drawmap()
 drawstats()
 moveplayer()
 drawplayer()
 playermapcollision(0,0)
 
 Flip
Wend
End
 
 
 
;*************
;*           *
;* FUNCTIONS *
;*           *
;*************
 

; PlayerMapCollision
Function playermapcollision(x1,y1)
 
 goffx=x1
 goffy=y1
 
For x=-1 To 1
	For y=-1 To 1

		Color 0,255,0
    
	    Rect (px/20)*20+(x*20),(py/20)*20+(y*20),20,20,False
    
    	Text 310+(x*10),140+(y*10),map(gpx+x,gpy+y)
    
    	Text 300,190,"X1: "+goffx+"      Y1: "+goffy
    
    	If map(gpx+goffx,gpy+goffy)=1 Then Text 300,210,"Block coming up"
         
		Color 255,255,255

	Next
Next
End Function
 
; DrawStats
Function drawstats()
 Text 300,10,"PX: "+px+"      PY: "+py
 gpx=px/20
 gpy=py/20
 Text 300,30,"Grid X: "+gpx+"   Grid Y:"+gpy        
 Text 300,50,"Surround: "+(px/20)*20+","+(py/20)*20      
 Text 300,70,"Map ref: "+map(gpx,gpy)         
 Text 300,90,map(gpx-1,gpy-1)+" "+map(gpx,gpy-1)+" "+map(gpx+1,gpy-1)
 Text 300,100,map(gpx-1,gpy)+" "+map(gpx,gpy)+" "+map(gpx+1,gpy)
 Text 300,110,map(gpx-1,gpy+1)+" "+map(gpx,gpy+1)+" "+map(gpx+1,gpy+1)
 
End Function
 
; Move Player
Function moveplayer()
 
 Local ox=px,oy=py
 
 If KeyDown(205) Then 
  If playermapcollision(1,0) = False
   px=px+1
  End If
 End If
 
 If KeyDown(203) Then
  If playermapcollision(-1,0) = False
   px=px-1
  End If
 End If
 
 If KeyDown(200) Then
  If playermapcollision(0,-1) = False
   py=py-1
  End If
 End If
 
 If KeyDown(208) Then
  If playermapcollision(0,1) = False
   py=py+1
  End If
 End If
 
 If px<20 Then px=ox
 If px>160 Then px=ox
 If py<20 Then py=oy
 If py>160 Then py=oy
 
End Function
 
; Draw Player
Function drawplayer()
 Color 255,255,0
 Rect px,py,20,20,True
 Color 255,255,255
End Function
 

; Read Map
Function readmap()
For y=0 To 9
 For x=0 To 9
  Read a
  map(x,y)=a
 Next
Next
End Function
 
.level1
Data 1,1,1,1,1,1,1,1,1,1
Data 1,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,1,0,1,0,1
Data 1,0,0,1,1,1,0,1,0,1
Data 1,0,0,1,0,0,0,0,0,1
Data 1,0,0,0,0,1,1,0,0,1
Data 1,0,0,0,0,0,1,0,0,1
Data 1,0,1,1,1,1,1,1,0,1
Data 1,0,0,0,0,0,0,0,0,1
Data 1,1,1,1,1,1,1,1,1,1
 
; Draw map
Function drawmap()
 
 Color 0,0,255
 
 For x=0 To 9
  For y=0 To 9
   If map(x,y)=1 Then Rect x*20,y*20,20,20,True
   Line 0,y*20,200,y*20
   Line x*20,0,x*20,200
  Next
 Next
 Color 255,255,255
 
End Function


What's the method of restricting player movement when you come up against walls?

.........you can tell I'm having problems - I can't even explain it well!

Any help much appreciated.

Tobo.


Tobo(Posted 2006) [#2]
Ooh ooh - I may be getting there.........

Graphics 640,480,32,2
SetBuffer BackBuffer()

Dim map(19,19)

Global px=20
Global py=20
Global gpx,gpy


readmap()

While Not KeyHit(1)
	Cls

	drawmap()
	checkmove()
	drawplayer()
	drawsurround()
	showstats()

	Flip
Wend
End


; FUNCTIONS

; Draw Surround
Function drawsurround()
	For x=-1 To 1
		For y=-1 To 1
			If map(gpx+x,gpy+y)=1
				Color 255,255,0
				Rect ((px/20)*20)+x*20,((py/20)*20)+y*20,20,20,False
				Color 255,255,255
			End If
		Next
	Next
End Function

; Show Stats
Function showstats()
	Text 430,10,"Grid Ref: "+gpx+","+gpy
	
	Text 430,30,map(gpx-1,gpy-1)+" "+map(gpx,gpy-1)+" "+map(gpx+1,gpy-1)
	Text 430,40,map(gpx-1,gpy)+" "+map(gpx,gpy)+" "+map(gpx+1,gpy)
	Text 430,50,map(gpx-1,gpy+1)+" "+map(gpx,gpy+1)+" "+map(gpx+1,gpy+1)

End Function

; Check Move
Function checkmove()
	
	ox=px
	oy=py
	
	If KeyDown(205)
		px=px+2
	End If
	
	If KeyDown(203)
		px=px-2
	End If
	
	If KeyDown(200)
		py=py-2
	End If
	
	If KeyDown(208)
		py=py+2
	End If
	
	If px>360 Or px<20 Then px=ox
	If py>360 Or py<20 Then py=oy
	
	gpx=px/20
	gpy=py/20
	
End Function

; Draw Player
Function drawplayer()
	Rect px,py,20,20
End Function

; Draw Map
Function drawmap()
	For ac=0 To 19
		For dn=0 To 19
			Color 0,0,255
			If map(ac,dn)=1 Then Rect ac*20,dn*20,20,20
			Color 0,255,0
			Line ac*20,0,ac*20,400
			Line 0,dn*20,400,dn*20
			Color 255,255,255
		Next
	Next
End Function

; Read Map
Function readmap()
	Restore level1
	For dn=0 To 19
		For ac=0 To 19
			Read a
			map(ac,dn)=a
		Next
	Next
End Function

.level1
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,1
Data 1,0,0,0,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,1
Data 1,0,0,0,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,1
Data 1,0,0,0,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,1
Data 1,0,0,0,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,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,1,1,1,1




Tobo(Posted 2006) [#3]
Okay - I'm officially happy now.

SORTED !

Graphics 640,480,32,2
SetBuffer BackBuffer()

Dim map(19,19)

Global px=20
Global py=20
Global gpx,gpy

readmap()

While Not KeyHit(1)
	Cls

	drawmap()
	checkmove()
	drawplayer()
	showstats()

	Flip
Wend
End


; FUNCTIONS


; Player Map Collision
Function playermapcollision()
	For x=-1 To 1
		For y=-1 To 1
			If map(gpx+x,gpy+y)=1
				If RectsOverlap (px,py,20,20,((px/20)*20)+x*20,((py/20)*20)+y*20,20,20) Then Return True
			End If
		Next
	Next
End Function

; Show Stats
Function showstats()
	Text 430,10,"Grid Ref: "+gpx+","+gpy
	
	Text 430,30,map(gpx-1,gpy-1)+" "+map(gpx,gpy-1)+" "+map(gpx+1,gpy-1)
	Text 430,40,map(gpx-1,gpy)+" "+map(gpx,gpy)+" "+map(gpx+1,gpy)
	Text 430,50,map(gpx-1,gpy+1)+" "+map(gpx,gpy+1)+" "+map(gpx+1,gpy+1)

End Function

; Check Move
Function checkmove()
	
	ox=px
	oy=py
	
	If KeyDown(205)
		px=px+2
	End If
	
	If KeyDown(203)
		px=px-2
	End If
	
	If KeyDown(200)
		py=py-2
	End If
	
	If KeyDown(208)
		py=py+2
	End If
	
	If px>360 Or px<20 Then px=ox
	If py>360 Or py<20 Then py=oy
	
	gpx=px/20
	gpy=py/20
	
	If playermapcollision() = True Then px=ox:py=oy
	
End Function

; Draw Player
Function drawplayer()
	Rect px,py,20,20
End Function

; Draw Map
Function drawmap()
	For ac=0 To 19
		For dn=0 To 19
			Color 0,0,255
			If map(ac,dn)=1 Then Rect ac*20,dn*20,20,20
			Color 0,255,0
			Line ac*20,0,ac*20,400
			Line 0,dn*20,400,dn*20
			Color 255,255,255
		Next
	Next
End Function

; Read Map
Function readmap()
	Restore level1
	For dn=0 To 19
		For ac=0 To 19
			Read a
			map(ac,dn)=a
		Next
	Next
End Function

.level1
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,1
Data 1,0,0,0,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,1
Data 1,0,0,0,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,1
Data 1,0,0,0,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,1
Data 1,0,0,0,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,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,1,1,1,1


If anyone can explain why in Nebula's code he had to pass variables to his playermapcollision() function, I'd love to know.

Sorry for the mega post.

Tobo.


Tobo(Posted 2006) [#4]
Forgot to say...

A very big thankyou to Nebula. Your damn piece of code has annoyed and encouraged me for the last 8 months.

Now, can anyone tell me how to go from the above, to Half-Life2?


b32(Posted 2006) [#5]
Good work, tobo :) glad you've solved it.