Numeric Ramp

BlitzMax Forums/BlitzMax Programming/Numeric Ramp

Zakk(Posted 2009) [#1]
I recently acclimated myself to the usage of pointers in BlitzMax, and I made a few PureData-inspired functions that I thought I'd share :)

'ramp function.bmx

'=============================
Function Ramp(f:Float Var, value:Float, milliseconds:Int, override:Int=True)
	Local target:Float Ptr = Varptr(f)
	Local r:TRamp = TRamp.Create(target, value, milliseconds, override)
End Function
'=============================
Function ReverseRamp(f:Float Var, milliseconds:Int=0)
	Local target:Float Ptr = Varptr(f)
	Local ramp1:TRamp = TRamp.FindRamp(target)
	If ramp1=Null Then Return
	If milliseconds = 0
		Local time_passed:Int = MilliSecs()-ramp1.start_time
		milliseconds = time_passed
	EndIf
	Local ramp2:TRamp = TRamp.Create(target, ramp1.start_value, milliseconds, True)
End Function
'=============================
Function HaltRamp(f:Float Var)
	Local target:Float Ptr = Varptr(f)
	Local ramp:TRamp = TRamp.FindRamp(target)
	If ramp<>Null
		ramp.Destroy()
		Return
	EndIf
End Function
'=============================

'=============================
Type TRamp
	Global global_list:TList = New TList
	'=============================
	Field global_link:TLink
	'=============================
	Method New()
		global_link = global_list.AddLast(Self)
	End Method
	'=============================
	Field target:Float Ptr
	Field start_value:Float
	Field start_time:Int
	Field end_value:Float
	Field end_time:Int
	Field duration:Int
	Field previous_value:Float
	Field difference:Float
	'=============================
	Function FindRamp:TRamp(target:Float Ptr)
		Local ramp:TRamp
		For ramp=EachIn global_list
			If ramp.target=target
				Return ramp
			EndIf
		Next
		Return Null
	End Function
	'=============================
	Function Create:TRamp(target:Float Ptr, value:Float, duration:Int, override:Int=True)
		Local ramp:TRamp=FindRamp(target)
		If ramp<>Null
			Select override
				Case True
					ramp.Destroy()		'new ramps override old ones
				Case False
					Return Null		'old ramps override new ones
				Default
			End Select
		EndIf
		'=============================
		ramp:TRamp = New TRamp
		ramp.target = target
		ramp.start_value = target[0]
		ramp.start_time = MilliSecs()
		ramp.end_value = value
		ramp.end_time = ramp.start_time+duration
		ramp.duration = duration
		ramp.difference = ramp.end_value-ramp.start_value
		ramp.previous_value=target[0]
		Return ramp
	End Function
	'=============================
	Function Update_All()
		Local ramp:TRamp
		For ramp=EachIn global_list
			ramp.Update()
		Next
	End Function
	'=============================
	Function Print_All()
		Local ramp:TRamp
		For ramp=EachIn global_list
			Print ramp.ToString()
		Next
	End Function
	'=============================
	Method Update()
		If target[0]<>previous_value
			Destroy()		'ramp is interrupted (doesn't respond if the variable is set to it's current value)
			Return
		EndIf
		Local current_time:Int = MilliSecs()
		If current_time >= end_time
			target[0]=end_value
			Destroy()
			Return
		EndIf
		Local time_passed:Float=current_time-start_time
		target[0] = start_value + time_passed*difference/duration 
		previous_value = target[0]
	End Method
	'=============================
	Method Destroy()
		global_link.Remove()
	End Method
	'=============================
	Method ToString:String()
		Return "start_value: "+start_value+"   end_value: "+end_value+"   duration: "+duration
	End Method
End Type
'=============================


here's a usage example.
controls:
-spacebar ramps myfloat to a random value over a random interval
-backspace reverses an in-progress ramp to return myfloat to it's previous value
-left click anywhere to set myfoat's value (this interrupts an in-progress ramp)
-right click anywhere to halt an in-progress ramp
'ramp example.bmx
'=============================
SuperStrict
Include "ramp function.bmx"
Graphics 400, 300
'=============================



'=============================
Global myfloat:Float=150
'=============================



'=============================
While Not KeyHit(KEY_ESCAPE)
	'=============================
	If KeyHit(KEY_SPACE)
		Ramp(myfloat, Rnd(0, 300), Rnd(500, 2000))
	EndIf
	'=============================
	If KeyHit(KEY_BACKSPACE)
		ReverseRamp(myfloat)
	EndIf
	'=============================
	If MouseHit(1)
		myfloat=MouseY()
	EndIf
	'=============================
	If MouseHit(2)
		HaltRamp(myfloat)
	EndIf
	'=============================
	TRamp.Update_All()
	'=============================
	Local ramp:TRamp
	For ramp=EachIn TRamp.global_list
		SetColor 255, 255, 0
		DrawOval 190, ramp.end_value-10, 20, 20
		SetColor 0, 0, 255
		DrawOval 190, ramp.start_value-10, 20, 20
	Next
	'=============================	
	SetColor 255, 255, 255
	DrawOval 190, myfloat-10, 20, 20
	'=============================	
Flip
Cls
Wend
End
'=============================

Pretty self-explanatory, tell me what you think :) Comments, suggestions, and let me know if something like this already exists.