Jittery Collision Response with Delta Timing

BlitzMax Forums/BlitzMax Programming/Jittery Collision Response with Delta Timing

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:
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



forum codes

Thanks tonyg! Much more readable now.

Try fixed rate logic like this . It's more suited to collision/physics games.

Excellent! Fixed rate is much better, thanks again tonyg.

Yes. Even though I've coded delta time in platformers, never again. Fixed timing is the way to do. ;)