Mario Collisions

BlitzMax Forums/BlitzMax Programming/Mario Collisions

I've been thinking about creating a simple platform game, and am already having trouble with the collisions. I took some .bb source code that someone posted on CodersWorkshop, ported it to blitzmax, giving me this:
SuperStrict



'********************************** screen constants

Const SCREEN_WIDTH:Int = 800
Const SCREEN_HEIGHT:Int = 600
Const FULL_SCREEN:Int = False 
Const HERTZ:Int = 60


'********************************** grid constants

Const MAP_WIDTH:Int = 20
Const MAP_HEIGHT:Int = 15
Global map:Int[MAP_WIDTH,MAP_HEIGHT]
'********************************** player state enumeration

Const ST_NORMAL:Int = 0
Const ST_FALLING:Int = 1
Const ST_JUMPING:Int = 2

'********************************** 
Const GRAVITY:Float = .2
Const TILE_SIZE:Int = 40 
Const DIR_RIGHT:Int = 2
Const DIR_LEFT:Int = 1
Graphics SCREEN_WIDTH,SCREEN_HEIGHT,FULL_SCREEN,HERTZ


Global player:Tplayer = New Tplayer
player.x = 200
player.y = 200
'player.state = ST_FALLING
player.bg_width = 40
player.bg_height = 40



fillmap()

While Not KeyDown(KEY_ESCAPE)

	drawmap()
	player.update() 
	DrawText("x: " + player.x,50,50)
	DrawText("y: " + player.y,50,70)
	DrawText("state: " + player.state,50,90)
	Flip
	Cls
	
Wend 


Function drawmap()
	For Local loop_x:Int = 0 To MAP_WIDTH - 1
		For Local loop_y:Int = 0 To MAP_HEIGHT - 1
			SetColor map[loop_x,loop_y] * 255,60,60
			DrawRect loop_x*TILE_SIZE,loop_y * TILE_SIZE,TILE_SIZE,TILE_SIZE
		Next
	Next
End Function 






Type Tplayer
	
	Field x:Float
	Field y:Float
	
	Field xv:Float
	Field yv:Float
	
	Field id:String
	
	Field state:Int
	Field direction:Int
	Field distance:Int
	
	Field bg_width:Int 'bounding box width 
	Field bg_height:Int 'bounding box height
	
	Method Update()
		checkkeys()
		draw()
	End Method 
	
	Method draw()
		SetColor 255,255,255
		DrawRect x,y,bg_width,bg_height
	End Method 
	
	Method RightCollision:Int(speed:Float)
		
		For Local loop_x:Int = 0 To MAP_WIDTH - 1
			For Local loop_y:Int = 0 To MAP_HEIGHT - 1
				
				If rectsoverlap(x + speed + 1, y, bg_width, bg_height, loop_x * TILE_SIZE, loop_y * TILE_SIZE, TILE_SIZE, TILE_SIZE)
					Select map[loop_x,loop_y]
						Case 1
							distance = (loop_x * TILE_SIZE) - (x + bg_width)
							Return True
					End Select
				EndIf
				
			Next
		Next 
		
	End Method 
	
	
	Method LeftCollision:Int(speed:Float)
		
		For Local loop_x:Int = 0 To MAP_WIDTH - 1
			For Local loop_y:Int = 0 To MAP_HEIGHT - 1
				
				If rectsoverlap(x + speed - 1, y, bg_width, bg_height, loop_x * TILE_SIZE, loop_y * TILE_SIZE, TILE_SIZE, TILE_SIZE)
					Select map[loop_x,loop_y]
						Case 1
							distance = x - ((loop_x + 1) * bg_width)
							Return True
					End Select
				EndIf
				
			Next
		Next 
	End Method 
	


	Method BottomCollision:Int(speed:Float)
		
		For Local loop_x:Int = 0 To MAP_WIDTH - 1
			For Local loop_y:Int = 0 To MAP_HEIGHT - 1
				
				If rectsoverlap(x, y + speed + 1, bg_width, bg_height, loop_x * TILE_SIZE, loop_y * TILE_SIZE, TILE_SIZE, TILE_SIZE)
					Select map[loop_x,loop_y]
						Case 1
							distance = (loop_y * TILE_SIZE) - (Y + bg_width)
							Return True
					End Select
				EndIf
				
			Next
		Next 
	End Method 	
	


	Method TopCollision:Int(speed:Float)
		
		For Local loop_x:Int = 0 To MAP_WIDTH - 1
			For Local loop_y:Int = 0 To MAP_HEIGHT - 1
				
				If rectsoverlap(x, y + speed - 1, bg_width, bg_height, loop_x * TILE_SIZE, loop_y * TILE_SIZE, TILE_SIZE, TILE_SIZE)
					Select map[loop_x,loop_y]
						Case 1
							distance = ((loop_y + 1) * TILE_SIZE) - (y)
							Return True
					End Select
				EndIf
				
			Next
		Next 
	End Method 		
	
	
	Method checkkeys()
		
		Select state
			Case ST_NORMAL
				If Not bottomCollision(yv)
					state = ST_FALLING
				EndIf
				
			Case ST_FALLING
				yv = yv + GRAVITY
				If bottomCollision(yv) And state <> ST_JUMPING 
					yv = 0
					y = y + distance
					state = ST_NORMAL
				EndIf
				
			Case ST_JUMPING
				If topCollision(yv)
					yv = 0
					y = y + distance
					state = ST_FALLING
				EndIf
				yv = yv + GRAVITY
				If yv >= 0 
					state = ST_FALLING
				EndIf
		End Select
	
		If KeyHit(KEY_UP) And (Not topCollision(yv)) And (state = ST_NORMAL)
			state = ST_JUMPING
			yv = -8
		EndIf 
		
		If yv > 10
			yv = 10
		EndIf 
		
		If xv > 5 
			xv = 5
		ElseIf xv < -5
			xv = -5
		EndIf 
		
		x = x + xv
		y = y + yv
		
		If KeyDown(KEY_RIGHT)
			direction = DIR_RIGHT
			If rightCollision(xv) 
				xv = 0
				x = x + distance
			Else
				If xv > 0
					If leftCollision(xv)
						xv = 0
						x = x - distance
					EndIf
					xv = xv + 0.5
				Else
					xv = xv + 0.2
				EndIf
			EndIf 
		EndIf 
		
		
		If KeyDown(KEY_LEFT)
			direction = DIR_LEFT
			If leftCollision(xv)
				xv = 0
				x = x - distance
			Else
				If xv < 0 
					If rightCollision(xv)
						xv = 0
						x = x + distance
					EndIf
					xv = xv - 0.5
				Else
					xv = xv - 0.2
				EndIf
			EndIf 
		EndIf 
		
		
		If (xv > 0 Or xv < 0) And ((Not KeyDown(KEY_RIGHT)) And (Not KeyDown(KEY_LEFT)))
			
			Select direction
				Case DIR_LEFT
					If leftCollision(xv)
						xv = 0
						x = x - distance
					Else
						xv = xv + GRAVITY
						If xv >= 0 
							xv = 0
						EndIf
					EndIf
					
				Case DIR_RIGHT
					If rightCollision(xv)
						xv = 0
						x = x + distance
					Else
						xv = xv - GRAVITY
						If xv <= 0 
							xv = 0
						EndIf
					EndIf
			End Select
		EndIf
	End Method 



End Type 



Function fillmap()
	Local line:String 
	For Local y:Int = 0 To MAP_HEIGHT - 1
		ReadData line 
		For Local x:Int = 0 To MAP_WIDTH - 1
		
			map[x,y] = Int(Mid(line,x+1,1))
			
		Next
	Next 
	
End Function 
			



Function RectsOverlap:Int(x0:Float, y0:Float, w0:Float, h0:Float, x2:Float, y2:Float, w2:Float, h2:Float)
	If x0 > (x2 + w2) Or (x0 + w0) < x2 Then Return False
	If y0 > (y2 + h2) Or (y0 + h0) < y2 Then Return False
	Return True
End Function




DefData "11111111111111111111"
DefData "11010101010101010101"
DefData "10000000000000000001"
DefData "11110000000000111111"
DefData "10000000000000000001"
DefData "10000000000000000001"
DefData "10000000111100000001"
DefData "10000000000000000001"
DefData "11110000000000000001"
DefData "10000000000000000001"
DefData "10000000001110001111"
DefData "10000000000000000001"
DefData "10000000000000000001"
DefData "10000000000000000001"
DefData "11111111111111111111"


It works, in a sense, but is far from perfect. At times, it will put me off of the screen for no apparent reason, along with a few other quirks. I was wondering, for one, can anyone tell me what I can improve/fix to make the collisions work better? Even better, does anyone have some blitzmax code already written that shows basic collision detection? All help is appreciated.