Temporary disabled soundtray label

Temporary disabled soundtray label

Strict

Import mojo

Import flxextern
Import flxbasic
Import flxstate
Import flxcamera
Import flxtimer
Import flxtext
Import flxg
Import flxu
Import flxtilemap
Import system.flxassetsmanager
Import system.flxfont
Import system.flxdebugger
Import system.flxreplay
Import plugin.timermanager

Import "data/flx_beep.mp3"

'#HTML5_SUSPEND_ON_BLUR_ENABLED = "true"

Class FlxGame extends App

	Field useSoundHotKeys:Bool

	Field useSystemCursor:Bool

	Field useVirtualResolution:Bool

	Field forceDebugger:Bool

	Field _state:FlxState

	Field _requestedState:FlxState

	Field _requestedReset:Bool

	Field _debugger:FlxDebugger

	Field _debuggerUp:Bool

	Field _replay:FlxReplay

	Field _replayRequested:Bool

	Field _recordingRequested:Bool

	Field _replaying:Bool

	Field _recording:Bool

	Field _replayCancelKeys:Int[]

	Field _replayTimer:Float

	Field _replayCallback:FlxReplayListener

Private
	Field _iState:FlxClass

	Field _created:Bool

	Field _total:Int

	Field _accumulator:Float

	Field _step:Float

	Field _maxAccumulation:Float

	Field _soundTrayTimer:Float

	Field _soundTrayWidth:Float

	Field _soundTrayHeight:Float

	Field _soundTrayX:Float

	Field _soundTrayY:Float

	Field _soundTrayVisible:Bool

	Field _soundTrayLabel:FlxText

	Field _updaterate:Int

	Field _framerate:Int

Public
	Method New(gameSizeX:Int, gameSizeY:Int, initialState:FlxClass, zoom:Float = 1, updaterate:Int = 60, framerate:Int = 30, useSystemCursor:Bool = False)
		_soundTrayTimer = 0
		_soundTrayWidth = 160
		_soundTrayHeight = 45
		_soundTrayX = 0
		_soundTrayY	= -_soundTrayHeight
		_soundTrayVisible = False

		FlxG.Init(Self, gameSizeX, gameSizeY, zoom)
		FlxG.Framerate = framerate
		FlxG.Updaterate = updaterate
		_total = 0

		_state = Null

		useSoundHotKeys = Not IsMobile()
		Self.useSystemCursor = useSystemCursor
		useVirtualResolution = True

		If (Not useSystemCursor) HideMouse()

		forceDebugger = False
		_debuggerUp = False

		_replay = New FlxReplay()
		_replayRequested = False
		_recordingRequested = False
		_replaying = False
		_recording = False

		_iState = initialState
		_requestedState = Null
		_requestedReset = True
		_created = False
	End Method

	Method OnCreate:Int()
		_InitData()
		_Step()

		_soundTrayX	= (FlxG.Width / 2) * FlxCamera.DefaultZoom * FlxG._DeviceScaleFactorX - (_soundTrayWidth / 2) + FlxG.Camera.X
		#Rem
		_soundTrayLabel = New FlxText(10, 32, _soundTrayWidth, "VOLUME")
		_soundTrayLabel.SetFormat(FlxText.SYSTEM_FONT, 16, FlxG.WHITE, FlxText.ALIGN_CENTER)
		#End
		Return 0
	End Method

	Method OnUpdate:Int()
		#If TARGET <> "ios" Or TARGET <> "android"
			If (useSoundHotKeys) Then
				If (KeyHit(KEY_0)) Then
					FlxG.Mute = Not FlxG.Mute

					If (FlxG.VolumeHandler <> Null) Then
						If (FlxG.Mute) Then
							FlxG.VolumeHandler.OnVolumeChange(0)
						Else
							FlxG.VolumeHandler.OnVolumeChange(FlxG.Volume())
						End If
					End If

					_ShowSoundTray()
				End If

				If (KeyHit(KEY_MINUS)) Then
					FlxG.Mute = False
					FlxG.Volume(FlxG.Volume() - .1)
					_ShowSoundTray()
				End If

				If (KeyHit(KEY_EQUALS)) Then
					FlxG.Mute = False
					FlxG.Volume(FlxG.Volume() + .1)
					_ShowSoundTray()
				End If
			End If

			_UpdateSoundTray(_step)
		#End

		Return 0
	End Method

	Method OnRender:Int()
		If (FlxG.Framerate <> _framerate Or FlxG.Updaterate <> _updaterate) Then
			_ResetFramerate()
		End If

		Local mark:Int = Millisecs()
		Local elapsedMS:Int = mark - _total
		_total = mark

		If (_debugger <> Null) Then
			'TODO!
		Else
			_accumulator += elapsedMS

			if (_accumulator > _maxAccumulation) Then
				_accumulator = _maxAccumulation
			End If

			While (_accumulator >= _step)
				_Step()
				_accumulator -= _step
			Wend
		End If

		FlxBasic._VisibleCount = 0

		_Draw()

		Return 0
	End Method

	Method OnSuspend:Int()
		ShowMouse()
		FlxG.PauseSounds()
		Return 0
	End Method

	Method OnResume:Int()
		If (Not _debuggerUp And Not useSystemCursor) Then
			HideMouse()
		End If

		FlxG.ResetInput()
		FlxG.ResumeSounds()
		Return 0
	End Method

	Method OnContentInit:Void()
	End Method

Private
	Method _ShowSoundTray:Void(silent:Bool = False)
		If (Not silent) Then
			FlxG.Play(FlxG.DATA_PREFIX + "beep")
		End If

		_soundTrayTimer = 1
		_soundTrayY = 0
		_soundTrayVisible = True
	End Method

	Method _SwitchState:Void()
		FlxG.ResetCameras()
		FlxG.ResetInput()
		FlxG.DestroySounds()
		FlxG.ClearBitmapCache()

		If (_debugger <> Null) Then
			'TODO!
		End If

		Local timeManager:TimerManager = FlxTimer.Manager()
		If (timeManager <> Null) timeManager.Clear()

		If (_state <> Null) _state.Destroy()

		_state = _requestedState
		_state.Create()

		If (FlxG.Framerate <> _framerate Or FlxG.Updaterate <> _updaterate) Then
			_ResetFramerate()
		End If
	End Method

	Method _Step:Void()
		If (_requestedReset) Then
			_requestedReset = False
			_requestedState = FlxState(_iState.CreateInstance())
			_replayTimer = 0
			_replayCancelKeys = []
			_Reset()
			FlxG.Reset()
		End If

		If (_recordingRequested) Then
			_recordingRequested = False
			_replay.Create(FlxG.GlobalSeed)
			_recording = True

			If (_debugger <> Null) Then
				'TODO
				FlxG.Log("FLIXEL: starting new flixel gameplay record.")
			End If

		ElseIf (_replayRequested)
			_replayRequested = False
			_replay.Rewind()
			FlxG.GlobalSeed = _replay.seed

			If (_debugger <> Null) Then
				'TODO
			End If

			_replaying = True
		End If

		If (_state <> _requestedState) _SwitchState()

		FlxBasic._ActiveCount = 0

		If (_replaying) Then
			If (_replayCancelKeys.Length() > 0 And Not KeyDown(192) And Not KeyDown(220)) Then
				Local i:Int = 0
				Local l:Int = _replayCancelKeys.Length()

				While (i < l)
					If (KeyDown(_replayCancelKeys[i])) Then
						If (_replayCallback <> Null) Then
							_replayCallback.OnReplayComplete()
							_replayCallback = Null
						Else
							FlxG.StopReplay()
						End If

						Exit
					End If

					i += 1
				Wend
			End If

			_replay.PlayNextFrame()

			If (_replayTimer > 0) Then
				_replayTimer -= _step

				If (_replayTimer <= 0) Then
					If (_replayCallback <> Null) Then
						_replayCallback.OnReplayComplete()
						_replayCallback = Null
					Else
						FlxG.StopReplay()
					End If
				End If
			End If

			If (_replaying And _replay.finished) Then
				FlxG.StopReplay()

				If (_replayCallback <> Null) Then
					_replayCallback.OnReplayComplete()
					_replayCallback = Null
				End If
			End If

			If (_debugger <> Null) Then
				'TODO
			End If
		Else
			FlxG.UpdateInput()
		End If

		If (_recording) Then
			_replay.RecordFrame()

			If (_debugger <> Null) Then
				'TODO
			End If
		End If

		_Update()

		If (_debugger <> Null) Then
			'TODO
		End If
	End Method

	Method _Update:Void()
		FlxG.Elapsed = FlxG.TimeScale * (_step / 1000.0)

		FlxG.UpdateSounds()
		FlxG.UpdatePlugins()
		_state.Update()
		FlxG.UpdateCameras()

		If (_debuggerUp) Then
			'TODO!
		End If
	End Method

	Method _UpdateSoundTray:Void(ms:Int)
		If (Not _soundTrayVisible) Return

		If (_soundTrayTimer > 0) Then
			_soundTrayTimer -= ms / 1000.0

		ElseIf (_soundTrayY > -_soundTrayHeight)
			_soundTrayY =_soundTrayY - (ms / 1000.0 * FlxG.Height * 2)

			If (_soundTrayY <= -_soundTrayHeight) Then
				_soundTrayVisible = False

				'TODO Save sound settings
			End If
		End If
	End Method

	Method _Draw:Void()
		Cls(FlxG._BgColor.r, FlxG._BgColor.g, FlxG._BgColor.b)
		Scale(FlxG._DeviceScaleFactorX, FlxG._DeviceScaleFactorY)

		FlxG._LastDrawingColor = FlxG.WHITE
		FlxG._LastDrawingBlend = GetBlend()
		FlxG._LastDrawingAlpha = GetAlpha()
		FlxG._CurrentCamera = Null

		Local i:Int = 0
		Local l:Int = FlxG.Cameras.Length()

		While(i < l)
			FlxG._CurrentCamera = FlxG.Cameras.Get(i)

			If (Not FlxG._CurrentCamera.active) Then
				i+=1
				Continue
			End If

			FlxG._CurrentCameraID = i

			If (FlxG._CurrentCamera = Null Or Not FlxG._CurrentCamera.exists Or Not FlxG._CurrentCamera.visible) Continue

			FlxG._CurrentCamera.DrawFX() 'not realy draw. Only calculation
			FlxG._CurrentCamera.Lock()
			_state.Draw()
			FlxG.DrawPlugins()
			FlxG._CurrentCamera.Unlock()

			i+=1
		Wend

		#If TARGET <> "ios" Or TARGET <> "android"
			If (Not FlxG.Mobile) Then
				_DrawSoundTray()
				FlxG.Mouse.Draw()
			End If
		#End
	End Method

	Method _DrawSoundTray:Void()
		If (_soundTrayVisible) Then
			Local globalVolume:Int = FlxU.Round(FlxG.Volume() * 10)
			If (FlxG.Mute) globalVolume = 0

			PushMatrix()

			Scale(1 / FlxG._DeviceScaleFactorX, 1 / FlxG._DeviceScaleFactorY)
			Translate(_soundTrayX, _soundTrayY)

			If (FlxG._LastDrawingAlpha <> .5) Then
				SetAlpha(.5)
				FlxG._LastDrawingAlpha = .5
			End If

			If (FlxG._LastDrawingColor <> FlxG.BLACK) Then
				SetColor(0, 0, 0)
			End If

			DrawRect(0, 0, _soundTrayWidth, _soundTrayHeight)

			SetColor(255, 255, 255)
			FlxG._LastDrawingColor = FlxG.WHITE

			Local bx:Int = 20
			Local by:Int = 28

			Local i:Int = 0
			While (i < 10)
				If (i < globalVolume) Then
					If (FlxG._LastDrawingAlpha <> 1) Then
						SetAlpha(1)
						FlxG._LastDrawingAlpha = 1
					End If

				Else
					If (FlxG._LastDrawingAlpha <> .5) Then
						SetAlpha(.5)
						FlxG._LastDrawingAlpha = .5
					End If
				End If

				DrawRect(bx, by, 8, i * 2)

				bx += 12
				by -= 2
				i += 1
			Wend

			'_soundTrayLabel.Draw()

			PopMatrix()
		End If
	End Method

	Method _Reset:Void()
		If (FlxG.Framerate <> _framerate Or FlxG.Updaterate <> _updaterate) Then
			_ResetFramerate()
		End If

		Seed = SystemMillisecs()

		FlxG.DeviceWidth = DeviceWidth()
		FlxG.DeviceHeight = DeviceHeight()

		If (useVirtualResolution) Then
			FlxG._DeviceScaleFactorX = FlxG.DeviceWidth / Float(FlxG.Width)
			FlxG._DeviceScaleFactorY = FlxG.DeviceHeight / Float(FlxG.Height)
		Else
			FlxG._DeviceScaleFactorX = 1
			FlxG._DeviceScaleFactorY = 1
		End If
	End Method

	Method _ResetFramerate:Void()
		SetUpdateRate(FlxG.Framerate)

		_step = 1000.0 / FlxG.Updaterate
		_maxAccumulation = 2000.0 / FlxG.Framerate - 1

		If (_maxAccumulation < _step) Then
			_maxAccumulation = _step
		End If

		_updaterate = FlxG.Updaterate
		_framerate = FlxG.Framerate
	End Method

	Method _InitData:Void()
		FlxAssetsManager.Init()

		Local minSystemFontSize:Int = 8
		Local maxSystemFontSize:Int = 24
		Local fontPathPrefix:String = FlxG.DATA_PREFIX + FlxText.SYSTEM_FONT + "_font_"

		Local system:FlxFont = 	FlxAssetsManager.AddFont(FlxText.SYSTEM_FONT)

		For Local size:Int = minSystemFontSize To maxSystemFontSize
			system.SetPath(size, fontPathPrefix + Min(size, 17) + ".png")
		Next

		FlxAssetsManager.AddImage(FlxG.DATA_PREFIX + "default", FlxG.DATA_PREFIX + "default.png")
		FlxAssetsManager.AddImage(FlxG.DATA_PREFIX + "button", FlxG.DATA_PREFIX + "button.png")
		FlxAssetsManager.AddImage(FlxTilemap.AUTOTILES, FlxTilemap.AUTOTILES + ".png")
		FlxAssetsManager.AddImage(FlxTilemap.AUTOTILES_ALT, FlxTilemap.AUTOTILES_ALT + ".png")
		FlxAssetsManager.AddCursor(FlxG.DATA_PREFIX + "cursor", FlxG.DATA_PREFIX + "cursor.png")
		FlxAssetsManager.AddSound(FlxG.DATA_PREFIX + "beep", FlxG.DATA_PREFIX + "beep.mp3")

		Self.OnContentInit()
	End Method
End Class

Private
Class FlxFPSCounter

	Field FPS:Int

Private
	Field _FPSCounter:Int

	Field _lastUpdateTime:Int

Public
	Method New()
		Reset()
	End Method

	Method Update:Void()
		If (_lastUpdateTime = 0) Then
			_lastUpdateTime = Millisecs()
		ElseIf (Millisecs() - _lastUpdateTime >= 1000) Then
			FPS = _FPSCounter
			_lastUpdateTime = Millisecs()
			_FPSCounter = 0
		End If

		_FPSCounter += 1
	End Method

	Method Reset:Void()
		FPS = FlxG.Framerate
		_FPSCounter = 0
		_lastUpdateTime = 0
	End Method

End Class

Strict

Import mojo

Import flxextern
Import flxbasic
Import flxstate
Import flxcamera
Import flxtimer
Import flxtext
Import flxg
Import flxu
Import flxtilemap
Import system.flxassetsmanager
Import system.flxfont
Import system.flxdebugger
Import system.flxreplay
Import plugin.timermanager

Import "data/flx_beep.mp3"

'#HTML5_SUSPEND_ON_BLUR_ENABLED = "true"

Class FlxGame extends App

	Field useSoundHotKeys:Bool

	Field useSystemCursor:Bool

	Field useVirtualResolution:Bool

	Field forceDebugger:Bool

	Field _state:FlxState

	Field _requestedState:FlxState

	Field _requestedReset:Bool

	Field _debugger:FlxDebugger

	Field _debuggerUp:Bool

	Field _replay:FlxReplay

	Field _replayRequested:Bool

	Field _recordingRequested:Bool

	Field _replaying:Bool

	Field _recording:Bool

	Field _replayCancelKeys:Int[]

	Field _replayTimer:Float

	Field _replayCallback:FlxReplayListener

Private
	Field _iState:FlxClass

	Field _created:Bool

	Field _total:Int

	Field _accumulator:Float

	Field _step:Float

	Field _maxAccumulation:Float

	Field _soundTrayTimer:Float

	Field _soundTrayWidth:Float

	Field _soundTrayHeight:Float

	Field _soundTrayX:Float

	Field _soundTrayY:Float

	Field _soundTrayVisible:Bool

	Field _soundTrayLabel:FlxText

	Field _updaterate:Int

	Field _framerate:Int

Public
	Method New(gameSizeX:Int, gameSizeY:Int, initialState:FlxClass, zoom:Float = 1, updaterate:Int = 60, framerate:Int = 30, useSystemCursor:Bool = False)
		_soundTrayTimer = 0
		_soundTrayWidth = 160
		_soundTrayHeight = 60
		_soundTrayX = 0
		_soundTrayY	= -_soundTrayHeight
		_soundTrayVisible = False

		FlxG.Init(Self, gameSizeX, gameSizeY, zoom)
		FlxG.Framerate = framerate
		FlxG.Updaterate = updaterate
		_total = 0

		_state = Null

		useSoundHotKeys = Not IsMobile()
		Self.useSystemCursor = useSystemCursor
		useVirtualResolution = True

		If (Not useSystemCursor) HideMouse()

		forceDebugger = False
		_debuggerUp = False

		_replay = New FlxReplay()
		_replayRequested = False
		_recordingRequested = False
		_replaying = False
		_recording = False

		_iState = initialState
		_requestedState = Null
		_requestedReset = True
		_created = False
	End Method

	Method OnCreate:Int()
		_InitData()
		_Step()

		_soundTrayX	= (FlxG.Width / 2) * FlxCamera.DefaultZoom * FlxG._DeviceScaleFactorX - (_soundTrayWidth / 2) + FlxG.Camera.X
		_soundTrayLabel = New FlxText(10, 32, _soundTrayWidth, "VOLUME")
		_soundTrayLabel.SetFormat(FlxText.SYSTEM_FONT, 16, FlxG.WHITE, FlxText.ALIGN_CENTER)
		Return 0
	End Method

	Method OnUpdate:Int()
		#If TARGET <> "ios" Or TARGET <> "android"
			If (useSoundHotKeys) Then
				If (KeyHit(KEY_0)) Then
					FlxG.Mute = Not FlxG.Mute

					If (FlxG.VolumeHandler <> Null) Then
						If (FlxG.Mute) Then
							FlxG.VolumeHandler.OnVolumeChange(0)
						Else
							FlxG.VolumeHandler.OnVolumeChange(FlxG.Volume())
						End If
					End If

					_ShowSoundTray()
				End If

				If (KeyHit(KEY_MINUS)) Then
					FlxG.Mute = False
					FlxG.Volume(FlxG.Volume() - .1)
					_ShowSoundTray()
				End If

				If (KeyHit(KEY_EQUALS)) Then
					FlxG.Mute = False
					FlxG.Volume(FlxG.Volume() + .1)
					_ShowSoundTray()
				End If
			End If

			_UpdateSoundTray(_step)
		#End

		Return 0
	End Method

	Method OnRender:Int()
		If (FlxG.Framerate <> _framerate Or FlxG.Updaterate <> _updaterate) Then
			_ResetFramerate()
		End If

		Local mark:Int = Millisecs()
		Local elapsedMS:Int = mark - _total
		_total = mark

		If (_debugger <> Null) Then
			'TODO!
		Else
			_accumulator += elapsedMS

			if (_accumulator > _maxAccumulation) Then
				_accumulator = _maxAccumulation
			End If

			While (_accumulator >= _step)
				_Step()
				_accumulator -= _step
			Wend
		End If

		FlxBasic._VisibleCount = 0

		_Draw()

		Return 0
	End Method

	Method OnSuspend:Int()
		ShowMouse()
		FlxG.PauseSounds()
		Return 0
	End Method

	Method OnResume:Int()
		If (Not _debuggerUp And Not useSystemCursor) Then
			HideMouse()
		End If

		FlxG.ResetInput()
		FlxG.ResumeSounds()
		Return 0
	End Method

	Method OnContentInit:Void()
	End Method

Private
	Method _ShowSoundTray:Void(silent:Bool = False)
		If (Not silent) Then
			FlxG.Play(FlxG.DATA_PREFIX + "beep")
		End If

		_soundTrayTimer = 1
		_soundTrayY = 0
		_soundTrayVisible = True
	End Method

	Method _SwitchState:Void()
		FlxG.ResetCameras()
		FlxG.ResetInput()
		FlxG.DestroySounds()
		FlxG.ClearBitmapCache()

		If (_debugger <> Null) Then
			'TODO!
		End If

		Local timeManager:TimerManager = FlxTimer.Manager()
		If (timeManager <> Null) timeManager.Clear()

		If (_state <> Null) _state.Destroy()

		_state = _requestedState
		_state.Create()

		If (FlxG.Framerate <> _framerate Or FlxG.Updaterate <> _updaterate) Then
			_ResetFramerate()
		End If
	End Method

	Method _Step:Void()
		If (_requestedReset) Then
			_requestedReset = False
			_requestedState = FlxState(_iState.CreateInstance())
			_replayTimer = 0
			_replayCancelKeys = []
			_Reset()
			FlxG.Reset()
		End If

		If (_recordingRequested) Then
			_recordingRequested = False
			_replay.Create(FlxG.GlobalSeed)
			_recording = True

			If (_debugger <> Null) Then
				'TODO
				FlxG.Log("FLIXEL: starting new flixel gameplay record.")
			End If

		ElseIf (_replayRequested)
			_replayRequested = False
			_replay.Rewind()
			FlxG.GlobalSeed = _replay.seed

			If (_debugger <> Null) Then
				'TODO
			End If

			_replaying = True
		End If

		If (_state <> _requestedState) _SwitchState()

		FlxBasic._ActiveCount = 0

		If (_replaying) Then
			If (_replayCancelKeys.Length() > 0 And Not KeyDown(192) And Not KeyDown(220)) Then
				Local i:Int = 0
				Local l:Int = _replayCancelKeys.Length()

				While (i < l)
					If (KeyDown(_replayCancelKeys[i])) Then
						If (_replayCallback <> Null) Then
							_replayCallback.OnReplayComplete()
							_replayCallback = Null
						Else
							FlxG.StopReplay()
						End If

						Exit
					End If

					i += 1
				Wend
			End If

			_replay.PlayNextFrame()

			If (_replayTimer > 0) Then
				_replayTimer -= _step

				If (_replayTimer <= 0) Then
					If (_replayCallback <> Null) Then
						_replayCallback.OnReplayComplete()
						_replayCallback = Null
					Else
						FlxG.StopReplay()
					End If
				End If
			End If

			If (_replaying And _replay.finished) Then
				FlxG.StopReplay()

				If (_replayCallback <> Null) Then
					_replayCallback.OnReplayComplete()
					_replayCallback = Null
				End If
			End If

			If (_debugger <> Null) Then
				'TODO
			End If
		Else
			FlxG.UpdateInput()
		End If

		If (_recording) Then
			_replay.RecordFrame()

			If (_debugger <> Null) Then
				'TODO
			End If
		End If

		_Update()

		If (_debugger <> Null) Then
			'TODO
		End If
	End Method

	Method _Update:Void()
		FlxG.Elapsed = FlxG.TimeScale * (_step / 1000.0)

		FlxG.UpdateSounds()
		FlxG.UpdatePlugins()
		_state.Update()
		FlxG.UpdateCameras()

		If (_debuggerUp) Then
			'TODO!
		End If
	End Method

	Method _UpdateSoundTray:Void(ms:Int)
		If (Not _soundTrayVisible) Return

		If (_soundTrayTimer > 0) Then
			_soundTrayTimer -= ms / 1000.0

		ElseIf (_soundTrayY > -_soundTrayHeight)
			_soundTrayY =_soundTrayY - (ms / 1000.0 * FlxG.Height * 2)

			If (_soundTrayY <= -_soundTrayHeight) Then
				_soundTrayVisible = False

				'TODO Save sound settings
			End If
		End If
	End Method

	Method _Draw:Void()
		Cls(FlxG._BgColor.r, FlxG._BgColor.g, FlxG._BgColor.b)
		Scale(FlxG._DeviceScaleFactorX, FlxG._DeviceScaleFactorY)

		FlxG._LastDrawingColor = FlxG.WHITE
		FlxG._LastDrawingBlend = GetBlend()
		FlxG._LastDrawingAlpha = GetAlpha()
		FlxG._CurrentCamera = Null

		Local i:Int = 0
		Local l:Int = FlxG.Cameras.Length()

		While(i < l)
			FlxG._CurrentCamera = FlxG.Cameras.Get(i)

			If (Not FlxG._CurrentCamera.active) Then
				i+=1
				Continue
			End If

			FlxG._CurrentCameraID = i

			If (FlxG._CurrentCamera = Null Or Not FlxG._CurrentCamera.exists Or Not FlxG._CurrentCamera.visible) Continue

			FlxG._CurrentCamera.DrawFX() 'not realy draw. Only calculation
			FlxG._CurrentCamera.Lock()
			_state.Draw()
			FlxG.DrawPlugins()
			FlxG._CurrentCamera.Unlock()

			i+=1
		Wend

		#If TARGET <> "ios" Or TARGET <> "android"
			If (Not FlxG.Mobile) Then
				_DrawSoundTray()
				FlxG.Mouse.Draw()
			End If
		#End
	End Method

	Method _DrawSoundTray:Void()
		If (_soundTrayVisible) Then
			Local globalVolume:Int = FlxU.Round(FlxG.Volume() * 10)
			If (FlxG.Mute) globalVolume = 0

			PushMatrix()

			Scale(1 / FlxG._DeviceScaleFactorX, 1 / FlxG._DeviceScaleFactorY)
			Translate(_soundTrayX, _soundTrayY)

			If (FlxG._LastDrawingAlpha <> .5) Then
				SetAlpha(.5)
				FlxG._LastDrawingAlpha = .5
			End If

			If (FlxG._LastDrawingColor <> FlxG.BLACK) Then
				SetColor(0, 0, 0)
			End If

			DrawRect(0, 0, _soundTrayWidth, _soundTrayHeight)

			SetColor(255, 255, 255)
			FlxG._LastDrawingColor = FlxG.WHITE

			Local bx:Int = 20
			Local by:Int = 28

			Local i:Int = 0
			While (i < 10)
				If (i < globalVolume) Then
					If (FlxG._LastDrawingAlpha <> 1) Then
						SetAlpha(1)
						FlxG._LastDrawingAlpha = 1
					End If

				Else
					If (FlxG._LastDrawingAlpha <> .5) Then
						SetAlpha(.5)
						FlxG._LastDrawingAlpha = .5
					End If
				End If

				DrawRect(bx, by, 8, i * 2)

				bx += 12
				by -= 2
				i += 1
			Wend

			_soundTrayLabel.Draw()

			PopMatrix()
		End If
	End Method

	Method _Reset:Void()
		If (FlxG.Framerate <> _framerate Or FlxG.Updaterate <> _updaterate) Then
			_ResetFramerate()
		End If

		Seed = SystemMillisecs()

		FlxG.DeviceWidth = DeviceWidth()
		FlxG.DeviceHeight = DeviceHeight()

		If (useVirtualResolution) Then
			FlxG._DeviceScaleFactorX = FlxG.DeviceWidth / Float(FlxG.Width)
			FlxG._DeviceScaleFactorY = FlxG.DeviceHeight / Float(FlxG.Height)
		Else
			FlxG._DeviceScaleFactorX = 1
			FlxG._DeviceScaleFactorY = 1
		End If
	End Method

	Method _ResetFramerate:Void()
		SetUpdateRate(FlxG.Framerate)

		_step = 1000.0 / FlxG.Updaterate
		_maxAccumulation = 2000.0 / FlxG.Framerate - 1

		If (_maxAccumulation < _step) Then
			_maxAccumulation = _step
		End If

		_updaterate = FlxG.Updaterate
		_framerate = FlxG.Framerate
	End Method

	Method _InitData:Void()
		FlxAssetsManager.Init()

		Local minSystemFontSize:Int = 8
		Local maxSystemFontSize:Int = 24
		Local fontPathPrefix:String = FlxG.DATA_PREFIX + FlxText.SYSTEM_FONT + "_font_"

		Local system:FlxFont = 	FlxAssetsManager.AddFont(FlxText.SYSTEM_FONT)

		For Local size:Int = minSystemFontSize To maxSystemFontSize
			system.SetPath(size, fontPathPrefix + Min(size, 17) + ".png")
		Next

		FlxAssetsManager.AddImage(FlxG.DATA_PREFIX + "default", FlxG.DATA_PREFIX + "default.png")
		FlxAssetsManager.AddImage(FlxG.DATA_PREFIX + "button", FlxG.DATA_PREFIX + "button.png")
		FlxAssetsManager.AddImage(FlxTilemap.AUTOTILES, FlxTilemap.AUTOTILES + ".png")
		FlxAssetsManager.AddImage(FlxTilemap.AUTOTILES_ALT, FlxTilemap.AUTOTILES_ALT + ".png")
		FlxAssetsManager.AddCursor(FlxG.DATA_PREFIX + "cursor", FlxG.DATA_PREFIX + "cursor.png")
		FlxAssetsManager.AddSound(FlxG.DATA_PREFIX + "beep", FlxG.DATA_PREFIX + "beep.mp3")

		Self.OnContentInit()
	End Method
End Class

Private
Class FlxFPSCounter

	Field FPS:Int

Private
	Field _FPSCounter:Int

	Field _lastUpdateTime:Int

Public
	Method New()
		Reset()
	End Method

	Method Update:Void()
		If (_lastUpdateTime = 0) Then
			_lastUpdateTime = Millisecs()
		ElseIf (Millisecs() - _lastUpdateTime >= 1000) Then
			FPS = _FPSCounter
			_lastUpdateTime = Millisecs()
			_FPSCounter = 0
		End If

		_FPSCounter += 1
	End Method

	Method Reset:Void()
		FPS = FlxG.Framerate
		_FPSCounter = 0
		_lastUpdateTime = 0
	End Method

End Class


FlxGame _state now not realy private

FlxGame _state now not realy private

Strict

Import mojo

Import flxextern
Import flxbasic
Import flxstate
Import flxcamera
Import flxtimer
Import flxtext
Import flxg

Import system.flxassetsmanager
Import system.flxfont

Import plugin.timermanager

Class FlxGame extends App

	Field _state:FlxState

Private
	Field _iState:FlxClass

	Field _created:Bool

	Field _lostFocus:Bool

	Field _requestedState:FlxState

	Field _requestedReset:Bool

	Field _lastMillisecs:Float

	Field _step:Int

Public
	Method New(gameSizeX:Int, gameSizeY:Int, initialState:FlxClass, zoom:Float = 1, framerate:Int = 60, useSystemCursor:Bool = False)
		_lostFocus = False

		FlxG.Init(Self, gameSizeX, gameSizeY, zoom)
		FlxG.framerate = framerate

		_state = Null

		_iState = initialState
		_requestedState = Null
		_requestedReset = True
		_created = False
	End Method

	Method OnCreate:Int()
		SetUpdateRate(FlxG.framerate)
		Seed = SystemMillisecs()

		FlxG.deviceWidth = DeviceWidth()
		FlxG.deviceHeight = DeviceHeight()

		If (FlxG.targetWidth = 0) FlxG.targetWidth = FlxG.width
		If (FlxG.targetHeight = 0) FlxG.targetHeight = FlxG.height

		FlxG._deviceScaleFactorX = FlxG.deviceWidth / Float(FlxG.targetWidth)
		FlxG._deviceScaleFactorY = FlxG.deviceHeight / Float(FlxG.targetHeight)

		_InitData()
		_step = 1000 / FlxG.framerate
		_Step()
		Return 0
	End Method

	Method OnUpdate:Int()
		_Step()
		Return 0
	End Method

	Method OnRender:Int()
		Cls(FlxG._bgColor.r, FlxG._bgColor.g, FlxG._bgColor.b)
		Scale(FlxG._deviceScaleFactorX, FlxG._deviceScaleFactorY)

		FlxG._lastDrawingColor = FlxG.WHITE
		FlxG._lastDrawingBlend = GetBlend()
		FlxG._lastDrawingAlpha = GetAlpha()
		FlxG._currentCamera = Null

		Local i:Int = 0
		Local l:Int = FlxG.cameras.Length()

		While(i < l)
			FlxG._currentCamera = FlxG.cameras.Get(i)
			If (FlxG._currentCamera = Null Or Not FlxG._currentCamera.exists Or Not FlxG._currentCamera.visible) Continue

			FlxG._currentCamera.DrawFX() 'not realy draw. Only calculation
			FlxG._currentCamera.Lock()
			_state.Draw()
			FlxG.DrawPlugins()
			FlxG._currentCamera.Unlock()

			i+=1
		Wend

		Return 0
	End Method

	Method OnContentInit:Void()

	End Method

Private
	Method _SwitchState:Void()
		FlxG.ResetCameras()

		Local timeManager:TimerManager = FlxTimer.Manager()
		If (timeManager <> Null) timeManager.Clear()

		If (_state <> Null) _state.Destroy()

		_state = _requestedState
		_state.Create()

		If (Millisecs() - _lastMillisecs > _step) Then
			_lastMillisecs = Millisecs() - _step
		End If
	End Method

	Method _Step:Void()
		If (_requestedReset) Then
			_requestedReset = False
			_requestedState = FlxState(_iState.CreateInstance())
			FlxG.Reset()
			_lastMillisecs = Millisecs() - _step
		End If

		If (_state <> _requestedState) _SwitchState()

		_Update()
	End Method

	Method _Update:Void()
		FlxG.elapsed = FlxG.timeScale * ((Millisecs() - _lastMillisecs) / 1000.0)
		_lastMillisecs = Millisecs()

		FlxG.UpdatePlugins()
		_state.Update()
		FlxG.UpdateCameras()
	End Method

	Method _InitData:Void()
		FlxAssetsManager.Init()

		Local minSystemFontSize:Int = 8
		Local maxSystemFontSize:Int = 24
		Local fontPathPrefix:String = FlxG.DATA_PREFIX + FlxText.SYSTEM_FONT + "_font"

		Local system:FlxFont = 	FlxAssetsManager.AddFont(FlxText.SYSTEM_FONT)

		For Local size:Int = minSystemFontSize To maxSystemFontSize
			system.SetPath(size, fontPathPrefix + "_" + Min(size, 17) + ".png")
		Next

		FlxAssetsManager.AddImage(FlxG.DATA_PREFIX + "default", FlxG.DATA_PREFIX + "default.png")

		Self.OnContentInit()
	End Method
End Class

Strict

Import mojo

Import flxextern
Import flxbasic
Import flxstate
Import flxcamera
Import flxtimer
Import flxtext
Import flxg

Import system.flxassetsmanager
Import system.flxfont

Import plugin.timermanager

Class FlxGame extends App

Private
	Field _state:FlxState

	Field _iState:FlxClass

	Field _created:Bool

	Field _lostFocus:Bool

	Field _requestedState:FlxState

	Field _requestedReset:Bool

	Field _lastMillisecs:Float

	Field _step:Int

Public
	Method New(gameSizeX:Int, gameSizeY:Int, initialState:FlxClass, zoom:Float = 1, framerate:Int = 60, useSystemCursor:Bool = False)
		_lostFocus = False

		FlxG.Init(Self, gameSizeX, gameSizeY, zoom)
		FlxG.framerate = framerate

		_state = Null

		_iState = initialState
		_requestedState = Null
		_requestedReset = True
		_created = False
	End Method

	Method OnCreate:Int()
		SetUpdateRate(FlxG.framerate)
		Seed = SystemMillisecs()

		FlxG.deviceWidth = DeviceWidth()
		FlxG.deviceHeight = DeviceHeight()

		If (FlxG.targetWidth = 0) FlxG.targetWidth = FlxG.width
		If (FlxG.targetHeight = 0) FlxG.targetHeight = FlxG.height

		FlxG._deviceScaleFactorX = FlxG.deviceWidth / Float(FlxG.targetWidth)
		FlxG._deviceScaleFactorY = FlxG.deviceHeight / Float(FlxG.targetHeight)

		_InitData()
		_step = 1000 / FlxG.framerate
		_Step()
		Return 0
	End Method

	Method OnUpdate:Int()
		_Step()
		Return 0
	End Method

	Method OnRender:Int()
		Cls(FlxG._bgColor.r, FlxG._bgColor.g, FlxG._bgColor.b)
		Scale(FlxG._deviceScaleFactorX, FlxG._deviceScaleFactorY)

		FlxG._lastDrawingColor = FlxG.WHITE
		FlxG._lastDrawingBlend = GetBlend()
		FlxG._lastDrawingAlpha = GetAlpha()
		FlxG._currentCamera = Null

		Local i:Int = 0
		Local l:Int = FlxG.cameras.Length()

		While(i < l)
			FlxG._currentCamera = FlxG.cameras.Get(i)
			If (FlxG._currentCamera = Null Or Not FlxG._currentCamera.exists Or Not FlxG._currentCamera.visible) Continue

			FlxG._currentCamera.DrawFX() 'not realy draw. Only calculation
			FlxG._currentCamera.Lock()
			_state.Draw()
			FlxG.DrawPlugins()
			FlxG._currentCamera.Unlock()

			i+=1
		Wend

		Return 0
	End Method

	Method OnContentInit:Void()

	End Method

Private
	Method _SwitchState:Void()
		FlxG.ResetCameras()

		Local timeManager:TimerManager = FlxTimer.Manager()
		If (timeManager <> Null) timeManager.Clear()

		If (_state <> Null) _state.Destroy()

		_state = _requestedState
		_state.Create()

		If (Millisecs() - _lastMillisecs > _step) Then
			_lastMillisecs = Millisecs() - _step
		End If
	End Method

	Method _Step:Void()
		If (_requestedReset) Then
			_requestedReset = False
			_requestedState = FlxState(_iState.CreateInstance())
			FlxG.Reset()
			_lastMillisecs = Millisecs() - _step
		End If

		If (_state <> _requestedState) _SwitchState()

		_Update()
	End Method

	Method _Update:Void()
		FlxG.elapsed = FlxG.timeScale * ((Millisecs() - _lastMillisecs) / 1000.0)
		_lastMillisecs = Millisecs()

		FlxG.UpdatePlugins()
		_state.Update()
		FlxG.UpdateCameras()
	End Method

	Method _InitData:Void()
		FlxAssetsManager.Init()

		Local minSystemFontSize:Int = 8
		Local maxSystemFontSize:Int = 24
		Local fontPathPrefix:String = FlxG.DATA_PREFIX + FlxText.SYSTEM_FONT + "_font"

		Local system:FlxFont = 	FlxAssetsManager.AddFont(FlxText.SYSTEM_FONT)

		For Local size:Int = minSystemFontSize To maxSystemFontSize
			system.SetPath(size, fontPathPrefix + "_" + Min(size, 17) + ".png")
		Next

		FlxAssetsManager.AddImage(FlxG.DATA_PREFIX + "default", FlxG.DATA_PREFIX + "default.png")

		Self.OnContentInit()
	End Method
End Class


Fixed a typo

Fixed a typo

Strict

Public

' Preprocessor related:
#If MOJO_EMULATOR_IMPLEMENTED
	' Imports:
	Import imagedimensions

	Import mojoemulator
	Import app

	' Classes:
	Class Image
		' Constant variable(s) (Public):
		Const MidHandle:Int = 1

		Const XPadding:Int		= 2
		Const YPadding:Int		= 4
		Const XYPadding:Int		= XPadding | YPadding

		' Constant variable(s) (Private):
		Private

		Const FullFrame:Int = 65536

		Public

		' Global variable(s):
		Global DefaultFlags:Int = 0

		' Functions (Public):
		' Nothing so far.

		' Functions (Private):
		Private

		' Nothing so far.

		Public

		' Constructor(s) (Public):
		' Nothing so far.

		' Constructor(s) (Private):
		Private

		Method New(Flags:Int=Image.DefaultFlags)
			Self._Flags = Flags
		End

		Method New(FrameCount:Int, Flags:Int=Image.DefaultFlags)
			Self._Frames = FrameCount
			Self._Flags = Flags
		End

		Method New(Width:Int, Height:Int, FrameCount:Int, Flags:Int=Image.DefaultFlags)
			Self._Width = Width
			Self._Height = Height
			Self._Frames = FrameCount
			Self._Flags = Flags
		End

		Public

		' Destructor(s):
		Method Discard:Void()
			Return
		End

		' Methods:
		Method Width:Int() ' Property
			Return Self._Width
		End

		Method Height:Int() ' Property
			Return Self._Height
		End

		Method Loaded:Bool()
			Return Self._Loaded
		End

		Method Frames:Int()
			Return Self._Frames
		End

		Method Flags:Int()
			Return Self._Flags
		End

		Method HandleX:Float()
			Return Self._HandleX
		End

		Method HandleY:Float()
			Return Self._HandleY
		End

		Method SetHandle:Void(X:Float, Y:Float)
			_HandleX = X
			_HandleY = Y

			_Flags = _Flags & ~MidHandle

			Return
		End

		' Unsupported:
		' Method GrabImage:Image(X:Int, Y:Int, Width:Int, Height:Int, nFrames:Int=1, Flags:Int=DefaultFlags)
		' Method WritePixels:Void(pixels:Int[], x:Int, y:Int, width:Int, height:Int, offset:Int=0, pitch:Int=0)

		' Methods (Private):
		Private

		Method ApplyFlags:Void(F:Int)
			_Flags = F

			If (_Flags & XPadding) Then
				_Width -= 2
			Endif

			If (_Flags & YPadding) Then
				_Height -= 2
			Endif

			If (_Flags & Image.MidHandle) Then
				SetHandle(_Width / 2.0, _Height / 2.0)
			Endif

			Return
		End

		Public

		' Properties (Public):
		' Nothing so far.

		' Properties (Private):
		Private

		' Nothing so far.

		Public

		' Fields (Public):
		' Nothing so far.

		' Fields (Private):
		Private

		Field _Width:Int, _Height:Int
		Field _HandleX:Float, _HandleY:Float
		Field _Flags:Int, _Frames:Int
		Field _Loaded:Bool

		Public
	End

	' Functions:
	Function LoadImage:Image(Path:String, FrameCount:Int, Flags:Int=Image.DefaultFlags)
		' Local variable(s):
		Local D:= LoadImageDimensions(FixDataPath(Path))

		If (D[0] <> 0 And D[1] <> 0) Then
			' Local variable(s):
			Local I:= New Image(FrameCount, Flags)

			I._Width = D[0]
			I._Height = D[1]

			Return I
		Endif

		Return Null
	End

	Function LoadImage:Image(Path:String, FrameWidth:Int, FrameHeight:Int, FrameCount:Int, Flags:Int=Image.DefaultFlags)
		Local I:= New Image(FrameWidth, FrameHeight, FrameCount, Flags)

		' LoadImageDemensions(Path) <-- There's no need to call this, it would only give incorrect results.

		Return I
	End

	Function CreateImage:Image(Width:Int, Height:Int, FrameCount:Int=1, Flags:Int=Image.DefaultFlags)
		Return New Image(Width, Height, FrameCount, Flags)
	End
#End

Strict

Public

' Preprocessor related:
#If MOJO_EMULATOR_IMPLEMENTED
	' Imports:
	Import imagedimensions

	Import mojoemulator
	Import app

	' Classes:
	Class Image
		' Constant variable(s) (Public):
		Const MidHandle:Int = 1

		Const XPadding:Int		= 2
		Const YPadding:Int		= 4
		Const XYPadding:Int		= XPadding | YPadding

		' Constant variable(s) (Private):
		Private

		Const FullFrame:Int = 65536

		Public

		' Global variable(s):
		Global DefaultFlags:Int = 0

		' Functions (Public):
		' Nothing so far.

		' Functions (Private):
		Private

		' Nothing so far.

		Public

		' Constructor(s) (Public):
		' Nothing so far.

		' Constructor(s) (Private):
		Private

		Method New(Flags:Int=Image.DefaultFlags)
			Self._Flags = Flags
		End

		Method New(FrameCount:Int, Flags:Int=Image.DefaultFlags)
			Self._Frames = FrameCount
			Self._Flags = Flags
		End

		Method New(Width:Int, Height:Int, FrameCount:Int, Flags:Int=Image.DefaultFlags)
			Self._Width = Width
			Self._Height = Height
			Self._Frames = FrameCount
			Self._Flags = Flags
		End

		Public

		' Destructor(s):
		Method Discard:Void()
			Return
		End

		' Methods:
		Method Width:Int() ' Property
			Return Self._Width
		End

		Method Height:Int() ' Property
			Return Self._Height
		End

		Method Loaded:Bool()
			Return Self._Loaded
		End

		Method Frames:Int()
			Return Self._Frames
		End

		Method Flags:Int()
			Return Self._Flags
		End

		Method HandleX:Float()
			Return Self._HandleX
		End

		Method HandleY:Float()
			Return Self._HandleY
		End

		Method SetHandle:Void(X:Float, Y:Float)
			_HandleX = X
			_HandleY = Y

			_Flags = _Flags & ~MidHandle

			Return
		End

		' Unsupported:
		' Method GrabImage:Image(X:Int, Y:Int, Width:Int, Height:Int, nFrames:Int=1, Flags:Int=DefaultFlags)
		' Method WritePixels:Void(pixels:Int[], x:Int, y:Int, width:Int, height:Int, offset:Int=0, pitch:Int=0)

		' Methods (Private):
		Private

		Method ApplyFlags:Void(F:Int)
			_Flags = F

			If (_Flags & XPadding) Then
				_Width -= 2
			Endif

			If (_Flags & YPadding) Then
				_Height -= 2
			Endif

			If (_Flags & Image.MidHandle) Then
				SetHandle(_Width / 2.0, _Height / 2.0)
			Endif

			Return
		End

		Public

		' Properties (Public):
		' Nothing so far.

		' Properties (Private):
		Private

		' Nothing so far.

		Public

		' Fields (Public):
		' Nothing so far.

		' Fields (Private):
		Private

		Field _Width:Int, _Height:Int
		Field _HandleX:Float, _HandleY:Float
		Field _Flags:Int, _Frames:Int
		Field _Loaded:Bool

		Public
	End

	' Functions:
	Function LoadImage:Image(Path:String, FrameCount:Int, Flags:Int=Image.DefaultFlags)
		' Local variable(s):
		Local D:= LoadImageDemensions(FixDataPath(Path))

		If (D[0] <> 0 And D[1] <> 0) Then
			' Local variable(s):
			Local I:= New Image(FrameCount, Flags)

			I._Width = D[0]
			I._Height = D[1]

			Return I
		Endif

		Return Null
	End

	Function LoadImage:Image(Path:String, FrameWidth:Int, FrameHeight:Int, FrameCount:Int, Flags:Int=Image.DefaultFlags)
		Local I:= New Image(FrameWidth, FrameHeight, FrameCount, Flags)

		' LoadImageDemensions(Path) <-- There's no need to call this, it would only give incorrect results.

		Return I
	End

	Function CreateImage:Image(Width:Int, Height:Int, FrameCount:Int=1, Flags:Int=Image.DefaultFlags)
		Return New Image(Width, Height, FrameCount, Flags)
	End
#End


Fixed FlxU.FromatMoney

Fixed FlxU.FromatMoney

Strict

Import mojo
Import reflection

Import flxextern
Import flxpoint
Import flxg
Import system.flximagedata

Alias MonkeyAbs = monkey.math.Abs
Alias MonkeyFloor = monkey.math.Floor
Alias MonkeyCeil = monkey.math.Ceil
Alias MonkeyMin = monkey.math.Min
Alias MonkeyMax = monkey.math.Max
Alias MonkeyGetClass = reflection.GetClass

#If TARGET <> "psm" And TARGET <> "xna"
	Alias FlxOpenURL = mojo.app.OpenUrl
#End

Class FlxU

Private
	Global _objClass:ClassInfo

Public

	Function OpenURL:Void(url:String)
		FlxOpenURL(url)
	End Function

	Function Abs:Float(value:Float)
		Return MonkeyAbs(value)
	End Function

	Function Floor:Float(value:Float)
		Return MonkeyFloor(value)
	End Function

	Function Ceil:Float(value:Float)
		Return MonkeyCeil(value)
	End Function

	Function Round:Float(value:Float)
		If (value > 0) Then
			Return Int(value + .5)
		Else
			Return Int(value - .5)
		End If
	End Function

	Function Min:Float(number1:Float, number2:Float)
		Return MonkeyMin(number1, number2)
	End Function

	Function Max:Float(number1:Float, number2:Float)
		Return MonkeyMax(number1, number2)
	End Function

	Function Bound:Float(value:Float, min:Float, max:Float)
		Return Clamp(value, min, max)
	End Function

	Function Srand:Float(seed:Float)
		Return Float(seed Shr 8 & $ffffff)/$1000000
	End Function

	#Rem
	Function Shuffle:Object[](objects:Object[], howManyTimes:Int)
		Shuffle is not currently supported in Monkey. Use FlxArray.Shuffle method
	End Function
	#End

	#Rem
	Function GetRandom:FlxBasic(objects:FlxBasic[], startIndex:Int = 0, length:Int = 0)
		GetRandom is not currently supported in Monkey. Use FlxArray.GetRandom method
	End Function
	#End

	Function GetTicks:Int()
		Return Millisecs()
	End Function

	Function FormatTicks:String(startTicks:Int, endTicks:Int)
		Return ((endTicks - startTicks) / 1000) + "s"
	End Function

	Function MakeColor:Int(red:Int, green:Int, blue:Int, alpha:Float = 1)
		If (alpha <= 1) alpha *= 255
		Return (alpha & $FF) Shl 24 | (red & $FF) Shl 16 | (green & $FF) Shl 8 | (blue & $FF)
	End Function

	Function MakeColorFromHSB:Int(hue:Float, saturation:Float, brightness:Float, alpha:Float = 1)
		Local red:Float
		Local green:Float
		Local blue:Float

		If (saturation = 0)
			red = brightness
			green = brightness
			blue = brightness
		Else
			If (hue = 360) hue = 0

			Local slice:Int = hue / 60
			Local hf:Float = hue / 60 - slice
			Local aa:Float = brightness * (1 - saturation)
			Local bb:Float = brightness * (1 - saturation * hf)
			Local cc:Float = brightness * (1 - saturation * (1.0 - hf))

			Select (slice)
				Case 0
					red = brightness
					green = cc
					blue = aa

				Case 1
					red = bb
					green = brightness
					blue = aa

				Case 2
					red = aa
					green = brightness
					blue = cc

				Case 3
					red = aa
					green = bb
					blue = brightness

				Case 4
					red = cc
					green = aa
					blue = brightness

				Case 5
					red = brightness
					green = aa
					blue = bb

				Default
					red = 0
					green = 0
					blue = 0
			End Select
		End If

		If (alpha <= 1) alpha *= 255
		Return (alpha & $FF) Shl 24 | int(red * 255) Shl 16 | int(green * 255) Shl 8 | int(blue * 255)
	End Function

	Function GetRGBA:Float[](color:Int, resluts:Float[] = [])
		If (resluts.Length() <> 4) resluts = resluts.Resize(4)

		resluts[0] = (color Shr 16) & $FF
		resluts[1] = (color Shr 8) & $FF
		resluts[2] = color & $FF
		resluts[3] = Float((color Shr 24) & $FF) / 255
		Return resluts
	End Function

	Function GetHSB:Float[](color:Int, resluts:Float[] = [])
		If (resluts.Length() <> 4) resluts = resluts.Resize(4)

		Local red:Float = Float((color Shr 16) & $FF) / 255
		Local green:Float = Float((color Shr 8) & $FF) / 255
		Local blue:Float = Float(color & $FF) / 255

		Local m:Float = MonkeyMax(red, green)
		Local dmax:Float = MonkeyMax(m, blue)
		m = MonkeyMin(red, green)
		Local dmin:Float = MonkeyMin(m, blue)
		Local range:Float = dmax - dmin

		resluts[2] = dmax
		resluts[1] = 0
		resluts[0] = 0

		If (dmax <> 0) resluts[1] = range / dmax

		If (resluts[1] <> 0) Then
			If (red = dmax) Then
				resluts[0] = (green - blue) / range

			ElseIf (green = dmax) Then
				resluts[0] = 2 + (blue - red) / range

			ElseIf (blue = dmax) Then
				resluts[0] = 4 + (red - green) / range
			End If

			resluts[0] *= 60
			If (resluts[0] < 0) resluts[0] += 360
		End If

		resluts[3] = Float((color Shr 24) & $FF) / 255

		Return resluts
	End Function

	Function FormatTime:String(seconds:Float, showMS:Bool = False)
		Local timeString:StringStack = New StringStack()
		timeString.Push(Int(seconds / 60) + ":")

		Local timeStringHepler:Int = Int(seconds) Mod 60

		If (timeStringHepler < 10) Then
			timeString.Push("0")
		End If

		timeString.Push(timeStringHepler)

		If (showMS) Then
			timeString.Push(".")
			timeStringHepler = (seconds - Int(seconds)) * 100

			If (timeStringHepler < 10) Then
				timeString.Push("0")
			End If

			timeString.Push(timeStringHepler)
		End If

		Return timeString.Join("")
	End Function

	Function FormatMoney:String(amount:Float, showDecimal:Bool = True, englishStyle:Bool = True)
		Local helper:Int
		Local sgn:Int = Sgn(amount)
		Local showSgn:Bool = False
		amount = Abs(amount)
		Local intAmount:Int = amount
		Local comma:String = ""
		Local result:String = ""
		Local zeroes:String = ""

		If (intAmount = 0) result = "0"

		While (intAmount > 0)
			If (result.Length() > 0 And comma.Length() <= 0) Then
				If (englishStyle) Then
					comma = ","
				Else
					comma = "."
				End If
			End If

			helper = intAmount - Int(intAmount / 1000) * 1000
			intAmount /= 1000

			zeroes = ""

			If (intAmount > 0) Then
				If (helper < 100) Then
					zeroes = "0"
				End If

				If (helper < 10) Then
					zeroes = "00"
				End If
			End If

			result = zeroes + helper + comma + result
			showSgn = True
		Wend

		If (showDecimal) Then
			intAmount = Round(amount * 100) - (Int(amount) * 100)
			If (intAmount <> 0) showSgn = True

			If (englishStyle) Then
				result += "."
			Else
				result += ","
			End If

			If (intAmount < 10) Then
				result += "0"
			End If

			result += intAmount
		End If

		If (sgn < 0 And showSgn) Then
			Return "-" + result
		End If

		Return result
	End Function

	Function GetClassName:String(obj:Object, simple:Bool = False)
		If (simple) Then
			Local name:String = MonkeyGetClass(obj).Name
			Return name[name.FindLast(".")+1..]
		End If

		Return MonkeyGetClass(obj).Name
	End Function

	Function CompareClassNames:Bool(object1:Object, object2:Object)
		Return (MonkeyGetClass(object1).Name = MonkeyGetClass(object2).Name)
	End Function

	Function GetClass:ClassInfo(name:String)
		Return MonkeyGetClass(name)
	End Function

	Function GetObjectClass:ClassInfo()
		If (_objClass <> Null)
			Return _objClass
		End If

		_objClass = MonkeyGetClass("monkey.lang.Object")

		Return _objClass
	End Function

	Function ComputeVelocity:Float(velocity:Float, acceleration:Float = 0, drag:Float = 0, max:Float = 10000)
		If (acceleration <> 0) Then
			velocity += acceleration * FlxG.Elapsed

		ElseIf (drag <> 0) Then
			drag *= FlxG.Elapsed

			If (velocity - drag > 0) Then
				velocity -= drag
			ElseIf (velocity + drag < 0) Then
				velocity += drag
			Else
				velocity = 0
			End If
		End If

		If (velocity <> 0 And max <> 10000) Then
			If (velocity > max) Then
				velocity = max
			ElseIf (velocity < -max) Then
				velocity = -max
			End If
		End If

		Return velocity
	End Function

	Function RotatePoint:FlxPoint(x:Float, y:Float, pivotX:Float, pivotY:Float, angle:Float, point:FlxPoint = Null)
		Local sin:Float = 0
		Local cos:Float = 0
		Local radians:Float = angle * -0.017453293

		While (radians < -PI)
			radians += TWOPI
		Wend

		While (radians > PI)
			radians = radians - TWOPI
		Wend

		If (radians < 0) Then
			sin =  1.27323954 * radians + .405284735 * radians * radians
			If (sin < 0) Then
				sin = .225 * (sin * -sin - sin) + sin
			Else
				sin = .225 * (sin * sin - sin) + sin
			End If
		Else
			sin = 1.27323954 * radians - 0.405284735 * radians * radians
			If (sin < 0) Then
				sin = .225 * (sin * -sin - sin) + sin
			Else
				sin = .225 * (sin * sin - sin) + sin
			End If
		End If

		radians += HALFPI
		If (radians > PI) radians -= TWOPI

		If (radians < 0) Then
			cos = 1.27323954 * radians + 0.405284735 * radians * radians
			If (cos < 0) Then
				cos = .225 * (cos * -cos - cos) + cos
			Else
				cos = .225 * (cos * cos - cos) + cos
			End If
		Else
			cos = 1.27323954 * radians - 0.405284735 * radians * radians
			If (cos < 0) Then
				cos = .225 * (cos * -cos - cos) + cos
			Else
				cos = .225 * (cos * cos - cos) + cos
			End If
		End If

		Local dx:Float = x - pivotX
		Local dy:Float = pivotY + y

		If (point = Null) point = New FlxPoint()
		point.x = pivotX + cos * dx - sin * dy
		point.y = pivotY - sin * dx - cos * dy

		Return point
	End Function

	Function GetAngle:Float(point1:FlxPoint, point2:FlxPoint)
		Local x:Float = point2.x - point1.x
		Local y:Float = point2.y - point1.y

		If (x = 0 And y = 0) Return 0

		Local c1:Float = PI * .25
		Local c2:Float = 3 * c1
		Local ay:Float = MonkeyAbs(y)
		Local angle:Float = 0

		If (x >= 0) Then
			angle = c1 - c1 * ((x - ay) / (x + ay))
		Else
			angle = c2 - c1 * ((x + ay) / (ay - x))
		End If

		If (y < 0) Then
			angle =	-angle * 57.2957796
		Else
			angle =	angle * 57.2957796
		End If

		If (angle > 90) Then
			angle = angle - 270
		Else
			angle += 90
		End If

		Return angle
	End Function

	Function GetDistance:Float(point1:FlxPoint, point2:FlxPoint)
		Local dx:Float = point1.x - point2.x
		Local dy:Float = point1.y - point2.y

		Return Sqrt(dx * dx + dy * dy)
	End Function

	Function GetDistance:Float(x1:Float, y1:Float, x2:Float, y2:Float)
		Local dx:Float = x1 - x2
		Local dy:Float = y1 - y2

		Return Sqrt(dx * dx + dy * dy)
	End Function

	Function SetImageMask:Image(image:Image, maskColor:Int)
		Local bitmapData:FlxImageData = FlxImageData.FromImage(image, True)
		bitmapData.ColorReplace(maskColor, 0)

		Local result:Image = bitmapData.Image
		bitmapData.Destroy()

		Return result
	End Function

	Function SetImagePadding:Image(image:Image, paddings:Int = Image.XYPadding)
		Local paddingX:Int, paddingY:Int

		If (paddings & Image.XPadding) paddingX = 1
		If (paddings & Image.YPadding) paddingY = 1

		Return FlxU.SetImagePadding(image, paddingX, paddingY)
	End Function

	Function SetImagePadding:Image(image:Image, paddingX:Int, paddingY:Int)
		Local bitmapData:FlxImageData = FlxImageData.FromImage(image, False, paddingX, paddingY)
		Local result:Image = bitmapData.Image
		bitmapData.Destroy()

		Return result
	End Function

End Class

Strict

Import mojo
Import reflection

Import flxextern
Import flxpoint
Import flxg
Import system.flximagedata

Alias MonkeyAbs = monkey.math.Abs
Alias MonkeyFloor = monkey.math.Floor
Alias MonkeyCeil = monkey.math.Ceil
Alias MonkeyMin = monkey.math.Min
Alias MonkeyMax = monkey.math.Max
Alias MonkeyGetClass = reflection.GetClass

#If TARGET <> "psm" And TARGET <> "xna"
	Alias FlxOpenURL = mojo.app.OpenUrl
#End

Class FlxU

Private
	Global _objClass:ClassInfo

Public

	Function OpenURL:Void(url:String)
		FlxOpenURL(url)
	End Function

	Function Abs:Float(value:Float)
		Return MonkeyAbs(value)
	End Function

	Function Floor:Float(value:Float)
		Return MonkeyFloor(value)
	End Function

	Function Ceil:Float(value:Float)
		Return MonkeyCeil(value)
	End Function

	Function Round:Float(value:Float)
		If (value > 0) Then
			Return Int(value + .5)
		Else
			Return Int(value - .5)
		End If
	End Function

	Function Min:Float(number1:Float, number2:Float)
		Return MonkeyMin(number1, number2)
	End Function

	Function Max:Float(number1:Float, number2:Float)
		Return MonkeyMax(number1, number2)
	End Function

	Function Bound:Float(value:Float, min:Float, max:Float)
		Return Clamp(value, min, max)
	End Function

	Function Srand:Float(seed:Float)
		Return Float(seed Shr 8 & $ffffff)/$1000000
	End Function

	#Rem
	Function Shuffle:Object[](objects:Object[], howManyTimes:Int)
		Shuffle is not currently supported in Monkey. Use FlxArray.Shuffle method
	End Function
	#End

	#Rem
	Function GetRandom:FlxBasic(objects:FlxBasic[], startIndex:Int = 0, length:Int = 0)
		GetRandom is not currently supported in Monkey. Use FlxArray.GetRandom method
	End Function
	#End

	Function GetTicks:Int()
		Return Millisecs()
	End Function

	Function FormatTicks:String(startTicks:Int, endTicks:Int)
		Return ((endTicks - startTicks) / 1000) + "s"
	End Function

	Function MakeColor:Int(red:Int, green:Int, blue:Int, alpha:Float = 1)
		If (alpha <= 1) alpha *= 255
		Return (alpha & $FF) Shl 24 | (red & $FF) Shl 16 | (green & $FF) Shl 8 | (blue & $FF)
	End Function

	Function MakeColorFromHSB:Int(hue:Float, saturation:Float, brightness:Float, alpha:Float = 1)
		Local red:Float
		Local green:Float
		Local blue:Float

		If (saturation = 0)
			red = brightness
			green = brightness
			blue = brightness
		Else
			If (hue = 360) hue = 0

			Local slice:Int = hue / 60
			Local hf:Float = hue / 60 - slice
			Local aa:Float = brightness * (1 - saturation)
			Local bb:Float = brightness * (1 - saturation * hf)
			Local cc:Float = brightness * (1 - saturation * (1.0 - hf))

			Select (slice)
				Case 0
					red = brightness
					green = cc
					blue = aa

				Case 1
					red = bb
					green = brightness
					blue = aa

				Case 2
					red = aa
					green = brightness
					blue = cc

				Case 3
					red = aa
					green = bb
					blue = brightness

				Case 4
					red = cc
					green = aa
					blue = brightness

				Case 5
					red = brightness
					green = aa
					blue = bb

				Default
					red = 0
					green = 0
					blue = 0
			End Select
		End If

		If (alpha <= 1) alpha *= 255
		Return (alpha & $FF) Shl 24 | int(red * 255) Shl 16 | int(green * 255) Shl 8 | int(blue * 255)
	End Function

	Function GetRGBA:Float[](color:Int, resluts:Float[] = [])
		If (resluts.Length() <> 4) resluts = resluts.Resize(4)

		resluts[0] = (color Shr 16) & $FF
		resluts[1] = (color Shr 8) & $FF
		resluts[2] = color & $FF
		resluts[3] = Float((color Shr 24) & $FF) / 255
		Return resluts
	End Function

	Function GetHSB:Float[](color:Int, resluts:Float[] = [])
		If (resluts.Length() <> 4) resluts = resluts.Resize(4)

		Local red:Float = Float((color Shr 16) & $FF) / 255
		Local green:Float = Float((color Shr 8) & $FF) / 255
		Local blue:Float = Float(color & $FF) / 255

		Local m:Float = MonkeyMax(red, green)
		Local dmax:Float = MonkeyMax(m, blue)
		m = MonkeyMin(red, green)
		Local dmin:Float = MonkeyMin(m, blue)
		Local range:Float = dmax - dmin

		resluts[2] = dmax
		resluts[1] = 0
		resluts[0] = 0

		If (dmax <> 0) resluts[1] = range / dmax

		If (resluts[1] <> 0) Then
			If (red = dmax) Then
				resluts[0] = (green - blue) / range

			ElseIf (green = dmax) Then
				resluts[0] = 2 + (blue - red) / range

			ElseIf (blue = dmax) Then
				resluts[0] = 4 + (red - green) / range
			End If

			resluts[0] *= 60
			If (resluts[0] < 0) resluts[0] += 360
		End If

		resluts[3] = Float((color Shr 24) & $FF) / 255

		Return resluts
	End Function

	Function FormatTime:String(seconds:Float, showMS:Bool = False)
		Local timeString:StringStack = New StringStack()
		timeString.Push(Int(seconds / 60) + ":")

		Local timeStringHepler:Int = Int(seconds) Mod 60

		If (timeStringHepler < 10) Then
			timeString.Push("0")
		End If

		timeString.Push(timeStringHepler)

		If (showMS) Then
			timeString.Push(".")
			timeStringHepler = (seconds - Int(seconds)) * 100

			If (timeStringHepler < 10) Then
				timeString.Push("0")
			End If

			timeString.Push(timeStringHepler)
		End If

		Return timeString.Join("")
	End Function

	Function FormatMoney:String(amount:Float, showDecimal:Bool = True, englishStyle:Bool = True)
		Local helper:Int
		Local intAmount:Int = amount
		Local comma:String = ""
		Local result:String = ""
		Local zeroes:String = ""

		While (intAmount > 0)
			If (result.Length() > 0 And comma.Length() <= 0) Then
				If (englishStyle) Then
					comma = ","
				Else
					comma = "."
				End If
			End If

			helper = intAmount - Int(intAmount / 1000) * 1000
			intAmount /= 1000

			zeroes = ""

			If (intAmount > 0) Then
				If (helper < 100) Then
					zeroes = "0"
				End If

				If (helper < 10) Then
					zeroes = "00"
				End If
			End If

			result = zeroes + helper + comma + result
		Wend

		If (showDecimal) Then
			intAmount = Int(amount * 100) - (Int(amount) * 100)

			If (englishStyle) Then
				result += "." + intAmount
			Else
				result += "," + intAmount
			End If

			If (amount < 10) Then
				result += "0"
			End If
		End If

		Return result
	End Function

	Function GetClassName:String(obj:Object, simple:Bool = False)
		If (simple) Then
			Local name:String = MonkeyGetClass(obj).Name
			Return name[name.FindLast(".")+1..]
		End If

		Return MonkeyGetClass(obj).Name
	End Function

	Function CompareClassNames:Bool(object1:Object, object2:Object)
		Return (MonkeyGetClass(object1).Name = MonkeyGetClass(object2).Name)
	End Function

	Function GetClass:ClassInfo(name:String)
		Return MonkeyGetClass(name)
	End Function

	Function GetObjectClass:ClassInfo()
		If (_objClass <> Null)
			Return _objClass
		End If

		_objClass = MonkeyGetClass("monkey.lang.Object")

		Return _objClass
	End Function

	Function ComputeVelocity:Float(velocity:Float, acceleration:Float = 0, drag:Float = 0, max:Float = 10000)
		If (acceleration <> 0) Then
			velocity += acceleration * FlxG.Elapsed

		ElseIf (drag <> 0) Then
			drag *= FlxG.Elapsed

			If (velocity - drag > 0) Then
				velocity -= drag
			ElseIf (velocity + drag < 0) Then
				velocity += drag
			Else
				velocity = 0
			End If
		End If

		If (velocity <> 0 And max <> 10000) Then
			If (velocity > max) Then
				velocity = max
			ElseIf (velocity < -max) Then
				velocity = -max
			End If
		End If

		Return velocity
	End Function

	Function RotatePoint:FlxPoint(x:Float, y:Float, pivotX:Float, pivotY:Float, angle:Float, point:FlxPoint = Null)
		Local sin:Float = 0
		Local cos:Float = 0
		Local radians:Float = angle * -0.017453293

		While (radians < -PI)
			radians += TWOPI
		Wend

		While (radians > PI)
			radians = radians - TWOPI
		Wend

		If (radians < 0) Then
			sin =  1.27323954 * radians + .405284735 * radians * radians
			If (sin < 0) Then
				sin = .225 * (sin * -sin - sin) + sin
			Else
				sin = .225 * (sin * sin - sin) + sin
			End If
		Else
			sin = 1.27323954 * radians - 0.405284735 * radians * radians
			If (sin < 0) Then
				sin = .225 * (sin * -sin - sin) + sin
			Else
				sin = .225 * (sin * sin - sin) + sin
			End If
		End If

		radians += HALFPI
		If (radians > PI) radians -= TWOPI

		If (radians < 0) Then
			cos = 1.27323954 * radians + 0.405284735 * radians * radians
			If (cos < 0) Then
				cos = .225 * (cos * -cos - cos) + cos
			Else
				cos = .225 * (cos * cos - cos) + cos
			End If
		Else
			cos = 1.27323954 * radians - 0.405284735 * radians * radians
			If (cos < 0) Then
				cos = .225 * (cos * -cos - cos) + cos
			Else
				cos = .225 * (cos * cos - cos) + cos
			End If
		End If

		Local dx:Float = x - pivotX
		Local dy:Float = pivotY + y

		If (point = Null) point = New FlxPoint()
		point.x = pivotX + cos * dx - sin * dy
		point.y = pivotY - sin * dx - cos * dy

		Return point
	End Function

	Function GetAngle:Float(point1:FlxPoint, point2:FlxPoint)
		Local x:Float = point2.x - point1.x
		Local y:Float = point2.y - point1.y

		If (x = 0 And y = 0) Return 0

		Local c1:Float = PI * .25
		Local c2:Float = 3 * c1
		Local ay:Float = MonkeyAbs(y)
		Local angle:Float = 0

		If (x >= 0) Then
			angle = c1 - c1 * ((x - ay) / (x + ay))
		Else
			angle = c2 - c1 * ((x + ay) / (ay - x))
		End If

		If (y < 0) Then
			angle =	-angle * 57.2957796
		Else
			angle =	angle * 57.2957796
		End If

		If (angle > 90) Then
			angle = angle - 270
		Else
			angle += 90
		End If

		Return angle
	End Function

	Function GetDistance:Float(point1:FlxPoint, point2:FlxPoint)
		Local dx:Float = point1.x - point2.x
		Local dy:Float = point1.y - point2.y

		Return Sqrt(dx * dx + dy * dy)
	End Function

	Function GetDistance:Float(x1:Float, y1:Float, x2:Float, y2:Float)
		Local dx:Float = x1 - x2
		Local dy:Float = y1 - y2

		Return Sqrt(dx * dx + dy * dy)
	End Function

	Function SetImageMask:Image(image:Image, maskColor:Int)
		Local bitmapData:FlxImageData = FlxImageData.FromImage(image, True)
		bitmapData.ColorReplace(maskColor, 0)

		Local result:Image = bitmapData.Image
		bitmapData.Destroy()

		Return result
	End Function

	Function SetImagePadding:Image(image:Image, paddings:Int = Image.XYPadding)
		Local paddingX:Int, paddingY:Int

		If (paddings & Image.XPadding) paddingX = 1
		If (paddings & Image.YPadding) paddingY = 1

		Return FlxU.SetImagePadding(image, paddingX, paddingY)
	End Function

	Function SetImagePadding:Image(image:Image, paddingX:Int, paddingY:Int)
		Local bitmapData:FlxImageData = FlxImageData.FromImage(image, False, paddingX, paddingY)
		Local result:Image = bitmapData.Image
		bitmapData.Destroy()

		Return result
	End Function

End Class


Fixed delta movement of SnapFling

Fixed delta movement of SnapFling

#Rem
Copyright (c) 2011 Steve Revill and Shane Woolcock
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#End

#Rem
Header: Provides the SnapFlingStack class.
#End

Strict

Import diddy

Class SnapFlingStack Extends DiddyStack<SnapFlingObject>
	Field selected:SnapFlingObject
	Field endPositionX:Int = SCREEN_WIDTH2
	Field timerSpeed:Float = 0.04

	Method Update:Void()
		For Local i:SnapFlingObject = EachIn Self
			i.Update()
			If i <> selected
				' slow down the objects
				i.SetDx(i.GetDx() * 0.95)
				' stop run away floats
				If (i.GetDx() <> 0 and Abs(i.GetDx()) < 0.3) Then
					i.SetDx(0)
					GetSelectedObject()
				End
				i.MoveByXY(i.GetDx() * dt.delta, 0)
			End
		Next
		If selected
			If selected.GetTimer() <> 1
				Local mx:Float = BackEaseOutTween(selected.GetOx(), selected.GetEx(), selected.GetTimer())

				Local selectedDiff:Float = mx - selected.GetX()

				For Local i:SnapFlingObject = EachIn Self
					If i <> selected
						i.MoveByXY(selectedDiff, 0)
					End
				Next
				selected.MoveToXY(mx, selected.GetY())

				If selected.GetTimer() < 1
					Local t:Float = selected.GetTimer()
					t += selected.GetTimerSpeed() * dt.delta
					selected.SetTimer(t)
				Else
					selected.SetTimer(1)
				End
			End
		End
	End

	Method OnTouchHit:Void(x:Int, y:Int, pointer:Int)
		For Local i:SnapFlingObject = EachIn Self
			i.SetDx(0)
			i.SetDy(0)
			selected = Null
		End
	End

	Method OnTouchFling:Void(releaseX:Int, releaseY:Int, velocityX:Float, velocityY:Float, velocitySpeed:Float, pointer:Int)
		For Local i:SnapFlingObject = EachIn Self
			i.SetDx(velocityX / 100)
			selected = Null
		End
	End

	Method OnTouchDragged:Void(x:Int, y:Int, dx:Int, dy:Int, pointer:Int)
		For Local i:SnapFlingObject = EachIn Self
			i.SetDx(dx)
			selected = Null
		End
	End

	Method OnTouchReleased:Void(x:Int, y:Int, pointer:Int)
		GetSelectedObject()
	End

	Method GetSelectedObject:Void()
		' find the object most out of view percentage
		Local oldPercentage:Float = 0
		For Local i:SnapFlingObject = EachIn Self
			If i.GetPercentageOnScreen() < oldPercentage
				oldPercentage = i.GetPercentageOnScreen()
			End
		Next

		' find the object which is the most in view
		Local found:Bool = False
		For Local i:SnapFlingObject = EachIn Self
			If i.GetDx() = 0
				If i.GetPercentageOnScreen() > oldPercentage
					oldPercentage = i.GetPercentageOnScreen()
					selected = i
					found = True
				End
			End
		Next
		If found
			If selected
				selected.SetEx(endPositionX)
				selected.SetOx(selected.GetX())
				selected.SetTimer(0)
				selected.SetTimerSpeed(timerSpeed)
			End
		End
	End

	Method Render:Void()
		For Local i:SnapFlingObject = EachIn Self
			i.Render()
		End
	End
End

Interface SnapFlingObject
	Method MoveByXY:Void(dx:Float, dy:Float)
	Method MoveToXY:Void(x:Float, y:Float)
	Method GetPercentageOnScreen:Float()
	Method Update:Void()
	Method Render:Void()

	' getters / setters
	Method GetX:Float()
	Method GetY:Float()
	Method GetDx:Float()
	Method GetDy:Float()
	Method SetX:Void(val:Float)
	Method SetY:Void(val:Float)
	Method SetDx:Void(val:Float)
	Method SetDy:Void(val:Float)
	Method GetOx:Float()
	Method SetOx:Void(val:Float)
	Method GetEx:Float()
	Method SetEx:Void(val:Float)
	Method GetTimer:Float()
	Method SetTimer:Void(val:Float)
	Method GetTimerSpeed:Float()
	Method SetTimerSpeed:Void(val:Float)
End

#Rem
Copyright (c) 2011 Steve Revill and Shane Woolcock
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#End

#Rem
Header: Provides the SnapFlingStack class.
#End

Strict

Import diddy

Class SnapFlingStack Extends DiddyStack<SnapFlingObject>
	Field selected:SnapFlingObject
	Field endPositionX:Int = SCREEN_WIDTH2
	Field timerSpeed:Float = 0.04

	Method Update:Void()
		For Local i:SnapFlingObject = EachIn Self
			i.Update()
			If i <> selected
				' slow down the objects
				i.SetDx(i.GetDx() * 0.95 * dt.delta)

				' stop run away floats
				If i.GetDx() <> 0 and Abs(i.GetDx()) < 0.3 Then
					i.SetDx(0)
					GetSelectedObject()
				End
				i.MoveByXY(i.GetDx(), 0)
			End
		Next
		If selected
			If selected.GetTimer() <> 1
				Local mx:Float = BackEaseOutTween(selected.GetOx(), selected.GetEx(), selected.GetTimer())

				Local selectedDiff:Float = mx - selected.GetX()

				For Local i:SnapFlingObject = EachIn Self
					If i <> selected
						i.MoveByXY(selectedDiff, 0)
					End
				Next
				selected.MoveToXY(mx, selected.GetY())

				If selected.GetTimer() < 1
					Local t:Float = selected.GetTimer()
					t += selected.GetTimerSpeed() * dt.delta
					selected.SetTimer(t)
				Else
					selected.SetTimer(1)
				End
			End
		End
	End

	Method OnTouchHit:Void(x:Int, y:Int, pointer:Int)
		For Local i:SnapFlingObject = EachIn Self
			i.SetDx(0)
			i.SetDy(0)
			selected = Null
		End
	End

	Method OnTouchFling:Void(releaseX:Int, releaseY:Int, velocityX:Float, velocityY:Float, velocitySpeed:Float, pointer:Int)
		For Local i:SnapFlingObject = EachIn Self
			i.SetDx(velocityX / 100)
			selected = Null
		End
	End

	Method OnTouchDragged:Void(x:Int, y:Int, dx:Int, dy:Int, pointer:Int)
		For Local i:SnapFlingObject = EachIn Self
			i.SetDx(dx)
			selected = Null
		End
	End

	Method OnTouchReleased:Void(x:Int, y:Int, pointer:Int)
		GetSelectedObject()
	End

	Method GetSelectedObject:Void()
		' find the object most out of view percentage
		Local oldPercentage:Float = 0
		For Local i:SnapFlingObject = EachIn Self
			If i.GetPercentageOnScreen() < oldPercentage
				oldPercentage = i.GetPercentageOnScreen()
			End
		Next

		' find the object which is the most in view
		Local found:Bool = False
		For Local i:SnapFlingObject = EachIn Self
			If i.GetDx() = 0
				If i.GetPercentageOnScreen() > oldPercentage
					oldPercentage = i.GetPercentageOnScreen()
					selected = i
					found = True
				End
			End
		Next
		If found
			If selected
				selected.SetEx(endPositionX)
				selected.SetOx(selected.GetX())
				selected.SetTimer(0)
				selected.SetTimerSpeed(timerSpeed)
			End
		End
	End

	Method Render:Void()
		For Local i:SnapFlingObject = EachIn Self
			i.Render()
		End
	End
End

Interface SnapFlingObject
	Method MoveByXY:Void(dx:Float, dy:Float)
	Method MoveToXY:Void(x:Float, y:Float)
	Method GetPercentageOnScreen:Float()
	Method Update:Void()
	Method Render:Void()

	' getters / setters
	Method GetX:Float()
	Method GetY:Float()
	Method GetDx:Float()
	Method GetDy:Float()
	Method SetX:Void(val:Float)
	Method SetY:Void(val:Float)
	Method SetDx:Void(val:Float)
	Method SetDy:Void(val:Float)
	Method GetOx:Float()
	Method SetOx:Void(val:Float)
	Method GetEx:Float()
	Method SetEx:Void(val:Float)
	Method GetTimer:Float()
	Method SetTimer:Void(val:Float)
	Method GetTimerSpeed:Float()
	Method SetTimerSpeed:Void(val:Float)
End


Added specific tracing to each Assert, and added AssertNull function.

Strict

Const ASSERT_MESSAGE$ = "Assertion failed!"

#Rem
	Assertion functions.
	Call the corresponding Assert function with the check that you expect to pass.  If it fails, the
	error message will be thrown.
#End

Function Assert:Void(val?, msg$=ASSERT_MESSAGE)
	If Not val Then Error(msg)
End

Function AssertNull:Void(val:Object, msg$=ASSERT_MESSAGE)
	If val <> Null Then Error(msg)
End

Function AssertNotNull:Void(val:Object, msg$=ASSERT_MESSAGE)
	If val = Null Then Error(msg)
End

Function AssertEquals:Void(val%, expected%, msg$=ASSERT_MESSAGE)
	If val <> expected Then Error(msg + " " + val + "<>"+expected)
End

Function AssertEquals:Void(val#, expected#, msg$=ASSERT_MESSAGE)
	If val <> expected Then Error(msg + " " + val + "<>"+expected)
End

Function AssertEquals:Void(val$, expected$, msg$=ASSERT_MESSAGE)
	If val <> expected Then Error(msg + " " + val + "<>"+expected)
End

Function AssertEqualsIgnoreCase:Void(val$, expected$, msg$=ASSERT_MESSAGE)
	' TODO:
End

Function AssertNotEqual:Void(val%, expected%, msg$=ASSERT_MESSAGE)
	If val = expected Then Error(msg + " " + val + "="+expected)
End

Function AssertNotEqual:Void(val#, expected#, msg$=ASSERT_MESSAGE)
	If val = expected Then Error(msg + " " + val + "="+expected)
End

Function AssertNotEqual:Void(val$, expected$, msg$=ASSERT_MESSAGE)
	If val = expected Then Error(msg + " " + val + "="+expected)
End

Function AssertNotEqualIgnoreCase:Void(val$, expected$, msg$=ASSERT_MESSAGE)
	' TODO:
End

Function AssertLessThan:Void(val%, expected%, msg$=ASSERT_MESSAGE)
	If val >= expected Then Error(msg + " " + val + ">="+expected)
End

Function AssertLessThan:Void(val#, expected#, msg$=ASSERT_MESSAGE)
	If val >= expected Then Error(msg + " " + val + ">="+expected)
End

Function AssertGreaterThan:Void(val%, expected%, msg$=ASSERT_MESSAGE)
	If val <= expected Then Error(msg + " " + val + "<="+expected)
End

Function AssertGreaterThan:Void(val#, expected#, msg$=ASSERT_MESSAGE)
	If val <= expected Then Error(msg + " " + val + "<="+expected)
End

Function AssertLessThanOrEqual:Void(val%, expected%, msg$=ASSERT_MESSAGE)
	If val > expected Then Error(msg + " " + val + ">"+expected)
End

Function AssertLessThanOrEqual:Void(val#, expected#, msg$=ASSERT_MESSAGE)
	If val > expected Then Error(msg + " " + val + ">"+expected)
End

Function AssertGreaterThanOrEqual:Void(val%, expected%, msg$=ASSERT_MESSAGE)
	If val < expected Then Error(msg + " " + val + "<"+expected)
End

Function AssertGreaterThanOrEqual:Void(val#, expected#, msg$=ASSERT_MESSAGE)
	If val < expected Then Error(msg + " " + val + "<"+expected)
End

Function AssertRange:Void(val%, minbound%, maxbound%, msg$=ASSERT_MESSAGE)
	If val < minbound Or val >= maxbound Then Error(msg + " " + val + " is not " + minbound + "<=val<" + size)
End

Function AssertRange:Void(val%, minbound#, maxbound#, msg$=ASSERT_MESSAGE)
	If val < minbound Or val >= maxbound Then Error(msg + " " + val + " is not " + minbound + "<=val<" + size)
End

Function AssertRangeInclusive:Void(val%, minbound%, maxbound%, msg$=ASSERT_MESSAGE)
	If val < minbound Or val > maxbound Then Error(msg + " " + val + " is not " + minbound + "<=val<=" + size)
End

Function AssertRangeInclusive:Void(val%, minbound#, maxbound#, msg$=ASSERT_MESSAGE)
	If val < minbound Or val > maxbound Then Error(msg + " " + val + " is not " + minbound + "<=val<=" + size)
End

Strict

Const ASSERT_MESSAGE$ = "Assertion failed!"

#Rem
	Assertion functions.
	Call the corresponding Assert function with the check that you expect to pass.  If it fails, the
	error message will be thrown.
#End

Function Assert:Void(val?, msg$=ASSERT_MESSAGE)
	If Not val Then Error(msg)
End

Function AssertNotNull:Void(val:Object, msg$=ASSERT_MESSAGE)
	If val = Null Then Error(msg)
End

Function AssertEquals:Void(val%, expected%, msg$=ASSERT_MESSAGE)
	If val <> expected Then Error(msg)
End

Function AssertEquals:Void(val#, expected#, msg$=ASSERT_MESSAGE)
	If val <> expected Then Error(msg)
End

Function AssertEquals:Void(val$, expected$, msg$=ASSERT_MESSAGE)
	If val <> expected Then Error(msg)
End

Function AssertEqualsIgnoreCase:Void(val$, expected$, msg$=ASSERT_MESSAGE)
	' TODO:
End

Function AssertNotEqual:Void(val%, expected%, msg$=ASSERT_MESSAGE)
	If val = expected Then Error(msg)
End

Function AssertNotEqual:Void(val#, expected#, msg$=ASSERT_MESSAGE)
	If val = expected Then Error(msg)
End

Function AssertNotEqual:Void(val$, expected$, msg$=ASSERT_MESSAGE)
	If val = expected Then Error(msg)
End

Function AssertNotEqualIgnoreCase:Void(val$, expected$, msg$=ASSERT_MESSAGE)
	' TODO:
End

Function AssertLessThan:Void(val%, expected%, msg$=ASSERT_MESSAGE)
	If val >= expected Then Error(msg)
End

Function AssertLessThan:Void(val#, expected#, msg$=ASSERT_MESSAGE)
	If val >= expected Then Error(msg)
End

Function AssertGreaterThan:Void(val%, expected%, msg$=ASSERT_MESSAGE)
	If val <= expected Then Error(msg)
End

Function AssertGreaterThan:Void(val#, expected#, msg$=ASSERT_MESSAGE)
	If val <= expected Then Error(msg)
End

Function AssertLessThanOrEqual:Void(val%, expected%, msg$=ASSERT_MESSAGE)
	If val > expected Then Error(msg)
End

Function AssertLessThanOrEqual:Void(val#, expected#, msg$=ASSERT_MESSAGE)
	If val > expected Then Error(msg)
End

Function AssertGreaterThanOrEqual:Void(val%, expected%, msg$=ASSERT_MESSAGE)
	If val < expected Then Error(msg)
End

Function AssertGreaterThanOrEqual:Void(val#, expected#, msg$=ASSERT_MESSAGE)
	If val < expected Then Error(msg)
End

Function AssertRange:Void(val%, minbound%, maxbound%, msg$=ASSERT_MESSAGE)
	If val < minbound Or val >= maxbound Then Error(msg)
End

Function AssertRange:Void(val%, minbound#, maxbound#, msg$=ASSERT_MESSAGE)
	If val < minbound Or val >= maxbound Then Error(msg)
End

Function AssertRangeInclusive:Void(val%, minbound%, maxbound%, msg$=ASSERT_MESSAGE)
	If val < minbound Or val > maxbound Then Error(msg)
End

Function AssertRangeInclusive:Void(val%, minbound#, maxbound#, msg$=ASSERT_MESSAGE)
	If val < minbound Or val > maxbound Then Error(msg)
End