Programming collisions with ZoomSprite3D()
Posted: Tue Sep 27, 2005 2:48 pm
What would be the best way to determine a collision between a regular sprite and a 3d one that has been zoomed or rotated.?
http://www.purebasic.com
https://www.purebasic.fr/english/
Code: Select all
; PureBasic Rotated Box Collision Checker by kenmo
; Based on http://www.ragestorm.net/tutorial?id=22
Structure Vector2D
x.f
y.f
EndStructure
Structure RotRect
C.Vector2D
S.Vector2D
Ang.f
Color.l
EndStructure
Procedure AddVectors2D(*v1.Vector2D,*v2.Vector2D)
*v1\x+*v2\x : *v1\y+*v2\y
EndProcedure
Procedure SubVectors2D(*v1.Vector2D,*v2.Vector2D)
*v1\x-*v2\x : *v1\y-*v2\y
EndProcedure
Procedure RotateVector2DClockwise(*v.Vector2D,ang.f)
t.f : cosa.f=Cos(ang) : sina.f=Sin(ang)
t=*v\x : *v\x=t*cosa+*v\y*sina : *v\y=-t*sina+*v\y*cosa
EndProcedure
Procedure CopyVector2D(*v1.Vector2D,*v2.Vector2D)
*v1\x=*v2\x : *v1\y=*v2\y
EndProcedure
Procedure.l RotRectsCollision(*rr1.RotRect,*rr2.RotRect)
A.Vector2D : B.Vector2D
C.Vector2D
BL.Vector2D : TR.Vector2D
ang.f=*rr1\ang-*rr2\ang
cosa.f=Cos(ang)
sina.f=Sin(ang)
t.f : x.f : af.f
dx.f
ext1.f : ext2.f
CopyVector2D(C,*rr2\C)
SubVectors2D(C,*rr1\C)
RotateVector2DClockwise(C,*rr2\ang)
CopyVector2D(BL,C) : CopyVector2D(TR,C)
SubVectors2D(BL,*rr2\S)
AddVectors2D(TR,*rr2\S)
A\x=-(*rr1\S\y)*sina : B\x=A\x : t=(*rr1\S\x)*cosa : A\x+t : B\x-t
A\y=(*rr1\S\y)*cosa : B\y=A\y : t=(*rr1\S\x)*sina : A\y+t : B\y-t
t=sina*cosa
If t<0.0
t=A\x : A\x=B\x : B\x=t
t=A\y : A\y=B\y : B\y=t
EndIf
If sina<0.0 : B\x=-B\x : B\y=-B\y : EndIf
If B\x>TR\x Or B\x>-BL\x : ProcedureReturn 0 : EndIf
If t=0.0
ext1=A\y : ext2=-ext1
Else
x=BL\x-A\x : af=TR\x-A\x
ext1=A\y
If af*x>0.0
dx=A\x
If x<0.0
dx-B\x : ext1-B\y : x=af
Else
dx+B\x : ext1+B\y
EndIf
ext1*x : ext1/dx : ext1+A\y
EndIf
x=BL\x+A\x : af=TR\x+A\x
ext2=-A\y
If af*x>0.0
dx=-A\x
If x<0.0
dx-B\x : ext2-B\y : x=af
Else
dx+B\x : ext2+B\y
EndIf
ext2*x : ext2/dx : ext2-A\y
EndIf
EndIf
tmp.l=(ext1<BL\y And ext2<BL\y) : res.l=0
If ((ext1<BL\y And ext2<BL\y) Or (ext1>TR\y And ext2>TR\y))=0
res.l=1
EndIf
ProcedureReturn res
EndProcedure
Procedure RotatePoint(*Point.Vector2D,Ang.f)
nx.f : ny.f
sina.f=Sin(ang) : cosa.f=Cos(ang)
nx=*Point\x*cosa-*Point\y*sina : ny=*Point\y*cosa+*Point\x*sina
*Point\x=nx : *Point\y=ny
EndProcedure
If InitSprite()=0 Or InitKeyboard()=0 Or InitMouse()=0 : MessageRequester("Error","Couldn't initialized!",#MB_ICONHAND) : End : EndIf
MessageRequester("Info","Rotated Rectangle Collision demo by kenmo"+Chr(10)+FormatDate("Compiled %mm/%dd/%yyyy, %hh:%ii",Date()),#MB_ICONINFORMATION)
If OpenScreen(640,480,16,"")=0
MessageRequester("Error","Couldn't initialize screen!",#MB_ICONHAND) : End :
EndIf
SetFrameRate(60)
Rects.l=2
Dim RR.RotRect(Rects-1)
RR(0)\S\x=25 : RR(0)\S\y=25
RR(0)\C\x=320 : RR(0)\C\y=100
RR(0)\Color=RGB(192,0,0)
RR(1)\S\x=Random(50)+10 : RR(1)\S\y=Random(50)+10 : RR(1)\Ang=Random(359)*3.14159265/180.0
RR(1)\C\x=320 : RR(1)\C\y=240
RR(1)\Color=RGB(0,0,192)
Autorotate.b=1
Dialogs.b=6 : Dim Dialog.s(Dialogs-1) : DialogFlag.b : DialogTime.l : DialogN.l
Dialog(0)="Move the red rectangle with the mouse."
Dialog(1)="Left-click and drag to resize it."
Dialog(2)="Right-click and drag left/right to rotate it."
Dialog(3)="Press Space to randomize center rectangle."
Dialog(4)="Press Enter to toggle Auto-rotate."
Dialog(5)="Press Escape to exit."
Dim Vec.Vector2D(3)
Repeat
ClearScreen(21,21,21) : ExamineKeyboard() : ExamineMouse()
Gosub control
Gosub render
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
End
control:
If KeyboardPushed(#PB_Key_Space)
RR(1)\S\x=Random(50)+10 : RR(1)\S\y=Random(50)+10 : RR(1)\Ang=Random(359)*3.14159265/180.0
EndIf
If KeyboardReleased(#PB_Key_Return)
Autorotate=1-Autorotate
EndIf
If Autorotate
RR(1)\Ang+3.14159265/360.0
EndIf
If MouseButton(1)
RR(0)\S\x+MouseDeltaX() : If RR(0)\S\x<=0.0 : RR(0)\S\x=1.0 : EndIf
RR(0)\S\y+MouseDeltaY() : If RR(0)\S\y<=0.0 : RR(0)\S\y=1.0 : EndIf
ElseIf MouseButton(2)
RR(0)\Ang+MouseDeltaX()/90.0
Else
RR(0)\C\x+MouseDeltaX() : RR(0)\C\y+MouseDeltaY()
EndIf
Return
render:
If StartDrawing(ScreenOutput())
DrawingMode(5) : Locate(0,0)
If RotRectsCollision(RR(0),RR(1))
FrontColor(36,229,36) : DrawText(">:O 'Hey man, you're colliding!'")
Else
FrontColor(247,247,247) : DrawText(">:( 'No collisions here.'")
EndIf
If Date()-dialogtime>(1+DialogFlag*2) : DialogFlag=1-DialogFlag : DialogTime=Date() : If DialogFlag=0 : DialogN+1 : If DialogN=Dialogs : DialogN=0 : EndIf : EndIf : EndIf
FrontColor(247,247,247) : Locate(0,460)
If DialogFlag
DrawText(">:O '"+Dialog(DialogN)+"'")
Else
DrawText(">:(")
EndIf
For tmp=0 To Rects-1
TmpX=RR(tmp)\C\x : TmpY=RR(tmp)\C\y : TmpW=RR(tmp)\S\x : TmpH=RR(tmp)\S\y : TmpA.f=RR(tmp)\Ang
Vec(0)\x=-TmpW : Vec(0)\y=TmpH : RotatePoint(Vec(0),TmpA) : Vec(0)\x+TmpX : Vec(0)\y+TmpY
Vec(1)\x=TmpW : Vec(1)\y=TmpH : RotatePoint(Vec(1),TmpA) : Vec(1)\x+TmpX : Vec(1)\y+TmpY
Vec(2)\x=TmpW : Vec(2)\y=-TmpH : RotatePoint(Vec(2),TmpA) : Vec(2)\x+TmpX : Vec(2)\y+TmpY
Vec(3)\x=-TmpW : Vec(3)\y=-TmpH : RotatePoint(Vec(3),TmpA) : Vec(3)\x+TmpX : Vec(3)\y+TmpY
LineXY(Vec(0)\x,Vec(0)\y,Vec(1)\x,Vec(1)\y,RR(tmp)\Color)
LineXY(Vec(1)\x,Vec(1)\y,Vec(2)\x,Vec(2)\y)
LineXY(Vec(2)\x,Vec(2)\y,Vec(3)\x,Vec(3)\y)
LineXY(Vec(3)\x,Vec(3)\y,Vec(0)\x,Vec(0)\y)
Next tmp
StopDrawing()
EndIf
Return