I'm trying to implement Sweep AABB collisions for the first time based on this gamedev article:
http://www.gamedev.net/page/resource...response-r3084
And what this is used for is collisions for fast moving objects. If you were to use a simple bounding box check, itll never register a collision because the object goes through the object. Sweep AABB helps prevent that.
However I ran into a snag. His broadphase box is wrong. What a broadphase box is, is a box that is invisible but is used for collision by creating a box combining the old position and new position after moving which looks like this:
![]()
The broadphase box in the article on the otherhand is backwards:
Where x and y are positions, w and h are width and height, and vx and vy are velocities. What this does is that it puts the box in front of the box rather than trail behind. This means that a collision will occur before the object will actually collide into the object! I created the same code only a tad different:
Now its the same code but I want the box to trail behind and look like the picture I have above rather than have the broadphase box heading up front. I tried playing with it and adding different things but it ended up a complete mess. If anyone whos got bigger brains than I do, I could sure use some help. Thanks in advance :bigyello:
Also here is the code I currently have:
http://www.gamedev.net/page/resource...response-r3084
And what this is used for is collisions for fast moving objects. If you were to use a simple bounding box check, itll never register a collision because the object goes through the object. Sweep AABB helps prevent that.
However I ran into a snag. His broadphase box is wrong. What a broadphase box is, is a box that is invisible but is used for collision by creating a box combining the old position and new position after moving which looks like this:
The broadphase box in the article on the otherhand is backwards:
Code:
Box GetSweptBroadphaseBox(Box b)
{
Box broadphasebox;
broadphasebox.x = b.vx > 0 ? b.x : b.x + b.vx;
broadphasebox.y = b.vy > 0 ? b.y : b.y + b.vy;
broadphasebox.w = b.vx > 0 ? b.vx + b.w : b.w - b.vx;
broadphasebox.h = b.vy > 0 ? b.vy + b.h : b.h - b.vy;
return broadphasebox;
}
vb Code:
Private Function GetSweptBroadphaseBox(B As Sprite_Type) As Sprite_Type Dim broadphasebox As Sprite_Type With broadphasebox If B.Velocity.X > 0 Then .Position.X = B.Position.X .Width = B.Velocity.X + B.Width ElseIf B.Velocity.X < 0 Then .Position.X = B.Position.X + B.Velocity.X .Width = B.Width - B.Velocity.X Else .Position.X = B.Position.X .Width = B.Width End If If B.Velocity.Y > 0 Then .Position.Y = B.Position.Y .Height = B.Velocity.Y + B.Height ElseIf B.Velocity.Y < 0 Then .Position.Y = B.Position.Y + B.Velocity.Y .Height = B.Height - B.Velocity.Y Else .Position.Y = B.Position.Y .Height = B.Height End If End With GetSweptBroadphaseBox = broadphasebox End Function
Now its the same code but I want the box to trail behind and look like the picture I have above rather than have the broadphase box heading up front. I tried playing with it and adding different things but it ended up a complete mess. If anyone whos got bigger brains than I do, I could sure use some help. Thanks in advance :bigyello:
Also here is the code I currently have:
vb Code:
Option Explicit Private Type Vector2D X As Single Y As Single End Type Private Type Sprite_Type Old_Position As Vector2D Position As Vector2D Width As Long Height As Long Velocity As Vector2D Speed As Long Normal As Vector2D Color As Long End Type Private Declare Function timeGetTime Lib "winmm.dll" () As Long Private Player As Sprite_Type Private Monster As Sprite_Type Private Const BUTTON_UP As Long = vbKeyW Private Const BUTTON_DOWN As Long = vbKeyS Private Const BUTTON_LEFT As Long = vbKeyA Private Const BUTTON_RIGHT As Long = vbKeyD Private Const BUTTON_UP_FLAG As Long = 1 Private Const BUTTON_DOWN_FLAG As Long = 2 Private Const BUTTON_LEFT_FLAG As Long = 4 Private Const BUTTON_RIGHT_FLAG As Long = 8 Private INFINITY As Double Private NEG_INFINITY As Double Private Running As Boolean Private Key_State As Long Private Milliseconds As Long Private Get_Frames_Per_Second As Long Private Frame_Count As Long Dim xInvEntry As Single, yInvEntry As Single Dim xInvExit As Single, yInvExit As Single Dim xEntry As Single, yEntry As Single Dim xExit As Single, yExit As Single Dim entryTime As Single Dim exitTime As Single Private Function Get_Elapsed_Time() As Single Dim Current_Time As Long Current_Time = timeGetTime Get_Elapsed_Time = CSng(Current_Time) / 1000 End Function Private Sub Lock_Framerate(ByVal Target_FPS As Long) Static Last_Time As Long Dim Current_Time As Long Dim FPS As Single Do Current_Time = timeGetTime FPS = 1000 / CSng(Current_Time - Last_Time) Loop While (FPS > Target_FPS) Last_Time = timeGetTime End Sub Private Function Get_FPS() As String Frame_Count = Frame_Count + 1 If Get_Elapsed_Time() - Milliseconds >= 1 Then Get_Frames_Per_Second = Frame_Count Frame_Count = 0 Milliseconds = Convert.ToInt32(Get_Elapsed_Time) End If Get_FPS = "Frames Per Second: " & Csngg(Get_Frames_Per_Second) End Function Public Sub Setup_Infinity() On Error Resume Next INFINITY = 1 / 0 On Error GoTo 0 NEG_INFINITY = -INFINITY End Sub Private Function Max(A As Single, B As Single) As Single If A >= B Then Max = A Else Max = B End Function Private Function Min(A As Single, B As Single) As Single If A <= B Then Min = A Else Min = B End Function Private Sub Get_Velocity(Sprite As Sprite_Type) With Sprite .Velocity.X = .Position.X - .Old_Position.X .Velocity.Y = .Position.Y - .Old_Position.Y End With End Sub Private Function AABBCheck(B1 As Sprite_Type, B2 As Sprite_Type) As Boolean AABBCheck = Not (B1.Position.X + B1.Width < B2.Position.X Or _ B1.Position.X > B2.Position.X + B2.Width Or _ B1.Position.Y + B1.Height < B2.Position.Y Or _ B1.Position.Y > B2.Position.Y + B2.Height) End Function Private Function GetSweptBroadphaseBox(B As Sprite_Type) As Sprite_Type Dim broadphasebox As Sprite_Type With broadphasebox If B.Velocity.X > 0 Then .Position.X = B.Position.X .Width = B.Velocity.X + B.Width ElseIf B.Velocity.X < 0 Then .Position.X = B.Position.X + B.Velocity.X .Width = B.Width - B.Velocity.X Else .Position.X = B.Position.X .Width = B.Width End If If B.Velocity.Y > 0 Then .Position.Y = B.Position.Y .Height = B.Velocity.Y + B.Height ElseIf B.Velocity.Y < 0 Then .Position.Y = B.Position.Y + B.Velocity.Y .Height = B.Height - B.Velocity.Y Else .Position.Y = B.Position.Y .Height = B.Height End If End With GetSweptBroadphaseBox = broadphasebox End Function Private Function Sweep_Collision_Detection(B1 As Sprite_Type, B2 As Sprite_Type) As Single 'find the distance between the objects on the near and far sides for both x and y If B1.Velocity.X > 0 Then xInvEntry = B2.Position.X - (B1.Position.X + B1.Width) xInvExit = (B2.Position.X + B2.Width) - B1.Position.X Else xInvEntry = (B2.Position.X + B2.Width) - B1.Position.X xInvExit = B2.Position.X - (B1.Position.X + B1.Width) End If If B1.Velocity.Y > 0 Then yInvEntry = B2.Position.Y - (B1.Position.Y + B1.Height) yInvExit = (B2.Position.Y + B2.Height) - B1.Position.Y Else yInvEntry = (B2.Position.Y + B2.Height) - B1.Position.Y yInvExit = B2.Position.Y - (B1.Position.Y + B1.Height) End If 'find time of collision and time of leaving for each axis (if statement is to prevent divide by zero) If B1.Velocity.X = 0 Then xEntry = CSng(NEG_INFINITY) xExit = CSng(INFINITY) Else xEntry = xInvEntry / B1.Velocity.X xExit = xInvExit / B1.Velocity.X End If If B1.Velocity.Y = 0 Then yEntry = CSng(NEG_INFINITY) yExit = CSng(INFINITY) Else yEntry = yInvEntry / B1.Velocity.Y yExit = yInvExit / B1.Velocity.Y End If entryTime = Max(xEntry, yEntry) exitTime = Min(xExit, yExit) If entryTime > exitTime Then Sweep_Collision_Detection = 1 Exit Function End If If (xEntry < 0 And yEntry < 0) Then Sweep_Collision_Detection = 1 Exit Function End If If xEntry < 0 Then If (B1.Position.X + B1.Width) < B2.Position.X Or B1.Position.X > (B2.Position.X + B2.Width) Then Sweep_Collision_Detection = 1 Exit Function End If End If 'if there was a collision 'calculate normal of collided surface If xEntry > yEntry Then If xInvEntry < 0 Then B1.Normal.X = 1 B1.Normal.Y = 0 Else B1.Normal.X = -1 B1.Normal.Y = 0 End If Else If yInvEntry < 0 Then B1.Normal.X = 0 B1.Normal.Y = 1 Else B1.Normal.X = 0 B1.Normal.Y = -1 End If End If 'return the time of collision Sweep_Collision_Detection = entryTime End Function Private Function Check_Key(Key_Flag As Long) As Long Check_Key = Key_State And Key_Flag End Function Private Sub Keyboard_Controls() With Player If Check_Key(BUTTON_UP_FLAG) Then .Position.Y = .Position.Y - .Speed End If If Check_Key(BUTTON_DOWN_FLAG) Then .Position.Y = .Position.Y + .Speed End If If Check_Key(BUTTON_LEFT_FLAG) Then .Position.X = .Position.X - .Speed End If If Check_Key(BUTTON_RIGHT_FLAG) Then .Position.X = .Position.X + .Speed End If End With End Sub Private Sub Draw_Rectangle(ByVal X As Long, ByVal Y As Long, ByVal Width As Long, ByVal Height As Long, ByVal Color As Long) frmMain.Line (X, Y)-(X + Width, Y + Height), Color, B End Sub Private Sub Draw_Filled_Rectangle(ByVal X As Long, ByVal Y As Long, ByVal Width As Long, ByVal Height As Long, ByVal Color As Long) frmMain.Line (X, Y)-(X + Width, Y + Height), Color, BF End Sub Private Sub Main() With frmMain .Show .BackColor = RGB(0, 0, 0) .ForeColor = RGB(0, 255, 0) .ScaleMode = vbPixels .AutoRedraw = True End With With Player .Width = 30 .Height = 30 .Position.X = (frmMain.ScaleWidth / 2) - (.Width / 2) .Position.Y = (frmMain.ScaleHeight / 2) - (.Height / 2) .Color = RGB(0, 55, 0) .Speed = 10 End With With Monster .Width = 30 .Height = 30 .Position.X = (frmMain.ScaleWidth / 2) - (.Width / 2) + 50 .Position.Y = (frmMain.ScaleHeight / 2) - (.Height / 2) .Color = RGB(255, 0, 0) .Speed = 1 End With Setup_Infinity Milliseconds = Get_Elapsed_Time Running = True Do While Running = True frmMain.Cls Player.Old_Position = Player.Position Keyboard_Controls Get_Velocity Player Dim broadphasebox As Sprite_Type broadphasebox = GetSweptBroadphaseBox(Player) If AABBCheck(broadphasebox, Monster) Then frmMain.Caption = "hit" Else frmMain.Caption = "Form1" 'Sweep_Collision_Detection Player, Monster 'frmMain.Caption = Sweep_Collision_Detection(Player, Monster) 'frmMain.Print entryTime, exitTime 'frmMain.Print xEntry, xExit 'frmMain.Print xExit, yExit 'frmMain.Print Player.Velocity.X, Player.Velocity.Y Draw_Filled_Rectangle Monster.Position.X, Monster.Position.Y, Monster.Width, Monster.Height, Monster.Color Draw_Filled_Rectangle Player.Position.X, Player.Position.Y, Player.Width, Player.Height, Player.Color Draw_Rectangle broadphasebox.Position.X, broadphasebox.Position.Y, broadphasebox.Width, broadphasebox.Height, RGB(255, 255, 255) Lock_Framerate 60 DoEvents Loop End Sub Private Sub Shutdown() Running = False Unload Me End Sub Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) Select Case KeyCode Case BUTTON_UP Key_State = Key_State Or BUTTON_UP_FLAG Case BUTTON_DOWN Key_State = Key_State Or BUTTON_DOWN_FLAG Case BUTTON_LEFT Key_State = Key_State Or BUTTON_LEFT_FLAG Case BUTTON_RIGHT Key_State = Key_State Or BUTTON_RIGHT_FLAG Case vbKeyEscape Shutdown End Select End Sub Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer) Select Case KeyCode Case BUTTON_UP Key_State = Key_State And (Not BUTTON_UP_FLAG) Case BUTTON_DOWN Key_State = Key_State And (Not BUTTON_DOWN_FLAG) Case BUTTON_LEFT Key_State = Key_State And (Not BUTTON_LEFT_FLAG) Case BUTTON_RIGHT Key_State = Key_State And (Not BUTTON_RIGHT_FLAG) End Select End Sub Private Sub Form_Load() Main End Sub Private Sub Form_Unload(Cancel As Integer) Shutdown End Sub