Fixed an overload problem with the 'Image' class's constructor.

Strict

Public

' Preprocessor related:
#MOJO_EMULATOR_FORCE_MOJO = True

#If BRL_GAMETARGET_IMPLEMENTED And MOJO_EMULATOR_FORCE_MOJO
	Import mojo.graphics
#Else
	#MOJO_EMULATOR_IMPLEMENTED = True

	#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)
				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
#End

Strict

Public

' Preprocessor related:
#MOJO_EMULATOR_FORCE_MOJO = True

#If BRL_GAMETARGET_IMPLEMENTED And MOJO_EMULATOR_FORCE_MOJO
	Import mojo.graphics
#Else
	#MOJO_EMULATOR_IMPLEMENTED = True

	#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
#End


Removed confusing method ;)

Removed confusing method ;)

--HG--
extra : convert_revision : svn%3Ae934d3cd-0d57-f34a-94d0-9e8d31ae1c29/trunk%4030

Strict

import diddy
Import mojo

Function Main:Int()
	game = new MyGame()
	Return 0
End Function

Global gameScreen:GameScreen
Global titleScreen:TitleScreen

Class MyGame Extends DiddyApp

	Method OnCreate:Int()
		Super.OnCreate()

		LoadImages()

		gameScreen = new GameScreen
		titleScreen = new TitleScreen

		titleScreen.PreStart()

		Return 0
	End

	'***********************
	'* Load Images
	'***********************
	Function LoadImages:Void()
		' create tmpImage for animations
		local tmpImage:Image

		images.LoadAnim("Ship1.png", 64, 64, 7, tmpImage)
	End
End

Class TitleScreen Extends Screen

	Method New()
		name = "Title"
	End

	Method Start:Void()
		game.screenFade.Start(50, false)
	End

	Method Render:Void()
		Cls
		DrawText "TITLE SCREEN!", SCREEN_WIDTH2, SCREEN_HEIGHT2, 0.5, 0.5
		DrawText "Click to Play!", SCREEN_WIDTH2, SCREEN_HEIGHT2 + 20, 0.5, 0.5
	End

	Method Update:Void()
		if KeyHit(KEY_SPACE) or MouseHit(0)
			game.screenFade.Start(50, true)
			game.nextScreen = gameScreen
		End
		If KeyHit(KEY_ESCAPE)
			game.screenFade.Start(50, true)
			game.nextScreen = game.exitScreen
		End
	End
End

Class GameScreen Extends Screen
	Field player:Player

	Method New()
		name = "Game"
	End

	Method Start:Void()
		game.screenFade.Start(50, false)
		player = new Player(game.images.Find("Ship1"), SCREEN_WIDTH2, SCREEN_HEIGHT2)
	End

	Method Render:Void()
		Cls
		player.Draw()
		DrawHUD()
	End

	Method Update:Void()
		player.UpdateAnimation()
		player.Update()

		if KeyHit(KEY_1)
			player.SetFrame(0, 6, 100, false, false)
		End
		if KeyHit(KEY_2)
			player.SetFrame(0, 6, 100, false, true)
		End
		if KeyHit(KEY_3)
			player.SetFrame(0, 6, 100, true, false)
		End
		if KeyHit(KEY_4)
			player.SetFrame(0, 6, 100, true, true)
		End

		if KeyHit(KEY_Q)
			player.SetFrame(6, 0, 100, false, false)
		End
		if KeyHit(KEY_W)
			player.SetFrame(6, 0, 100, false, true)
		End
		if KeyHit(KEY_E)
			player.SetFrame(6, 0, 100, true, false)
		End
		if KeyHit(KEY_R)
			player.SetFrame(6, 0, 100, true, true)
		End

		if KeyHit(KEY_ESCAPE)
			game.screenFade.Start(50, true)
			game.nextScreen = titleScreen
		End
	End

	Method DrawHUD:Void()
		DrawText("frame = "+player.frame, 10, 0)

		If player.pingPong
			DrawText("pingPong = true" , 10, 30)
		else
			DrawText("pingPong = false" , 10, 30)
		End
		If player.loop
			DrawText("loop = true" , 10, 60)
		Else
			DrawText("loop = false" , 10, 60)
		End
		DrawText("startFrame = "+player.frameStart, 10, 90)
		DrawText("startEnd = "+player.frameEnd, 10, 120)

		DrawText("Press 1 - 4 to change animation", 10, 150)

		DrawText("Press <ESC> to return to the Title Screen", 10, SCREEN_HEIGHT-12)

		FPSCounter.Draw(SCREEN_WIDTH, SCREEN_HEIGHT  - 12, 1)

	End
End

Class Player Extends Sprite
    Field vx:Float, vy:Float
    Field ax:Float, ay:Float
    Field direction:Float

	Method New(gi:GameImage, x#, y#)
		Super.New(gi, x, y)
		direction = -90
		frame = 3
	End

	Method Update:Void()
		Local Acceleration:Float

		If KeyDown(KEY_UP)
			Acceleration=.2
		else If KeyDown(KEY_DOWN)
			Acceleration=-.2
		Else
			Acceleration=0
		End If
		If KeyDown(KEY_LEFT)
			direction-=2
			self.rotation+=2
		End If
		If KeyDown(KEY_RIGHT)
			direction+=2
			self.rotation-=2
		End If

		Local ax:Float = Acceleration * Cos(direction)
		Local ay:Float = Acceleration * Sin(direction)

		vx+=ax
		vy+=ay
		x+=vx * dt.delta
		y+=vy * dt.delta

		If x < 0 x = SCREEN_WIDTH
		If x > SCREEN_WIDTH x = 0
		If y < 0 y = SCREEN_HEIGHT
		If y > SCREEN_HEIGHT y = 0
	End

End

Strict

import diddy
Import mojo

Function Main:Int()
	game = new MyGame()
	Return 0
End Function

Global gameScreen:GameScreen
Global titleScreen:TitleScreen

Class MyGame Extends DiddyApp

	Method OnCreate:Int()
		Super.OnCreate()

		LoadImages()

		gameScreen = new GameScreen
		titleScreen = new TitleScreen

		titleScreen.PreStart()

		Return 0
	End

	'***********************
	'* Load Images
	'***********************
	Function LoadImages:Void()
		' create tmpImage for animations
		local tmpImage:Image

		images.LoadAnim("Ship1.png", 64, 64, 7, tmpImage)
	End
End

Class TitleScreen Extends Screen

	Method New()
		name = "Title"
	End

	Method Start:Void()
		game.screenFade.Start(50, false)
	End

	Method Render:Void()
		Cls
		DrawText "TITLE SCREEN!", SCREEN_WIDTH2, SCREEN_HEIGHT2, 0.5, 0.5
		DrawText "Click to Play!", SCREEN_WIDTH2, SCREEN_HEIGHT2 + 20, 0.5, 0.5
	End

	Method Update:Void()
		if KeyHit(KEY_SPACE) or MouseHit(0)
			game.screenFade.Start(50, true)
			game.nextScreen = gameScreen
		End
		If KeyHit(KEY_ESCAPE)
			game.screenFade.Start(50, true)
			game.nextScreen = game.exitScreen
		End
	End
End

Class GameScreen Extends Screen
	Field player:Player

	Method New()
		name = "Game"
	End

	Method Start:Void()
		game.screenFade.Start(50, false)
		player = new Player(game.images.Find("Ship1"), SCREEN_WIDTH2, SCREEN_HEIGHT2)
	End

	Method Render:Void()
		Cls
		player.Draw()
		DrawHUD()
	End

	Method Update:Void()
		player.UpdateAnimation()
		player.Update()

		if KeyHit(KEY_1)
			player.SetFrame(0, 6, 100, false, false)
		End
		if KeyHit(KEY_2)
			player.SetFrame(0, 6, 100, false, true)
		End
		if KeyHit(KEY_3)
			player.SetFrame(0, 6, 100, true, false)
		End
		if KeyHit(KEY_4)
			player.SetFrame(0, 6, 100, true, true)
		End

		if KeyHit(KEY_Q)
			player.SetFrame(6, 0, 100, false, false)
		End
		if KeyHit(KEY_W)
			player.SetFrame(6, 0, 100, false, true)
		End
		if KeyHit(KEY_E)
			player.SetFrame(6, 0, 100, true, false)
		End
		if KeyHit(KEY_R)
			player.SetFrame(6, 0, 100, true, true)
		End

		if KeyHit(KEY_ESCAPE)
			game.screenFade.Start(50, true)
			game.nextScreen = titleScreen
		End
	End

	Method DrawHUD:Void()
		DrawText("frame = "+player.frame, 10, 0)

		If player.pingPong
			DrawText("pingPong = true" , 10, 30)
		else
			DrawText("pingPong = false" , 10, 30)
		End
		If player.loop
			DrawText("loop = true" , 10, 60)
		Else
			DrawText("loop = false" , 10, 60)
		End
		DrawText("startFrame = "+player.frameStart, 10, 90)
		DrawText("startEnd = "+player.frameEnd, 10, 120)

		DrawText("Press 1 - 4 to change animation", 10, 150)

		DrawText("Press <ESC> to return to the Title Screen", 10, SCREEN_HEIGHT-12)

		FPSCounter.Draw(SCREEN_WIDTH, SCREEN_HEIGHT  - 12, 1)

	End
End

Class Player Extends Sprite
    Field vx:Float, vy:Float
    Field ax:Float, ay:Float
    Field direction:Float

	Method New(gi:GameImage, x#, y#)
		Super.New(gi, x, y)
		direction = -90
		frame = 3
	End

	Method Update:Void()
		Local Acceleration:Float

		If KeyDown(KEY_UP)
			Acceleration=.2
		else If KeyDown(KEY_DOWN)
			Acceleration=-.2
		Else
			Acceleration=0
		End If
		If KeyDown(KEY_LEFT)
			direction-=2
			self.rotation+=2
		End If
		If KeyDown(KEY_RIGHT)
			direction+=2
			self.rotation-=2
		End If

		Local ax:Float = Acceleration * Cos(direction)
		Local ay:Float = Acceleration * Sin(direction)

		vx+=ax
		vy+=ay
		x+=vx * dt.delta
		y+=vy * dt.delta

		If x < 0 x = SCREEN_WIDTH
		If x > SCREEN_WIDTH x = 0
		If y < 0 y = SCREEN_HEIGHT
		If y > SCREEN_HEIGHT y = 0
	End

	Method draw:Void()
		Super.draw()
	End

End


Add Revert() to Vector2D

Add Revert() to Vector2D

Strict

Class Vector2D
    Field x:Float
    Field y:Float

    Method New(x:Float=0, y:Float=0)
        Self.x = x
        Self.y = y
    End

    Method IsZero:Bool()
        Return (x = 0 And y = 0)
    End

    Method Length:Float()
        Return Sqrt(x * x + y * y)
    End

    Method DotProduct:Float(v2:Vector2D)
        Return (x * v2.x) + (y * v2.y)
    End

    Method CrossProduct:Float(v2:Vector2D)
        Return (x * v2.y) - (y * v2.x)
    End

    Method Distance:Float(v2:Vector2D)
        Return Sqrt((v2.x - x)) + Sqrt((v2.y - y))
    End

    Method Equal:Bool(v2:Vector2D)
        Return (x = v2.x And y = v2.y)
    End

    Method Copy:Vector2D()
        Return New Vector2D(x, y)
    End

    Method Normalize:Vector2D()
        Local length:Float = Length()
        If length = 0 Then Return Self

        x /= length
        y /= length

        Return Self
    End

    Method Rotate:Vector2D(angle:Float)
        Local tmpX:Float = (x * Cos(angle)) - (y * Sin(angle))
        Local tmpY:Float = (y * Cos(angle)) - (x * Sin(angle))

        x = tmpX
        y = tmpY

        Return Self
    End

    Method Revert:Vector2D()
        x *= -1
        y *= -1

        Return Self
    End

    Method Add:Vector2D(v2:Vector2D)
        x += v2.x
        y += v2.y
        Return Self
    End

    Method Add:Vector2D(factor:Float)
        x += factor
        y += factor
        Return Self
    End

    Method Sub:Vector2D(v2:Vector2D)
        x -= v2.x
        y -= v2.y
        Return Self
    End

    Method Sub:Vector2D(factor:Float)
        x -= factor
        y -= factor
        Return Self
    End

    Method Mul:Vector2D(v2:Vector2D)
        x *= v2.x
        y *= v2.y
        Return Self
    End

    Method Mul:Vector2D(factor:Float)
        x *= factor
        y *= factor
        Return Self
    End

    Method Div:Vector2D(v2:Vector2D)
        x /= v2.x
        y /= v2.y
        Return Self
    End

    Method Div:Vector2D(factor:Float)
        y /= factor
        x /= factor
        Return Self
    End

    Method ToString:String()
        Return "(" + x + ", " + y + ")"
    End
End

Strict

Class Vector2D
    Field x:Float
    Field y:Float

    Method New(x:Float=0, y:Float=0)
        Self.x = x
        Self.y = y
    End

    Method IsZero:Bool()
        Return (x = 0 And y = 0)
    End

    Method Length:Float()
        Return Sqrt(x * x + y * y)
    End

    Method DotProduct:Float(v2:Vector2D)
        Return (x * v2.x) + (y * v2.y)
    End

    Method CrossProduct:Float(v2:Vector2D)
        Return (x * v2.y) - (y * v2.x)
    End

    Method Distance:Float(v2:Vector2D)
        Return Sqrt((v2.x - x)) + Sqrt((v2.y - y))
    End

    Method Equal:Bool(v2:Vector2D)
        Return (x = v2.x And y = v2.y)
    End

    Method Copy:Vector2D()
        Return New Vector2D(x, y)
    End

    Method Normalize:Vector2D()
        Local length:Float = Length()
        If length = 0 Then Return Self

        x /= length
        y /= length

        Return Self
    End

    Method Rotate:Vector2D(angle:Float)
        Local tmpX:Float = (x * Cos(angle)) - (y * Sin(angle))
        Local tmpY:Float = (y * Cos(angle)) - (x * Sin(angle))

        x = tmpX
        y = tmpY

        Return Self
    End

    Method Add:Vector2D(v2:Vector2D)
        x += v2.x
        y += v2.y
        Return Self
    End

    Method Add:Vector2D(factor:Float)
        x += factor
        y += factor
        Return Self
    End

    Method Sub:Vector2D(v2:Vector2D)
        x -= v2.x
        y -= v2.y
        Return Self
    End

    Method Sub:Vector2D(factor:Float)
        x -= factor
        y -= factor
        Return Self
    End

    Method Mul:Vector2D(v2:Vector2D)
        x *= v2.x
        y *= v2.y
        Return Self
    End

    Method Mul:Vector2D(factor:Float)
        x *= factor
        y *= factor
        Return Self
    End

    Method Div:Vector2D(v2:Vector2D)
        x /= v2.x
        y /= v2.y
        Return Self
    End

    Method Div:Vector2D(factor:Float)
        y /= factor
        x /= factor
        Return Self
    End

    Method ToString:String()
        Return "(" + x + ", " + y + ")"
    End
End


Sprite code cleaned a little bit

Sprite code cleaned a little bit

Strict

Private

Import align
Import basedisplayobject
Import bono.kernel
Import bono.utils
Import mojo.graphics

Public

Class Sprite Extends BaseDisplayObject
    Private

    Field currentFrame:Int
    Field frameCount:Int
    Field frameSize:Vector2D
    Field frameTimer:Int
    Field image:Image
    Field imageName:String
    Field _scale:Vector2D = New Vector2D(1, 1)
    Field _halign:Int = Align.LEFT
    Field _valign:Int = Align.TOP
    Field renderPos:Vector2D

    Public

    Field frameSpeed:Int
    Field loopAnimation:Bool
    Field rotation:Float

    Method New(imageName:String, pos:Vector2D=Null)
        Self.imageName = imageName

        LoadImage()
        If pos Then SetPosition(pos)
    End

    Method New(imageName:String, frameSize:Vector2D, frameCount:Int, frameSpeed:Int, pos:Vector2D=Null)
        Self.imageName = imageName
        Self.frameSize = frameSize
        Self.frameCount = frameCount
        Self.frameSpeed = frameSpeed

        LoadImage()
        If pos Then SetPosition(pos)
    End

    Method OnRender:Void()
        If Not renderPos Then CalculateRenderPos()
        GetColor().Activate()
        DrawImage(image, renderPos.x, renderPos.y, rotation, scale.x, scale.y, currentFrame)
        GetColor().Deactivate()
    End

    Method OnUpdate:Void(deltaTimer:DeltaTimer)
        If frameCount <= 0 Then Return
        If animationIsDone Then Return

        If frameTimer < frameSpeed
            frameTimer += deltaTimer.frameTime
            Return
        End

        If (currentFrame + 1) = frameCount
            If loopAnimation
                currentFrame = 1
            End
        Else
            currentFrame += 1
        End
        frameTimer = 0
    End

    Method Restart:Void()
        currentFrame = 0
    End

    Method animationIsDone:Bool() Property
        If loopAnimation Then Return False
        Return (currentFrame = frameCount)
    End

    Method scale:Vector2D() Property
        Return _scale
    End

    Method scale:Void(newScale:Vector2D) Property
        If image Then GetSize().Div(_scale).Mul(newScale)
        _scale = newScale
    End

    Method filepath:String() Property
        Return imageName
    End

    Method halign:Int() Property
        Return _halign
    End

    Method halign:Void(newAlign:Int) Property
        _halign = newAlign
        renderPos = Null
    End

    Method valign:Int() Property
        Return _valign
    End

    Method valign:Void(newAlign:Int) Property
        _valign = newAlign
        renderPos = Null
    End

    Method SetPosition:Void(newPos:Vector2D)
        Super.SetPosition(newPos)
        renderPos = Null
    End

    Method Collide:Bool(checkPos:Vector2D)
        Local offset:Vector2D = New Vector2D()
        Align.AdjustHorizontal(offset, Self, halign)
        Align.AdjustVertical(offset, Self, valign)

        Return Super.Collide(checkPos.Copy().Sub(offset))
    End

    Private

    Method CalculateRenderPos:Void()
        renderPos = GetPosition().Copy()
        Align.AdjustHorizontal(renderPos, Self, halign)
        Align.AdjustVertical(renderPos, Self, valign)
    End

    Method LoadImage:Void()
        If frameSize
            image = graphics.LoadImage(imageName, frameSize.x, frameSize.y, frameCount)
            SetSize(frameSize.Copy())
        Else
            image = graphics.LoadImage(imageName)
            SetSize(New Vector2D(image.Width(), image.Height()))
        End

        If Not image Then Error("Unable to load: " + imageName)
        GetSize().Mul(scale)
    End
End

Strict

Private

Import align
Import basedisplayobject
Import bono.kernel
Import bono.utils
Import mojo.graphics

Public

Class Sprite Extends BaseDisplayObject
    Private

    Field currentFrame:Int
    Field frameCount:Int
    Field frameSize:Vector2D
    Field frameTimer:Int
    Field image:Image
    Field imageName:String
    Field _scale:Vector2D = New Vector2D(1, 1)
    Field _halign:Int = Align.LEFT
    Field _valign:Int = Align.TOP
    Field renderPos:Vector2D

    Public

    Field frameSpeed:Int
    Field loopAnimation:Bool
    Field rotation:Float

    Method New(imageName:String, pos:Vector2D=Null)
        SetNameAndPos(imageName, pos)
        LoadImage()
    End

    Method New(imageName:String, frameSize:Vector2D, frameCount:Int, frameSpeed:Int, pos:Vector2D=Null)
        Self.frameSize = frameSize
        Self.frameCount = frameCount
        Self.frameSpeed = frameSpeed

        SetNameAndPos(imageName, pos)
        LoadImage()
    End

    Method OnRender:Void()
        If Not renderPos Then CalculateRenderPos()
        GetColor().Activate()
        DrawImage(image, renderPos.x, renderPos.y, rotation, scale.x, scale.y, currentFrame)
        GetColor().Deactivate()
    End

    Method OnUpdate:Void(deltaTimer:DeltaTimer)
        If frameCount <= 0 Then Return
        If animationIsDone Then Return

        If frameTimer < frameSpeed
            frameTimer += deltaTimer.frameTime
            Return
        End

        If (currentFrame + 1) = frameCount
            If loopAnimation
                currentFrame = 1
            End
        Else
            currentFrame += 1
        End
        frameTimer = 0
    End

    Method Restart:Void()
        currentFrame = 0
    End

    Method animationIsDone:Bool() Property
        If loopAnimation Then Return False
        Return (currentFrame = frameCount)
    End

    Method scale:Vector2D() Property
        Return _scale
    End

    Method scale:Void(newScale:Vector2D) Property
        If image Then GetSize().Div(_scale).Mul(newScale)
        _scale = newScale
    End

    Method filepath:String() Property
        Return imageName
    End

    Method halign:Int() Property
        Return _halign
    End

    Method halign:Void(newAlign:Int) Property
        _halign = newAlign
        renderPos = Null
    End

    Method valign:Int() Property
        Return _valign
    End

    Method valign:Void(newAlign:Int) Property
        _valign = newAlign
        renderPos = Null
    End

    Method SetPosition:Void(newPos:Vector2D)
        Super.SetPosition(newPos)
        renderPos = Null
    End

    Method Collide:Bool(checkPos:Vector2D)
        Local offset:Vector2D = New Vector2D()
        Align.AdjustHorizontal(offset, Self, halign)
        Align.AdjustVertical(offset, Self, valign)

        Return Super.Collide(checkPos.Copy().Sub(offset))
    End

    Private

    Method CalculateRenderPos:Void()
        renderPos = GetPosition().Copy()
        Align.AdjustHorizontal(renderPos, Self, halign)
        Align.AdjustVertical(renderPos, Self, valign)
    End

    Method LoadImage:Void()
        If frameSize
            image = graphics.LoadImage(imageName, frameSize.x, frameSize.y, frameCount)
            SetSize(frameSize.Copy())
        Else
            image = graphics.LoadImage(imageName)
            SetSize(New Vector2D(image.Width(), image.Height()))
        End

        If Not image Then Error("Unable to load: " + imageName)
        GetSize().Mul(scale)
    End

    Method SetNameAndPos:Void(imageName:String, pos:Vector2D=Null)
        Self.imageName = imageName
        If Not pos Then pos = New Vector2D(0, 0)
        Self.SetPosition(pos)
    End
End


Framework started

Framework started

--HG--
extra : convert_revision : svn%3Ae934d3cd-0d57-f34a-94d0-9e8d31ae1c29/trunk%4022

'
' Module diddy.diddy
'

Import functions
Import framework


FPS stabilization fixe

FPS stabilization fixe

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

	Field _replayCallback:FlxReplayListener

Private
	Field _iState:FlxClass

	Field _created:Bool

	Field _lostFocus:Bool

	Field _step:Int

	Field _soundTrayTimer:Float

	Field _soundTrayWidth:Float

	Field _soundTrayHeight:Float

	Field _soundTrayX:Float

	Field _soundTrayY:Float

	Field _soundTrayVisible:Bool

	Field _soundTrayLabel:FlxText

	Field _updatesCounter:FlxFPSCounter

	Field _rendersCounter:FlxFPSCounter

	Field _updatesLoopUsed:Bool

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

		useSoundHotKeys = Not IsMobile()
		Self.useSystemCursor = useSystemCursor
		useVirtualResolution = True
		If (Not useSystemCursor) HideMouse()
		_debuggerUp = False

		_state = Null

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

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

		_soundTrayTimer = 0
		_soundTrayWidth = 160
		_soundTrayHeight = 60
		_soundTrayX = 0
		_soundTrayY	= -_soundTrayHeight
		_soundTrayVisible = False

		_updatesCounter = New FlxFPSCounter()
		_rendersCounter = New FlxFPSCounter()
	End Method

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

		_soundTrayX	= (FlxG.Width / 2) * FlxCamera.DefaultZoom - (_soundTrayWidth / 2)
		_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()
		_updatesCounter.Update()

		If (_updatesLoopUsed Or _updatesCounter.FPS - _rendersCounter.FPS > 10) Then
			'Real elapsed time very unstable in Monkey. TODO!
			FlxG.Elapsed = FlxG.TimeScale * (1.0 / _updatesCounter.FPS)
			_Step()
			_updatesLoopUsed = True
		End If

		Return 0
	End Method

	Method OnRender:Int()
		_rendersCounter.Update()

		If (Not _updatesLoopUsed) Then
			'Real elapsed time very unstable in Monkey. TODO!
			FlxG.Elapsed = FlxG.TimeScale * (1.0 / _rendersCounter.FPS)
			_Step()
		End If

		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 (_soundTrayVisible) Then
				Local globalVolume:Int = FlxU.Round(FlxG.Volume() * 10)
				If (FlxG.Mute) globalVolume = 0

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

				If (FlxG._LastDrawingColor <> FlxG.WHITE) Then
					SetColor(255, 255, 255)
					FlxG._LastDrawingColor = FlxG.WHITE
				End If

				PushMatrix()
				Translate(_soundTrayX, _soundTrayY)

				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

		FlxG.Mouse.Draw()

		#Rem
		#If CONFIG = "debug"
			SetColor(255, 255, 255)
			DrawText("Renders: " + _rendersCounter.FPS, 10, 10)
			DrawText("Updates: " + _updatesCounter.FPS, 10, 25)

			If (_updatesLoopUsed) Then
				DrawText("Updates loop: ENABLED", 10, 40)
			Else
				DrawText("Updates loop: DISABLED", 10, 40)
			End If
		#End
		#End

		Return 0
	End Method

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

	Method OnResume:Int()
		If (Not _debuggerUp And useSystemCursor) Then
			HideMouse()
		End If
		FlxG.ResetInput()
		FlxG.ResumeSounds()
		_ResetFPSCounters()
		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()

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

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

		_state = _requestedState
		_state.Create()
		_ResetFPSCounters()
	End Method

	Method _Step:Void()
		#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()
		#End

		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 _UpdateSoundTray:Void()
		If (Not _soundTrayVisible) Return

		If (_soundTrayTimer > 0) Then
			_soundTrayTimer -= FlxG.Elapsed

		ElseIf (_soundTrayY > -_soundTrayHeight)
			_soundTrayY =_soundTrayY - (FlxG.Elapsed * FlxG.Height * 2)

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

				'TODO Save sound settings
			End If
		End If
	End Method

	Method _Update:Void()
		FlxG.UpdateSounds()
		FlxG.UpdatePlugins()
		_state.Update()
		FlxG.UpdateCameras()
	End Method

	Method _Reset:Void()
		SetUpdateRate(FlxG.Framerate)
		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

		_step = 1000.0 / FlxG.Framerate
		_ResetFPSCounters()
	End Method

	Method _ResetFPSCounters:Void()
		_updatesCounter.Reset()
		_rendersCounter.Reset()
		_updatesLoopUsed = False
	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

	Field realFPS:Int

Private
	Field _FPSCounter:Int

	Field _lastUpdateTime:Int

	Field _isReset:Bool

Public
	Method New()
		Reset()
	End Method

	Method Update:Void()
		If (_isReset) Then
			If (_FPSCounter = 2) Then
				_lastUpdateTime = Millisecs()

			ElseIf (_FPSCounter = 3) Then
				Local deltaTime:Int = Millisecs() - _lastUpdateTime

				If (deltaTime > 0) Then
					FPS = 1000 / deltaTime
				End If

				_lastUpdateTime = Millisecs()
				_isReset = False
				_FPSCounter = 0
			End If
		Else
			If (Millisecs() - _lastUpdateTime >= 1000) Then
				FPS = _FPSCounter
				_lastUpdateTime = Millisecs()
				_FPSCounter = 0
			End If
		End If

		_FPSCounter += 1
	End Method

	Method Reset:Void()
		FPS = FlxG.Framerate
		realFPS = FPS
		_FPSCounter = 0
		_lastUpdateTime = 0
		_isReset = True
	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:Int

	Field _replayCallback:FlxReplayListener

Private
	Field _iState:FlxClass

	Field _created:Bool

	Field _lostFocus:Bool

	Field _step:Int

	Field _soundTrayTimer:Float

	Field _soundTrayWidth:Float

	Field _soundTrayHeight:Float

	Field _soundTrayX:Float

	Field _soundTrayY:Float

	Field _soundTrayVisible:Bool

	Field _soundTrayLabel:FlxText

	Field _updatesCounter:FlxFPSCounter

	Field _rendersCounter:FlxFPSCounter

	Field _updatesLoopUsed:Bool

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

		useSoundHotKeys = Not IsMobile()
		Self.useSystemCursor = useSystemCursor
		useVirtualResolution = True
		If (Not useSystemCursor) HideMouse()
		_debuggerUp = False

		_state = Null

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

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

		_soundTrayTimer = 0
		_soundTrayWidth = 160
		_soundTrayHeight = 60
		_soundTrayX = 0
		_soundTrayY	= -_soundTrayHeight
		_soundTrayVisible = False

		_updatesCounter = New FlxFPSCounter()
		_rendersCounter = New FlxFPSCounter()
	End Method

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

		_soundTrayX	= (FlxG.Width / 2) * FlxCamera.DefaultZoom - (_soundTrayWidth / 2)
		_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()
		_updatesCounter.Update()

		If (_updatesLoopUsed Or (_rendersCounter.FPS >= 0 And _rendersCounter.FPS < FlxG.Framerate - 10)) Then
			'Real elapsed time very unstable in Monkey. TODO!
			FlxG.Elapsed = FlxG.TimeScale * (1.0 / _updatesCounter.FPS)
			_Step()

			_updatesLoopUsed = True
		End If
		Return 0
	End Method

	Method OnRender:Int()
		If (Not _updatesLoopUsed) Then
			_rendersCounter.Update()

			'Real elapsed time very unstable in Monkey. TODO!
			FlxG.Elapsed = FlxG.TimeScale * (1.0 / _rendersCounter.FPS)
			_Step()
		End If

		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 (_soundTrayVisible) Then
				Local globalVolume:Int = FlxU.Round(FlxG.Volume() * 10)
				If (FlxG.Mute) globalVolume = 0

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

				If (FlxG._LastDrawingColor <> FlxG.WHITE) Then
					SetColor(255, 255, 255)
					FlxG._LastDrawingColor = FlxG.WHITE
				End If

				PushMatrix()
				Translate(_soundTrayX, _soundTrayY)

				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

		FlxG.Mouse.Draw()

		#If CONFIG = "debug"
			SetColor(255, 255, 255)
			DrawText("FPS: " + _rendersCounter.FPS, 10, 10)
		#End

		Return 0
	End Method

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

	Method OnResume:Int()
		If (Not _debuggerUp And 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()

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

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

		_state = _requestedState
		_state.Create()
	End Method

	Method _Step:Void()
		#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()
		#End

		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 _UpdateSoundTray:Void()
		If (Not _soundTrayVisible) Return

		If (_soundTrayTimer > 0) Then
			_soundTrayTimer -= FlxG.Elapsed

		ElseIf (_soundTrayY > -_soundTrayHeight)
			_soundTrayY =_soundTrayY - (FlxG.Elapsed * FlxG.Height * 2)

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

				'TODO Save sound settings
			End If
		End If
	End Method

	Method _Update:Void()
		FlxG.UpdateSounds()
		FlxG.UpdatePlugins()
		_state.Update()
		FlxG.UpdateCameras()
	End Method

	Method _Reset:Void()
		SetUpdateRate(FlxG.Framerate)
		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

		_step = 1000.0 / FlxG.Framerate

		_updatesCounter.Reset()
		_rendersCounter.Reset()
		_updatesLoopUsed = False
	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 _lastFPSCounter:Int

	Field _lastUpdateTime:Int

Public
	Method New()
		Reset()
	End Method

	Method Update:Void()
		If (FPS < 0) Then
			_lastUpdateTime = Millisecs()
			FPS = FlxG.Framerate
			_lastFPSCounter = FPS
		Else
			If (Millisecs() - _lastUpdateTime > 1000) Then
				If (Abs(_lastFPSCounter - _FPSCounter) < 10) Then
					FPS = _FPSCounter
				End If

				_lastFPSCounter = _FPSCounter
				_FPSCounter = 0
				_lastUpdateTime = Millisecs()
			Else
				_FPSCounter += 1
			End If
		End If
	End Method

	Method Reset:Void()
		FPS = -1
		_FPSCounter = 0
		_lastFPSCounter = 0
		_lastUpdateTime = 0
	End Method

End Class