Collision...

BlitzMax Forums/BlitzMax Beginners Area/Collision...

po(Posted 2008) [#1]
Say I have two squares. One square is moved around with the cursor keys (the player), the other is stationary (a wall). Would it be possible to stop the player from entering the wall, if you don't know the wall's position or scale? Also: the player's movement may not move one pixel at a time.


xlsior(Posted 2008) [#2]
Presumable you're drawing it, so you ought to know the position....


LarsG(Posted 2008) [#3]
If you don't know the walls position or scal, then you might want to readpixel the corners of the players square.
And do the check before you actually move the player, so that you don't get the collision after the player is "inside" the wall.


z80jim(Posted 2008) [#4]
lets see if this helps... and please note this is not supposed to be runable code :D

playerx:int
playery:int
objectx:int
objecty:int
size1:int
size2:int

while
cls
gosub move
gosub checkcollision
gosub draw
flip
wend

function move:
if keydown(key_left) then playerx=playerx-1
etc...
etc...
etc...
endfunction


function checkcollision:
if playerx+size1 > objectx then playerx+size1 = objectx
if playerx < objectx+size2 then playerx = objectx+size2

if playery+size1 > objecty then playery+size1 = objecty
if playery < objecty+size2 then playery = objecty+size2
endfunction


function draw:
setcolor 255,0,0
drawrect playerx,playery,size1,size1
setcolor 0,0,255
drawrect objectx,objecty,size2,size2
endfunction



turn that code into usable code and run it. You should be able to run into the object and be repelled.


z80jim(Posted 2008) [#5]
I apologize I ran my code after fixing it to see if it works and it doesn't seem to work after all... here's an updated code that actually runs though it has a problem.
Global playerx:Int = 50
Global playery:Int = 50
Global objectx:Int = 100
Global objecty:Int = 100
Global size1:Int
Global size2:Int
Global extra:Int

Graphics 640,480

While Not KeyHit(key_Q)
Cls
move()
checkcollision()
draw()
Flip
Wend

Function move()
If KeyDown(key_left) Then playerx=playerx-1
If KeyDown(key_right) Then playerx=playerx+1
If KeyDown(key_up) Then playery=playery-1
If KeyDown(key_down) Then playery=playery+1
EndFunction


Function checkcollision()
extra=playerx+20
If playerx+20 > objectx And playery+20 > objecty And playery < objecty+20 Then extra = objectx
extra=objectx+20
If playerx < objectx+20 And playery+20 > objecty And playery < objecty+20 Then playerx = extra
extra=playery+20
If playery+20 > objecty And playerx+20 > objectx And playerx < objectx+20 Then extra = objecty
extra=objecty+20
If playery < objecty+20 And playerx+20 > objectx And playerx < objectx+20 Then playery = extra
EndFunction


Function draw()
SetColor 255,0,0
DrawRect playerx,playery,20,20
SetColor 0,0,255
DrawRect objectx,objecty,20,20
EndFunction


po(Posted 2008) [#6]
Oops forgot about this thread. Thanks all.
I must not be thinking straight, but how would I stop the rects from overlapping in a scenario similar to the code above (knowing the position and scale of everything), only not bugged? Here's some code:
SuperStrict

Graphics(400,300,0)

Local x1%=10,y1%=10,x2%=200,y2%=200
Local w1%=15,h1%=10,w2%=20,h2%=30

While Not KeyHit(KEY_ESCAPE)

	SetColor(255,255,255)
	DrawRect(x1,y1,w1,h1)
	
	SetColor(255,255,0)
	DrawRect(x2,y2,w2,h2)
	
	If KeyDown(KEY_UP) Then y1=y1-2
	If KeyDown(KEY_DOWN) Then y1=y1+2
	If KeyDown(KEY_LEFT) Then x1=x1-2
	If KeyDown(KEY_RIGHT) Then x1=x1+2	
	
	If RectsOverlap(x1,y1,w1,h1,x2,y2,w2,h2) Then
		x1=x2-w1
	EndIf
	
	Flip;Cls;ResetCollisions
	
Wend

End

Function RectsOverlap%(x1%,y1%,w1%,h1%,x2%,y2%,w2%,h2%)

	If x1+w1>x2 And y1+h1>y2 And x1<x2+w2 And y1<y2+h2 Then
		Return True
	Else
		Return False
	EndIf

End Function



Retimer(Posted 2008) [#7]

SuperStrict

Graphics(400,300,0)

Local x1%=10,y1%=10,x2%=200,y2%=200
Local w1%=15,h1%=10,w2%=20,h2%=30
Local TmpX:Int,TmpY:Int
While Not KeyHit(KEY_ESCAPE)

	SetColor(255,255,255)
	DrawRect(x1,y1,w1,h1)
	
	SetColor(255,255,0)
	DrawRect(x2,y2,w2,h2)
	TmpX = x1
	TmpY = y1
	If KeyDown(KEY_UP) Then TmpY=TmpY-2
	If KeyDown(KEY_DOWN) Then TmpY=TmpY+2
	If KeyDown(KEY_LEFT) Then TmpX=TmpX-2
	If KeyDown(KEY_RIGHT) Then TmpX=TmpX+2	
	
	If Not RectsOverlap(TmpX,TmpY,w1,h1,x2,y2,w2,h2) Then
		x1=tmpX
		y1=tmpY
	EndIf
	
	Flip;Cls;ResetCollisions
	
Wend

End

Function RectsOverlap%(x1%,y1%,w1%,h1%,x2%,y2%,w2%,h2%)

	If x1+w1>x2 And y1+h1>y2 And x1<x2+w2 And y1<y2+h2 Then
		Return True
	Else
		Return False
	EndIf

End Function



Try that out. It checks if it collides BEFORE changing the position, rather than after. If it doesn't collide, then the move is made.


po(Posted 2008) [#8]
Thanks, that works, but change the moving speed to something like 7 or 13 and you get large gaps in the collision. Is there a way to remove these gaps? Move the temp rect back a pixel until it no longer collides then place the real rect there?


Retimer(Posted 2008) [#9]


Probobly not the best method but it does accurate collision detection. It does partial collision checks depending on the direction of the box.


po(Posted 2008) [#10]
I see, thanks.


CGV(Posted 2008) [#11]
Any idea why the collision fails when moving up?
It works perfectly in the other three directions.


Retimer(Posted 2008) [#12]


Fixed, sorry.


po(Posted 2008) [#13]
Now I'm just wondering how I could do that except with mouse control. :/


Retimer(Posted 2008) [#14]


Something like that?


po(Posted 2008) [#15]
Ah, yes. Precisely. Thanks.