Programming collisions with ZoomSprite3D()

Advanced game related topics
DriakTravo
Enthusiast
Enthusiast
Posts: 346
Joined: Fri Oct 10, 2003 12:42 am
Location: Tampa,FL,USA
Contact:

Programming collisions with ZoomSprite3D()

Post by DriakTravo »

What would be the best way to determine a collision between a regular sprite and a 3d one that has been zoomed or rotated.?
User avatar
kenmo
Addict
Addict
Posts: 2033
Joined: Tue Dec 23, 2003 3:54 am

Post by kenmo »

If you want pixel-perfect collision, that would be difficult. If you just want rotated box collision, I could post some code for you.
User avatar
kenmo
Addict
Addict
Posts: 2033
Joined: Tue Dec 23, 2003 3:54 am

Post by kenmo »

Eh here it is anyway.

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
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

Nice Kenmo.
However, perhaps it is an unnecessary work; isn't this implemented in DX9 stuff?
I need collision detection for 3D and 2D sprites for my projects, but should be made by hardware (DX9 compatible VGAs) because of a speed matter.
Lets hope PB 4.00 and after includes advanced collision detection... I'm impatient for that and many other DX9 stuff. Else, maybe my only hope is Sprite3DReal lib by S. Moebius, or other lib which support DX9 or after.
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
DriakTravo
Enthusiast
Enthusiast
Posts: 346
Joined: Fri Oct 10, 2003 12:42 am
Location: Tampa,FL,USA
Contact:

Post by DriakTravo »

Thanks for that awsome demo! It helped a little bit but my program would be alot better if I could figure out how to do pixel by pixel collisions. The only way that works so far is if I draw just the rotated/zoomed sprite on the screen by itself and use GrabSprite() to make a regular sprite out of it but doing that each frame eats up the framerate like crazy.
MadMax
Enthusiast
Enthusiast
Posts: 237
Joined: Mon Oct 06, 2003 11:56 am

Post by MadMax »

@ TriacDavo, That's the system I use, but I don't notice any significan't drop in speed.
DriakTravo
Enthusiast
Enthusiast
Posts: 346
Joined: Fri Oct 10, 2003 12:42 am
Location: Tampa,FL,USA
Contact:

Post by DriakTravo »

hrm... would you mind giving a code snip of display and grabbing of the sprite?
Post Reply