I've been working on a very simple beginnings of a platformer which has been going ok until I started looking into the whole delta timing thing. I've setup a Bounding box type that handles creation and collision detection against them, the detection and response code worked great until I added delta timing. Now when the "player" rectangle object collides with the "floor" bounding box it jitters around. I've tried a few things to get it smooth again but I'm not having much luck.
EDIT: If someone would like to point out the syntax for a code box in a forum post since I can't seem to find any info on the topic.
This is the code for the Bounding Box type:
And the code for the Delta Timing:
And finally the code for the actual program:
EDIT: If someone would like to point out the syntax for a code box in a forum post since I can't seem to find any info on the topic.
This is the code for the Bounding Box type:
Global BoxList : TList Global BoundingBoxID = 0 Const BoundingBox_Solid = 1 Const BoundingBox_TwoWay = 2 Const BoundingBox_AllowLeft = 4 Const BoundingBox_AllowRight = 8 Const BoundingBox_AllowUp = 16 Const BoundingBox_AllowDown = 32 Const BoudingBox_LeftEdge = 1 Const BoudingBox_RightEdge = 2 Const BoudingBox_TopEdge = 3 Const BoudingBox_BottomEdge = 4 Global Axis : Int = 0 Global Side : Int = 0 Global MTD : Float = 0.0 Type BoundingBox Field X : Float , Y : Float Field Width : Float , Height: Float Field LeftEdge : Int , RightEdge : Int Field TopEdge : Int, BottomEdge : Int Field ID : Int Function Create : BoundingBox(X : Float , Y : Float , Width : Float , Height : Float, LeftEdge : Int = 2, RightEdge : Int = 2, TopEdge : Int = BoundingBox_AllowUp, BottomEdge : Int = 2) Local NewBox : BoundingBox NewBox = New BoundingBox NewBox.X = X NewBox.Y = Y NewBox.Width = Width NewBox.Height = Height NewBox.LeftEdge = LeftEdge NewBox.RightEdge = RightEdge NewBox.TopEdge = TopEdge NewBox.BottomEdge = BottomEdge NewBox.ID = BoundingBoxID BoundingBoxID = BoundingBoxID + 1 If Not BoxList Then BoxList = CreateList() BoxList.AddLast(NewBox) Return NewBox End Function Method IsOnScreen(ScreenX : Float , ScreenY : Float , ScreenWidth : Float , ScreenHeight : Float) If Self.X > (ScreenX + ScreenWidth) Or (Self.X + Self.Width) < ScreenX Then Return False If Self.Y > (ScreenY + ScreenHeight) Or (Self.Y + Self.Height) < ScreenY Then Return False Return True End Method Method GetEdgeType(Edge : Int) Select Edge Case BoudingBox_LeftEdge Return Self.LeftEdge Case BoudingBox_RightEdge Return Self.RightEdge Case BoudingBox_TopEdge Return Self.TopEdge Case BoudingBox_RightEdge Return Self.RightEdge End Select End Method 'debug method Method Draw(CameraX , CameraY) DrawRect(self.X - CameraX, self.Y - CameraY, Self.Width , Self.Height) End Method End Type Function CalculateCollision(x0#, y0#, w0#, h0#, x2#, y2#, w2#, h2#) Axis = 0 Side = 0 MTD = 0 Local Difference : Float = 0 Difference = (x0 + w0) - x2 If Difference < 0 Return False Else MTD = Difference Axis = 0 Side = - 1 EndIf Difference = (x2 + w2) - x0 If Difference < 0 Return False ElseIf (Difference < MTD) MTD = Difference Axis = 0 Side = 1 EndIf Difference = (y0 + h0) - y2 If Difference < 0 Return False ElseIf (Difference < MTD) MTD = Difference Axis = 1 Side = -1 EndIf Difference = (y2 + h2) - y0 If Difference < 0 Return False ElseIf (Difference < MTD) MTD = Difference Axis = 1 Side = 1 EndIf Return True End Function
And the code for the Delta Timing:
Type DeltaTime Global DeltaTList :TList Field OldTime :Int Field ElapsedTime :Int Field dFps :Float Field dDelta :Float Field CurrFps :Int Field FPSCounter :Int Field CurrTime :Int Field CheckTime :Int Method New () If DeltaTList = Null Then DeltaTList = New TList DeltaTList.AddLast Self End Method Method Destroy () DeltaTList.Remove Self End Method Function Create:DeltaTime(Fps:Float) Local dTime:DeltaTime = New DeltaTime dTime.dFps = Fps dTime.dDelta = 1000/Fps Return dTime End Function Method Update() Self.CurrTime = MilliSecs() Self.ElapsedTime = Self.CurrTime - Self.OldTime Self.OldTime = Self.CurrTime If Self.CurrTime > Self.CheckTime Self.CheckTime = Self.CurrTime + 1000 Self.CurrFps = Self.FPSCounter Self.FPSCounter = 0 Else Self.FPSCounter:+1 EndIf End Method Method FPS() Return Self.CurrFps End Method Method CurrDelta:Float() Return Double(Self.ElapsedTime)/Self.dDelta End Method Method SetFPS(NewFPS:Float) Self.dFPS = NewFPS Self.dDelta = 1000/Self.dFPS End Method End Type
And finally the code for the actual program:
Import "BoundingBox.bmx" Import "FrameLimit.bmx" Global px : Float = 10 Global py : Float = 10 Local velx : Float = 0 Local vely : Float = 0 Local grav : Float = 2 Global ScreenWidth = 1024 Global ScreenHeight = 768 Global Box1 : BoundingBox = BoundingBox.Create(0 , 700 , 1024 , 68 , BoundingBox_Solid, BoundingBox_Solid, BoundingBox_Solid, BoundingBox_Solid) Global Delta1 : DeltaTime = DeltaTime.Create(30.0) ' Normal 35 FPS Local Delta : Double Graphics 1024, 768, 0 While Not MouseHit(1) Delta1.Update() Delta = Delta1.CurrDelta() If Delta > 1 Then Delta = 1 ' Delta should never be bigger than 1. velx = 0 If KeyDown(key_left) velx = -15 ElseIf KeyDown(key_right) velx = 15 EndIf vely = vely + (grav * Delta) If vely > 15 Then vely = 15 If KeyHit(Key_space) Then vely = -30 py = py + (vely * Delta ) px = px + (velx * Delta) For Local Box : BoundingBox = EachIn BoxList If CalculateCollision(px, py, 70, 120, Box.X, Box.Y, Box.Width, Box.Height) = True Result = Side * MTD 'Y Axis If Axis = 1 py = py + Result 'X Axis Else px = px + Result EndIf EndIf Next ScreenUpdate = ScreenUpdate + Delta If ScreenUpdate > 0.30 Then Cls RenderGFX(ScreenUpdate) Flip 0 EndIf Wend End Function RenderGFX(Delta:Double=1) SetColor 255 , 255 , 255 DrawText Delta1.FPS()+" FPS",200,10 DrawText(px , 100 , 10) DrawText(py, 100, 30) SetColor 255,100 , 0 DrawRect px, py, 70, 120 SetColor 0,0,255 Box1.Draw(0, 0) End Function