Quantcast
Channel: VBForums - Visual Basic 6 and Earlier
Viewing all articles
Browse latest Browse all 21271

[RESOLVED] Math Issues With Boxes.....

$
0
0
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:
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;
}

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:

vb Code:
  1. Private Function GetSweptBroadphaseBox(B As Sprite_Type) As Sprite_Type
  2.     Dim broadphasebox As Sprite_Type
  3.    
  4.     With broadphasebox
  5.         If B.Velocity.X > 0 Then
  6.             .Position.X = B.Position.X
  7.             .Width = B.Velocity.X + B.Width
  8.         ElseIf B.Velocity.X < 0 Then
  9.             .Position.X = B.Position.X + B.Velocity.X
  10.             .Width = B.Width - B.Velocity.X
  11.         Else
  12.             .Position.X = B.Position.X
  13.             .Width = B.Width
  14.         End If
  15.        
  16.         If B.Velocity.Y > 0 Then
  17.             .Position.Y = B.Position.Y
  18.             .Height = B.Velocity.Y + B.Height
  19.         ElseIf B.Velocity.Y < 0 Then
  20.             .Position.Y = B.Position.Y + B.Velocity.Y
  21.             .Height = B.Height - B.Velocity.Y
  22.         Else
  23.             .Position.Y = B.Position.Y
  24.             .Height = B.Height
  25.         End If
  26.     End With
  27.     GetSweptBroadphaseBox = broadphasebox
  28. 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:
  1. Option Explicit
  2.  
  3. Private Type Vector2D
  4.     X As Single
  5.     Y As Single
  6. End Type
  7.  
  8. Private Type Sprite_Type
  9.     Old_Position As Vector2D
  10.     Position As Vector2D
  11.     Width As Long
  12.     Height As Long
  13.     Velocity As Vector2D
  14.     Speed As Long
  15.     Normal As Vector2D
  16.     Color As Long
  17. End Type
  18.  
  19. Private Declare Function timeGetTime Lib "winmm.dll" () As Long
  20.  
  21. Private Player As Sprite_Type
  22. Private Monster As Sprite_Type
  23.  
  24. Private Const BUTTON_UP As Long = vbKeyW
  25. Private Const BUTTON_DOWN As Long = vbKeyS
  26. Private Const BUTTON_LEFT As Long = vbKeyA
  27. Private Const BUTTON_RIGHT As Long = vbKeyD
  28.  
  29. Private Const BUTTON_UP_FLAG As Long = 1
  30. Private Const BUTTON_DOWN_FLAG As Long = 2
  31. Private Const BUTTON_LEFT_FLAG As Long = 4
  32. Private Const BUTTON_RIGHT_FLAG As Long = 8
  33.  
  34. Private INFINITY As Double
  35. Private NEG_INFINITY As Double
  36.  
  37. Private Running As Boolean
  38. Private Key_State As Long
  39.  
  40. Private Milliseconds As Long
  41. Private Get_Frames_Per_Second As Long
  42. Private Frame_Count As Long
  43.  
  44. Dim xInvEntry As Single, yInvEntry As Single
  45. Dim xInvExit As Single, yInvExit As Single
  46. Dim xEntry As Single, yEntry As Single
  47. Dim xExit As Single, yExit As Single
  48. Dim entryTime As Single
  49. Dim exitTime As Single
  50.  
  51. Private Function Get_Elapsed_Time() As Single
  52.     Dim Current_Time As Long
  53.  
  54.     Current_Time = timeGetTime
  55.     Get_Elapsed_Time = CSng(Current_Time) / 1000
  56. End Function
  57.  
  58. Private Sub Lock_Framerate(ByVal Target_FPS As Long)
  59.     Static Last_Time As Long
  60.     Dim Current_Time As Long
  61.     Dim FPS As Single
  62.  
  63.     Do
  64.         Current_Time = timeGetTime
  65.         FPS = 1000 / CSng(Current_Time - Last_Time)
  66.     Loop While (FPS > Target_FPS)
  67.  
  68.     Last_Time = timeGetTime
  69. End Sub
  70.  
  71. Private Function Get_FPS() As String
  72.     Frame_Count = Frame_Count + 1
  73.  
  74.     If Get_Elapsed_Time() - Milliseconds >= 1 Then
  75.         Get_Frames_Per_Second = Frame_Count
  76.         Frame_Count = 0
  77.         Milliseconds = Convert.ToInt32(Get_Elapsed_Time)
  78.     End If
  79.  
  80.     Get_FPS = "Frames Per Second: " & Csngg(Get_Frames_Per_Second)
  81. End Function
  82.  
  83. Public Sub Setup_Infinity()
  84.   On Error Resume Next
  85.   INFINITY = 1 / 0
  86.   On Error GoTo 0
  87.   NEG_INFINITY = -INFINITY
  88. End Sub
  89.  
  90. Private Function Max(A As Single, B As Single) As Single
  91.     If A >= B Then Max = A Else Max = B
  92. End Function
  93.  
  94. Private Function Min(A As Single, B As Single) As Single
  95.     If A <= B Then Min = A Else Min = B
  96. End Function
  97.  
  98. Private Sub Get_Velocity(Sprite As Sprite_Type)
  99.     With Sprite
  100.         .Velocity.X = .Position.X - .Old_Position.X
  101.         .Velocity.Y = .Position.Y - .Old_Position.Y
  102.     End With
  103. End Sub
  104.  
  105. Private Function AABBCheck(B1 As Sprite_Type, B2 As Sprite_Type) As Boolean
  106.     AABBCheck = Not (B1.Position.X + B1.Width < B2.Position.X Or _
  107.                      B1.Position.X > B2.Position.X + B2.Width Or _
  108.                      B1.Position.Y + B1.Height < B2.Position.Y Or _
  109.                      B1.Position.Y > B2.Position.Y + B2.Height)
  110. End Function
  111.  
  112. Private Function GetSweptBroadphaseBox(B As Sprite_Type) As Sprite_Type
  113.     Dim broadphasebox As Sprite_Type
  114.    
  115.     With broadphasebox
  116.         If B.Velocity.X > 0 Then
  117.             .Position.X = B.Position.X
  118.             .Width = B.Velocity.X + B.Width
  119.         ElseIf B.Velocity.X < 0 Then
  120.             .Position.X = B.Position.X + B.Velocity.X
  121.             .Width = B.Width - B.Velocity.X
  122.         Else
  123.             .Position.X = B.Position.X
  124.             .Width = B.Width
  125.         End If
  126.        
  127.         If B.Velocity.Y > 0 Then
  128.             .Position.Y = B.Position.Y
  129.             .Height = B.Velocity.Y + B.Height
  130.         ElseIf B.Velocity.Y < 0 Then
  131.             .Position.Y = B.Position.Y + B.Velocity.Y
  132.             .Height = B.Height - B.Velocity.Y
  133.         Else
  134.             .Position.Y = B.Position.Y
  135.             .Height = B.Height
  136.         End If
  137.     End With
  138.     GetSweptBroadphaseBox = broadphasebox
  139. End Function
  140.  
  141. Private Function Sweep_Collision_Detection(B1 As Sprite_Type, B2 As Sprite_Type) As Single
  142.  
  143.     'find the distance between the objects on the near and far sides for both x and y
  144.     If B1.Velocity.X > 0 Then
  145.         xInvEntry = B2.Position.X - (B1.Position.X + B1.Width)
  146.         xInvExit = (B2.Position.X + B2.Width) - B1.Position.X
  147.     Else
  148.         xInvEntry = (B2.Position.X + B2.Width) - B1.Position.X
  149.         xInvExit = B2.Position.X - (B1.Position.X + B1.Width)
  150.     End If
  151.  
  152.     If B1.Velocity.Y > 0 Then
  153.         yInvEntry = B2.Position.Y - (B1.Position.Y + B1.Height)
  154.         yInvExit = (B2.Position.Y + B2.Height) - B1.Position.Y
  155.     Else
  156.         yInvEntry = (B2.Position.Y + B2.Height) - B1.Position.Y
  157.         yInvExit = B2.Position.Y - (B1.Position.Y + B1.Height)
  158.     End If
  159.    
  160.     'find time of collision and time of leaving for each axis (if statement is to prevent divide by zero)
  161.  
  162.     If B1.Velocity.X = 0 Then
  163.         xEntry = CSng(NEG_INFINITY)
  164.         xExit = CSng(INFINITY)
  165.     Else
  166.         xEntry = xInvEntry / B1.Velocity.X
  167.         xExit = xInvExit / B1.Velocity.X
  168.     End If
  169.  
  170.     If B1.Velocity.Y = 0 Then
  171.         yEntry = CSng(NEG_INFINITY)
  172.         yExit = CSng(INFINITY)
  173.     Else
  174.         yEntry = yInvEntry / B1.Velocity.Y
  175.         yExit = yInvExit / B1.Velocity.Y
  176.     End If
  177.    
  178.     entryTime = Max(xEntry, yEntry)
  179.     exitTime = Min(xExit, yExit)
  180.    
  181.     If entryTime > exitTime Then
  182.         Sweep_Collision_Detection = 1
  183.         Exit Function
  184.     End If
  185.    
  186.     If (xEntry < 0 And yEntry < 0) Then
  187.         Sweep_Collision_Detection = 1
  188.         Exit Function
  189.     End If
  190.    
  191.     If xEntry < 0 Then
  192.         If (B1.Position.X + B1.Width) < B2.Position.X Or B1.Position.X > (B2.Position.X + B2.Width) Then
  193.             Sweep_Collision_Detection = 1
  194.             Exit Function
  195.         End If
  196.     End If
  197.    
  198.     'if there was a collision
  199.     'calculate normal of collided surface
  200.     If xEntry > yEntry Then
  201.         If xInvEntry < 0 Then
  202.             B1.Normal.X = 1
  203.             B1.Normal.Y = 0
  204.         Else
  205.             B1.Normal.X = -1
  206.             B1.Normal.Y = 0
  207.         End If
  208.     Else
  209.         If yInvEntry < 0 Then
  210.             B1.Normal.X = 0
  211.             B1.Normal.Y = 1
  212.         Else
  213.             B1.Normal.X = 0
  214.             B1.Normal.Y = -1
  215.         End If
  216.     End If
  217.    
  218.     'return the time of collision
  219.     Sweep_Collision_Detection = entryTime
  220.  
  221. End Function
  222.  
  223. Private Function Check_Key(Key_Flag As Long) As Long
  224.     Check_Key = Key_State And Key_Flag
  225. End Function
  226.  
  227. Private Sub Keyboard_Controls()
  228.    
  229.     With Player
  230.         If Check_Key(BUTTON_UP_FLAG) Then
  231.             .Position.Y = .Position.Y - .Speed
  232.         End If
  233.                
  234.         If Check_Key(BUTTON_DOWN_FLAG) Then
  235.             .Position.Y = .Position.Y + .Speed
  236.         End If
  237.                
  238.         If Check_Key(BUTTON_LEFT_FLAG) Then
  239.             .Position.X = .Position.X - .Speed
  240.         End If
  241.                
  242.         If Check_Key(BUTTON_RIGHT_FLAG) Then
  243.             .Position.X = .Position.X + .Speed
  244.         End If
  245.     End With
  246. End Sub
  247.  
  248. Private Sub Draw_Rectangle(ByVal X As Long, ByVal Y As Long, ByVal Width As Long, ByVal Height As Long, ByVal Color As Long)
  249.     frmMain.Line (X, Y)-(X + Width, Y + Height), Color, B
  250. End Sub
  251.  
  252. 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)
  253.     frmMain.Line (X, Y)-(X + Width, Y + Height), Color, BF
  254. End Sub
  255.  
  256. Private Sub Main()
  257.     With frmMain
  258.         .Show
  259.         .BackColor = RGB(0, 0, 0)
  260.         .ForeColor = RGB(0, 255, 0)
  261.         .ScaleMode = vbPixels
  262.         .AutoRedraw = True
  263.     End With
  264.    
  265.     With Player
  266.         .Width = 30
  267.         .Height = 30
  268.         .Position.X = (frmMain.ScaleWidth / 2) - (.Width / 2)
  269.         .Position.Y = (frmMain.ScaleHeight / 2) - (.Height / 2)
  270.         .Color = RGB(0, 55, 0)
  271.         .Speed = 10
  272.     End With
  273.    
  274.     With Monster
  275.         .Width = 30
  276.         .Height = 30
  277.         .Position.X = (frmMain.ScaleWidth / 2) - (.Width / 2) + 50
  278.         .Position.Y = (frmMain.ScaleHeight / 2) - (.Height / 2)
  279.         .Color = RGB(255, 0, 0)
  280.         .Speed = 1
  281.     End With
  282.    
  283.     Setup_Infinity
  284.     Milliseconds = Get_Elapsed_Time
  285.     Running = True
  286.    
  287.     Do While Running = True
  288.         frmMain.Cls
  289.         Player.Old_Position = Player.Position
  290.         Keyboard_Controls
  291.         Get_Velocity Player
  292.         Dim broadphasebox As Sprite_Type
  293.         broadphasebox = GetSweptBroadphaseBox(Player)
  294.         If AABBCheck(broadphasebox, Monster) Then frmMain.Caption = "hit" Else frmMain.Caption = "Form1" 'Sweep_Collision_Detection Player, Monster
  295.         'frmMain.Caption = Sweep_Collision_Detection(Player, Monster)
  296.         'frmMain.Print entryTime, exitTime
  297.         'frmMain.Print xEntry, xExit
  298.         'frmMain.Print xExit, yExit
  299.         'frmMain.Print Player.Velocity.X, Player.Velocity.Y
  300.         Draw_Filled_Rectangle Monster.Position.X, Monster.Position.Y, Monster.Width, Monster.Height, Monster.Color
  301.         Draw_Filled_Rectangle Player.Position.X, Player.Position.Y, Player.Width, Player.Height, Player.Color
  302.         Draw_Rectangle broadphasebox.Position.X, broadphasebox.Position.Y, broadphasebox.Width, broadphasebox.Height, RGB(255, 255, 255)
  303.         Lock_Framerate 60
  304.         DoEvents
  305.     Loop
  306. End Sub
  307.  
  308. Private Sub Shutdown()
  309.     Running = False
  310.     Unload Me
  311. End Sub
  312.  
  313. Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
  314.     Select Case KeyCode
  315.         Case BUTTON_UP
  316.             Key_State = Key_State Or BUTTON_UP_FLAG
  317.         Case BUTTON_DOWN
  318.             Key_State = Key_State Or BUTTON_DOWN_FLAG
  319.         Case BUTTON_LEFT
  320.             Key_State = Key_State Or BUTTON_LEFT_FLAG
  321.         Case BUTTON_RIGHT
  322.             Key_State = Key_State Or BUTTON_RIGHT_FLAG
  323.         Case vbKeyEscape
  324.             Shutdown
  325.     End Select
  326. End Sub
  327.  
  328. Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
  329.     Select Case KeyCode
  330.         Case BUTTON_UP
  331.             Key_State = Key_State And (Not BUTTON_UP_FLAG)
  332.         Case BUTTON_DOWN
  333.             Key_State = Key_State And (Not BUTTON_DOWN_FLAG)
  334.         Case BUTTON_LEFT
  335.             Key_State = Key_State And (Not BUTTON_LEFT_FLAG)
  336.         Case BUTTON_RIGHT
  337.             Key_State = Key_State And (Not BUTTON_RIGHT_FLAG)
  338.     End Select
  339. End Sub
  340.  
  341. Private Sub Form_Load()
  342.     Main
  343. End Sub
  344.  
  345. Private Sub Form_Unload(Cancel As Integer)
  346.     Shutdown
  347. End Sub

Viewing all articles
Browse latest Browse all 21271

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>