Momentum Problem

Monkey Forums/Monkey Programming/Momentum Problem

Matt Finch(Posted 2014) [#1]
Hi Monkeys!

Method Update:Int()
		If KeyDown( KEY_RIGHT )
			If inertia < maxInertia
				inertia += 0.2
			End
		Else
			If inertia > 0.0
				inertia -= 0.2
			End
		End
		If KeyDown( KEY_LEFT )
			If inertia > -maxInertia
				inertia -= 0.2
			End
		Else
			If inertia < 0.0
				inertia += 0.2
			End
		End
		posX += inertia
		If posX > SCREEN_R - 100 
			inertia = 0.0
			posX = SCREEN_R - 100
		End
		If posX < SCREEN_L
			inertia = 0.0
			posX = SCREEN_L
		End
		Return( 0 )
	End


Please see the above code. This 'works', but I don't feel that it is the best way of doing it, plus sometimes the movement continues long after the button has been released (my 'inertia' variable, when printed in debug, shows 0.19xxxx and not '0' as I would be expecting. Would anyone be able to kindly advise how to tweak this (or suggest a neater way of achieving the smooth movement I'm after)?

Full code below if needed (no external resources).

I'm after adding momentum to the movement, to give a bit of 'weight' to the bat.

Strict
Import mojo

Const SCREEN_W:Int = 800
Const SCREEN_H:Int = 600
Const SCREEN_L:Int = 10
Const SCREEN_R:Int = SCREEN_W - 10

Class BouncerGame Extends App
	Field bat1:Bat = New Bat( ( SCREEN_W / 2 ) - 50, 550, 7 )

	Method OnCreate:Int()
		SetUpdateRate( 60 )
		Return( 0 )
	End
	
	Method OnUpdate:Int()
		bat1.Update()
		Return( 0 )
	End
	
	Method OnRender:Int()
		Cls( 0, 0, 0 )
		bat1.Render()
		Return( 0 )
	End
End

Class Bat
	Field posX:Float
	Field posY:Float
	Field inertia:Float
	Field maxInertia:Float
	
	Method New( posX:Float, posY:Float, maxInertia:Float )
		Self.posX = posX
		Self.posY = posY
		Self.maxInertia = maxInertia
	End
	
	Method Update:Int()
		If KeyDown( KEY_RIGHT )
			If inertia < maxInertia
				inertia += 0.2
			End
		Else
			If inertia > 0.0
				inertia -= 0.2
			End
		End
		If KeyDown( KEY_LEFT )
			If inertia > -maxInertia
				inertia -= 0.2
			End
		Else
			If inertia < 0.0
				inertia += 0.2
			End
		End
		posX += inertia
		If posX > SCREEN_R - 100 
			inertia = 0.0
			posX = SCREEN_R - 100
		End
		If posX < SCREEN_L
			inertia = 0.0
			posX = SCREEN_L
		End
		Return( 0 )
	End
	
	Method Render:Int()
		SetColor( 255, 255, 255 )
		DrawRect( posX, posY, 100, 16 )
		DrawText( inertia, 0, 0 )
		Return( 0 )
	End
End

Function Main:Int()
	New BouncerGame
	Return( 0 )
End


Thanks as always. :)
Matt...


Matt Finch(Posted 2014) [#2]
Whoops - I thought I was in the beginners forum. I do apologise: please move as appropriate. Thanks!


Trez(Posted 2014) [#3]
Hi, try this should stop the ping pong .

add another field
	Field direction:Int = -1


and change the keypress detection to this:

	If KeyDown(KEY_RIGHT)
			direction = 0
			If inertia < maxInertia
				inertia += 0.2
			End
		ElseIf direction = 0
			If inertia > 0.0
				inertia -= 0.2
			ElseIf inertia <= 0.0
				inertia = 0.0
				direction = -1
			End
		End
		If KeyDown(KEY_LEFT)
			direction = 1
			If inertia > - maxInertia
				inertia -= 0.2
			End
		ElseIf direction = 1
			If inertia < 0.0
				inertia += 0.2
			ElseIf inertia >= 0.0
				inertia = 0.0
				direction = -1
			End
		End



muddy_shoes(Posted 2014) [#4]
I'd probably approach this by implementing drag rather than trying to track movement state:

If KeyDown( KEY_RIGHT )
    inertia += 0.7
End
		
If KeyDown( KEY_LEFT )
    inertia -= 0.7
End
		
inertia *= 0.9 'drag


The drag calc both limits the top speed and ensures the fall back to zero. You might still end up adding special casing to tweak the feel but it's a simpler place to start.


Matt Finch(Posted 2014) [#5]
Thank you both. I will try both methods to see what suits best. Thanks again, Matt.