2D collision, needs criticizing =D

BlitzPlus Forums/BlitzPlus Programming/2D collision, needs criticizing =D

InvincibleWall(Posted 2010) [#1]
I am very new at BlitzPlus and so I would like to know how to do things better. So if you would like to take the time to read through my code I would appreciate any advice you could give

I would prefer though that you would tell me how to do it right not just what i did wrong

the point of this engine is to be able to make Blocks that the player can
react with, without changing the if's and then's to accommodate the new object. These Blocks are created with Create_Block which is well marked so that you can mess around with it yourself

this is the .png you need
the other isn't used yet

http://img837.imageshack.us/f/gear1h.png/

PS: I know there are some useless things in there, They are for future use and testing (example: the Global x readout in the top-left hand corner)

AppTitle "Robot Brawl"
AutoMidHandle True
Graphics 640,480,0,2

Const ESCKEY = 1,ENTERKEY = 28, UPKEY = 200, LEFTKEY = 203, DOWNKEY = 208, RIGHTKEY = 205, AKEY = 30, WKEY = 1


Global Robot1=LoadAnimImage("Images/Robots/Gear1.png",64,64,0,4)
Global Robot2=LoadAnimImage("Images/Robots/Gear2.png",64,64,0,2)
MaskImage Robot1,255,255,255
MaskImage Robot2,255,255,255
ClsColor 160,180,255
Timer=CreateTimer(35)

Type Robot
	Field x,y,xv,yv,mxv,myv
	Field f,j1,j2,j3
	Field w,h
	Field atk,mHP,cHP
End Type

Type Block
	Field x,y
	Field w,h
	Field r,g,b
End Type

Global R1.Robot = New Robot
R1\x = 300
R1\h = 24
R1\w = 20
R1\mxv = 10
R1\myv = -3
R1\mHP = 100
R1\cHP = 50

;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
;@@@@@@@@@@		CHANGE THESE	@@@@@@@@@@@@@@
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

;Create_Block(x,y,Width,Height,Red,Green,Blue)

;@@@@@@@@@@@@@		WARNING		@@@@@@@@@@@@@@
;@@@@@@	they are handled from the center @@@@@
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Create_Block(320,470,640,30,50,200,50)
Create_Block(230,200,200,30,50,200,50)

;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Global x = 0

;---------------------------------------------------------------------------------------------------
;---------------------------------------------------------------------------------------------------

While Not KeyDown(ESCKEY)

	Draw()
	
If TimerTicks(Timer) >= 1
	x = R1\x
	Gravity()
	Friction()
	Move_LR()
	Move_UD()
	Reset()
	ResetTimer(Timer)
End If
Wend

EndGraphics
FreeImage (Robot1)
FreeImage (Robot2)

;---------------------------------------------------------------------------------------------------
;---------------------------------------------------------------------------------------------------

Function Draw()
	Cls
	DrawImage Robot1,R1\x,R1\y,R1\f
	Draw_Block()
	DrawHUD()
	Text 0,0,x
	Flip
End Function

;---------------------------------------------------------------------------------------------------

Function Draw_Block()
	For Block.Block = Each Block
		Color Block\r,Block\g,Block\b
		Bx = Block\x - Block\w/2
		By = Block\y - Block\h/2
		Rect Bx,By,Block\w,Block\h
	Next
End Function

;---------------------------------------------------------------------------------------------------

Function DrawHUD()
	Color 0,0,0
	Rect 615,20,15,100,0
	Color 255,0,0
	Rect 618,21+R1\mHP-R1\cHP,9,98-R1\mHP+R1\cHP,1
End Function

;---------------------------------------------------------------------------------------------------

Function Reset()
	If KeyHit(AKEY)
		R1\x = 300
		R1\y = 0
		R1\yv = 0
		R1\xv = 0
		FlushKeys
	End If
End Function

;---------------------------------------------------------------------------------------------------

Function Move_LR()
	
	Select KeyDown_LR()
		Case RIGHTKEY
			If R1\xv < R1\mxv
				R1\xv = R1\xv + 1
				R1\f = 1
			End If
		Case LEFTKEY
			If R1\xv > -R1\mxv
				R1\xv = R1\xv - 1
				R1\f = 0
			End If
		Default
	End Select
	
End Function

;---------------------------------------------------------------------------------------------------

Function Move_UD()
	
	Select KeyDown_UD()
		Case UPKEY
			If R1\yv > R1\myv
				R1\yv = R1\yv - 1
			End If
			If R1\f < 2
				R1\f = R1\f + 2
			End If
		Default
	End Select
	
End Function

;---------------------------------------------------------------------------------------------------

Function KeyDown_LR()

	If KeyDown(RIGHTKEY)
		Return RIGHTKEY
	Else If KeyDown(LEFTKEY)
		Return LEFTKEY
	End If
	
End Function

;---------------------------------------------------------------------------------------------------

Function KeyDown_UD()

	If KeyDown(UPKEY)
		Return UPKEY
	Else If KeyDown(DOWNKEY)
		Return DOWNKEY
	End If
	
End Function

;---------------------------------------------------------------------------------------------------

Function Friction()

	R1\x = R1\x + R1\xv
	
	If R1\xv > 0 And KeyDown_LR() = False
		R1\xv = R1\xv - 1
	Else If R1\xv < 0 And KeyDown_LR() = False
		R1\xv = R1\xv + 1
	End If

	If TooFast_L()
		R1\x = TooFast_L()
		R1\xv = 0
	Else If TooFast_R()
		R1\x = TooFast_R()
		R1\xv = 0
	End If
	
End Function	

;---------------------------------------------------------------------------------------------------

Function Gravity()
	
	R1\y = R1\y + R1\yv
	
	If TooFast_D()
		R1\y = TooFast_D()
		R1\yv = 0
	Else If TooFast_U()
		R1\y = TooFast_U()
		R1\yv = 0
	Else If Block_Collision_UD() = False And KeyDown_UD() <> UPKEY
		R1\yv =  R1\yv + 1
	End If

	
End Function	

;---------------------------------------------------------------------------------------------------	
	
Function Block_Collision_UD()
	For Block.Block = Each Block
		If R1\y+R1\h = Block\y-Block\h/2 And R1\x > Block\x-Block\w/2 And R1\x < Block\x+Block\w/2
			Return True
		End If
	Next
End Function

;---------------------------------------------------------------------------------------------------

Function Block_Collision_LR()
	For Block.Block = Each Block
		If R1\x+R1\w = Block\x-Block\w/2 And R1\y > Block\y-Block\h/2 And R1\y < Block\y+Block\h/2
			Return True
		End If
	Next
End Function

;---------------------------------------------------------------------------------------------------

Function TooFast_L()
	For Block.Block = Each Block
		If R1\x-R1\w+R1\xv < Block\x+Block\w/2 And R1\x > Block\x And R1\y > Block\y-Block\h/2 And R1\y < Block\y+Block\h/2
			Return Block\x+Block\w/2+R1\w
		End If
	Next
End Function
	
;---------------------------------------------------------------------------------------------------	

Function TooFast_R()
	For Block.Block = Each Block
		If R1\x+R1\w+R1\xv > Block\x-Block\w/2 And R1\x < Block\x And R1\y > Block\y-Block\h/2 And R1\y < Block\y+Block\h/2
			Return Block\x-Block\w/2-R1\w
		End If
	Next
End Function

;---------------------------------------------------------------------------------------------------

Function TooFast_D()
	For Block.Block = Each Block
		If R1\y+R1\h+R1\yv > Block\y-Block\h/2 And R1\y < Block\y And R1\x > Block\x-Block\w/2 And R1\x < Block\x+Block\w/2
			Return Block\y-Block\h/2-R1\h
		End If
	Next
End Function

;---------------------------------------------------------------------------------------------------

Function TooFast_U()
	For Block.Block = Each Block
		If R1\y-R1\h-R1\yv < Block\y+Block\h/2 And R1\y > Block\y And R1\x > Block\x-Block\w/2 And R1\x < Block\x+Block\w/2
			Return Block\y+Block\h/2+R1\h
		End If
	Next
End Function

;---------------------------------------------------------------------------------------------------

Function Create_Block(x,y,w,h,r,g,b)
	Block.Block = New Block
	Block\x = x
	Block\y = y
	Block\w = w
	Block\h = h
	Block\r = r
	Block\g = g
	Block\b = b
End Function

;---------------------------------------------------------------------------------------------------



InvincibleWall(Posted 2010) [#2]
I would really like to know if this code is done well. I have been working on some other mechanics such as shooting and would like to add them but the basics haven't been commented on yet =\

did I put this in the right place?


Sauer(Posted 2010) [#3]
I'll take a look in a bit.


Sauer(Posted 2010) [#4]
I think it looks pretty good, especially for a beginner. The code is well commented and indented, so you're good there.

You'll notice that your collisions are not 100% accurate. They are probably close enough, but they can be improved by the common 2d box collision algorithm:

If x<Boxx+Boxw and x+w>Boxx
  ;collision
EndIf


This will return a 'horizontal' collision. For a full collision, do a similar thing with the y coordinates. If you're having trouble visualizing it, draw it out in Paint, and you'll see a collision will always happen when this is true.

Hope that helps.


InvincibleWall(Posted 2010) [#5]
Thank you =D

is that collision algorithm for a top-left handled player?