Fixed PathFinding example array out of bounds error

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

Strict

Import diddy

Global gameScreen:GameScreen

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

Class MyGame Extends DiddyApp

	Method OnCreate:Int()
		Super.OnCreate()
		gameScreen = New GameScreen
		game.Start(gameScreen)
		Return 0
	End
End

Class GameScreen Extends Screen
	Const MAP_WIDTH:Int = 20
	Const MAP_HEIGHT:Int = 20
	Const TILE_SIZE:Int = 20

	Field grid:Float[MAP_WIDTH * MAP_HEIGHT]
	Field fx:Int, fy:Int
	Field mx:Int, my:Int
	Field startX:Int = 1, startY:Int = 1
	Field endX:Int = 10, endY:Int = 15
	Field x:Float, y:Float
	Field i:Int
	Field z:Int, g:Float
	Field currentPath:Int = 0

	Method New()
		name = "Game"
	End

	Method Start:Void()
		PathFinder.SetMap(grid, MAP_WIDTH, MAP_HEIGHT, 2, 0)
		x = startX * TILE_SIZE
		y = startY * TILE_SIZE
	End

	Method Render:Void()
		Cls

		'Draw grid tiles
		For fy = 0 Until MAP_HEIGHT
			For fx = 0 Until  MAP_WIDTH
				If grid[fx + fy * MAP_WIDTH] > 0 Then
					SetColor grid[fx + fy * 20] * 255, 0, 0
					DrawRect fx * TILE_SIZE, fy * TILE_SIZE, TILE_SIZE, TILE_SIZE
				End
			Next
		Next

		'Draw grid lines
		SetColor 255, 255, 255
		For fx = 0 To MAP_WIDTH
			DrawLine fx * TILE_SIZE, 0, fx * TILE_SIZE, MAP_HEIGHT * TILE_SIZE
			DrawLine 0, fx * TILE_SIZE, MAP_WIDTH * TILE_SIZE, fx * TILE_SIZE
		Next

		'Draw the "player" position
		SetColor 255, 0, 255
		DrawOval x, y, TILE_SIZE, TILE_SIZE

		'Draw end position
		SetColor 255, 255, 0
		DrawOval endX * TILE_SIZE, endY * TILE_SIZE, TILE_SIZE, TILE_SIZE

		'Draw path
		SetColor 0, 255, 0
		For i = 0 Until PathFinder.paths * 2 Step 2
			DrawRect PathFinder.route[i] * TILE_SIZE + TILE_SIZE/2, PathFinder.route[i + 1] * TILE_SIZE+ TILE_SIZE/2, 5, 5
		Next

		SetColor 255, 255, 255
		DrawHUD()
	End

	Method SetPath:Void()
		startX = x / TILE_SIZE
		startY = y / TILE_SIZE
		PathFinder.FindPath(startX, startY, endX, endY)
		currentPath = (PathFinder.paths - 1) * 2
	End

	Method Update:Void()
		mx = game.mouseX / TILE_SIZE
		my = game.mouseY / TILE_SIZE
		mx = Max(mx, 0)
		mx = Min(mx, 19)
		my = Max(my, 0)
		my = Min(my, 19)

		If MouseDown(0) Then
			grid[mx + my * MAP_WIDTH] = 1
			SetPath()
		End

		If MouseDown(MOUSE_MIDDLE) Then
			grid[mx + my * MAP_WIDTH] = 0
			SetPath()
		End

		If KeyHit(KEY_SPACE)
			endX = mx
			endY = my
			SetPath()
		End

		If currentPath >= 0 And PathFinder.route.Length() > 0
			If x < PathFinder.route[currentPath] * TILE_SIZE
				x += 1
			End
			If x > PathFinder.route[currentPath] * TILE_SIZE
				x -= 1
			End
			If y < PathFinder.route[currentPath + 1] * TILE_SIZE
				y += 1
			End
			If y > PathFinder.route[currentPath + 1] * TILE_SIZE
				y -= 1
			End

			If x = PathFinder.route[currentPath] * TILE_SIZE And
				y = PathFinder.route[currentPath + 1] * TILE_SIZE
				currentPath -= 2
			End
		End

		If KeyHit(KEY_ESCAPE)
			FadeToScreen(Null)
		End
	End

	Method DrawHUD:Void()
		DrawText "No. of paths = "+ PathFinder.paths, SCREEN_WIDTH, 10, 1
		DrawText "Mouse Grid = "+ mx+ "," + my, SCREEN_WIDTH, 30, 1
		If PathFinder.route.Length() > 0 Then DrawText "currentPath = " + PathFinder.route[currentPath] + "," + PathFinder.route[currentPath + 1], SCREEN_WIDTH, 30, 1
		FPSCounter.Draw(SCREEN_WIDTH, SCREEN_HEIGHT  - 12, 1)
	End
End

Strict

Import diddy

Global gameScreen:GameScreen

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

Class MyGame Extends DiddyApp

	Method OnCreate:Int()
		Super.OnCreate()
		gameScreen = New GameScreen
		game.Start(gameScreen)
		Return 0
	End
End

Class GameScreen Extends Screen
	Const MAP_WIDTH:Int = 20
	Const MAP_HEIGHT:Int = 20
	Const TILE_SIZE:Int = 20

	Field grid:Float[MAP_WIDTH * MAP_HEIGHT]
	Field fx:Int, fy:Int
	Field mx:Int, my:Int
	Field startX:Int = 1, startY:Int = 1
	Field endX:Int = 10, endY:Int = 15
	Field x:Float, y:Float
	Field i:Int
	Field z:Int, g:Float
	Field currentPath:Int = 0

	Method New()
		name = "Game"
	End

	Method Start:Void()
		PathFinder.SetMap(grid, MAP_WIDTH, MAP_HEIGHT, 2, 0)
		x = startX * TILE_SIZE
		y = startY * TILE_SIZE
	End

	Method Render:Void()
		Cls

		'Draw grid tiles
		For fy = 0 Until MAP_HEIGHT
			For fx = 0 Until  MAP_WIDTH
				If grid[fx + fy * MAP_WIDTH] > 0 Then
					SetColor grid[fx + fy * 20] * 255, 0, 0
					DrawRect fx * TILE_SIZE, fy * TILE_SIZE, TILE_SIZE, TILE_SIZE
				End
			Next
		Next

		'Draw grid lines
		SetColor 255, 255, 255
		For fx = 0 To MAP_WIDTH
			DrawLine fx * TILE_SIZE, 0, fx * TILE_SIZE, MAP_HEIGHT * TILE_SIZE
			DrawLine 0, fx * TILE_SIZE, MAP_WIDTH * TILE_SIZE, fx * TILE_SIZE
		Next

		'Draw the "player" position
		SetColor 255, 0, 255
		DrawOval x, y, TILE_SIZE, TILE_SIZE

		'Draw end position
		SetColor 255, 255, 0
		DrawOval endX * TILE_SIZE, endY * TILE_SIZE, TILE_SIZE, TILE_SIZE

		'Draw path
		SetColor 0, 255, 0
		For i = 0 Until PathFinder.paths * 2 Step 2
			DrawRect PathFinder.route[i] * TILE_SIZE + TILE_SIZE/2, PathFinder.route[i + 1] * TILE_SIZE+ TILE_SIZE/2, 5, 5
		Next

		SetColor 255, 255, 255
		DrawHUD()
	End

	Method SetPath:Void()
		startX = x / TILE_SIZE
		startY = y / TILE_SIZE
		PathFinder.FindPath(startX, startY, endX, endY)
		currentPath = (PathFinder.paths - 1) * 2
	End

	Method Update:Void()
		mx = game.mouseX / TILE_SIZE
		my = game.mouseY / TILE_SIZE
		mx = Max(mx, 0)
		mx = Min(mx, 19)
		my = Max(my, 0)
		my = Min(my, 19)

		If MouseDown(0) Then
			grid[mx + my * MAP_WIDTH] = 1
			SetPath()
		End

		If MouseDown(MOUSE_MIDDLE) Then
			grid[mx + my * MAP_WIDTH] = 0
			SetPath()
		End

		If KeyHit(KEY_SPACE)
			endX = mx
			endY = my
			SetPath()
		End

		If currentPath >= 0
			If x < PathFinder.route[currentPath] * TILE_SIZE
				x += 1
			End
			If x > PathFinder.route[currentPath] * TILE_SIZE
				x -= 1
			End
			If y < PathFinder.route[currentPath + 1] * TILE_SIZE
				y += 1
			End
			If y > PathFinder.route[currentPath + 1] * TILE_SIZE
				y -= 1
			End

			If x = PathFinder.route[currentPath] * TILE_SIZE And
				y = PathFinder.route[currentPath + 1] * TILE_SIZE
				currentPath -= 2
			End
		End

		If KeyHit(KEY_ESCAPE)
			FadeToScreen(Null)
		End
	End

	Method DrawHUD:Void()
		DrawText "No. of paths = "+ PathFinder.paths, SCREEN_WIDTH, 10, 1
		DrawText "Mouse Grid = "+ mx+ "," + my, SCREEN_WIDTH, 30, 1
		DrawText "currentPath = " + PathFinder.route[currentPath] + "," + PathFinder.route[currentPath + 1], SCREEN_WIDTH, 30, 1
		FPSCounter.Draw(SCREEN_WIDTH, SCREEN_HEIGHT  - 12, 1)
	End
End


Gfk's filesystem changes:
"Converted the filesystem mod to Little Endian, also added in the ReadBool/WriteBool methods"

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

Strict
Import mojo

Class FileSystem Extends DataConversion
Private
	Field _header:String = "MKYDATA"
	Field fileData:String
	Field index:StringMap<FileStream>
Public

	Method New()
		Self.LoadAll()
	End

	Method WriteFile:FileStream(filename:String)
		Local f:FileStream = new FileStream
		f.filename = filename
		f.fileptr = 0
		Self.index.Set(f.filename.ToLower(),f)
		Return f
	End

	Method ReadFile:FileStream(filename:String)
		filename = filename.ToLower()
		Local f:FileStream
		f = Self.index.ValueForKey(filename)
		f.fileptr = 0
		Return f
	End

	Method FileExists:Bool(filename:String)
		filename = filename.ToLower()
		if Self.index.Contains(filename)
			Return True
		Else
			Return False
		End
		Return False
	End

	Method ListDir:Void()
		Local filename:String
		Local stream:FileStream
		Print "Directory Listing:"
		For filename = EachIn Self.index.Keys()
			stream = Self.index.ValueForKey(filename)
			Print filename + "   " + stream.data.Length()+" byte(s)."
		Next
	End

	Method DeleteFile:Void(filename:String)
		filename = filename.ToLower()
		if Self.index.Contains(filename)
			Self.index.Remove(filename)
		End
	End

	Method SaveAll:Void()
		Local f:FileStream
		Self.fileData = Self._header'header
		self.fileData+= Self.IntToString(Self.index.Count())'number of files in index
		if Self.index.Count() > 0
			For f = EachIn Self.index.Values()
				'store filename
				Self.fileData+= Self.IntToString(f.filename.Length())
				if f.filename.Length() > 0
					Self.fileData+= f.filename
				End
				'store data
				Self.fileData+= Self.IntToString(f.data.Length())
				if f.data.Length() > 0
					Self.fileData+= f.data
				End
			Next
		End
		SaveState(Self.fileData)
	End

	Method LoadAll:Void()
		Local numFiles:Int
		Local stream:FileStream
		Local len:Int
		Local ptr:Int
		Self.fileData = LoadState()
		self.index = New StringMap<FileStream>
		if Self.fileData.Length() > 0
			if Self.fileData.StartsWith(Self._header)
				Self.index.Clear()
				ptr+=Self._header.Length()
				numFiles = Self.StringToInt(Self.fileData[ptr..ptr+4])
				ptr+=4
				if numFiles > 0
					For Local n:Int = 1 to numFiles
						stream = New FileStream
						'filename
						len = Self.StringToInt(Self.fileData[ptr..ptr+4])
						ptr+=4
						if len > 0
							stream.filename = Self.fileData[ptr..ptr+len]
							ptr+=len
						End
						'data
						len = Self.StringToInt(Self.fileData[ptr..ptr+4])
						ptr+=4
						if len > 0
							stream.data = Self.fileData[ptr..ptr+len]
							ptr+=len
						End
						Self.index.Set(stream.filename,stream)
					Next
				End
			End
		Else
			SaveState(Self._header+Self.IntToString(0))'save empty file and indicate no files stored
		End
	End
End

Class FileStream Extends DataConversion
	Field filename:String
	Field fileptr:Int
Private
	Field data:String
Public

	Method ReadInt:Int()
		Local result:string
		result = Self.data[Self.fileptr..self.fileptr+4]
		Self.fileptr+=4
		Return Self.StringToInt(result)
	End

	Method WriteInt:Void(val:Int)
		Self.data+=Self.IntToString(val)
	End

	Method ReadString:String()
		Local result:String
		Local strLen:Int = self.StringToInt(self.data[self.fileptr..self.fileptr+4])
		Self.fileptr+=4
		if strLen > 0
			result = Self.data[Self.fileptr..self.fileptr+strLen]
			Self.fileptr+=strLen
		End
		Return result
	End

	Method WriteString:Void(val:String)
		Self.data+=Self.IntToString(val.Length())
		if val.Length() > 0
			Self.data+=val
		End
	End

	Method ReadFloat:Float()
		Local result:float
		Local s:String
		Local strLen:Int = self.StringToInt(self.data[self.fileptr..self.fileptr+4])
		Self.fileptr+=4
		s = Self.data[Self.fileptr..self.fileptr+strLen]
		result = Self.StringToFloat(s)
		Self.fileptr+=strLen
		Return result
	End

	Method WriteFloat:Void(val:Float)
		Local s:String = self.FloatToString(val)
		Self.data+=Self.IntToString(s.Length())
		Self.data+=s
	End

	Method ReadBool:Bool()
		Local result:Bool
		result = Bool(Self.data[Self.fileptr])
		Self.fileptr+=1
		Return result
	End Method

	Method WriteBool:Void(val:Bool)
		Self.data+=String.FromChar(val)
	End Method
End

Class DataConversion
	Method IntToString:String(val:Int)
		Local result:String
		result = String.FromChar((val) & $FF)
		result+= String.FromChar((val Shr 8) & $FF)
		result+= String.FromChar((val Shr 16) & $FF)
		result+= String.FromChar((val Shr 24) & $FF)
		Return result
	End

	Method FloatToString:String(val:Float)
		Return String(val)
	End

	Method StringToInt:Int(val:String)
		Local result:Int
		result = (val[0])
		result|= (val[1] Shl 8)
		result|= (val[2] Shl 16)
		result|= (val[3] Shl 24)
		Return result
	End

	Method StringToFloat:Float(val:String)
		Return Float(val)
	End
End

Strict
Import mojo

Class FileSystem Extends DataConversion
Private
	Field _header:String = "MKYDATA"
	Field fileData:String
	Field index:StringMap<FileStream>
Public

	Method New()
		Self.LoadAll()
	End

	Method WriteFile:FileStream(filename:String)
		Local f:FileStream = new FileStream
		f.filename = filename
		f.fileptr = 0
		Self.index.Set(f.filename.ToLower(),f)
		Return f
	End

	Method ReadFile:FileStream(filename:String)
		filename = filename.ToLower()
		Local f:FileStream
		f = Self.index.ValueForKey(filename)
		f.fileptr = 0
		Return f
	End

	Method FileExists:Bool(filename:String)
		filename = filename.ToLower()
		if Self.index.Contains(filename)
			Return True
		Else
			Return False
		End
	End

	Method ListDir:Void()
		Local filename:String
		Local stream:FileStream
		Print "Directory Listing:"
		For filename = EachIn Self.index.Keys()
			stream = Self.index.ValueForKey(filename)
			Print filename + "   " + stream.data.Length()+" byte(s)."
		Next
	End

	Method DeleteFile:Void(filename:String)
		filename = filename.ToLower()
		if Self.index.Contains(filename)
			Self.index.Remove(filename)
		End
	End

	Method SaveAll:Void()
		Local f:FileStream
		Self.fileData = Self._header'header
		self.fileData+= Self.IntToString(Self.index.Count())'number of files in index
		if Self.index.Count() > 0
			For f = EachIn Self.index.Values()
				'store filename
				Self.fileData+= Self.IntToString(f.filename.Length())
				if f.filename.Length() > 0
					Self.fileData+= f.filename
				End
				'store data
				Self.fileData+= Self.IntToString(f.data.Length())
				if f.data.Length() > 0
					Self.fileData+= f.data
				End
			Next
		End
		SaveState(Self.fileData)
	End

	Method LoadAll:Void()
		Local numFiles:Int
		Local stream:FileStream
		Local len:Int
		Local ptr:Int
		Self.fileData = LoadState()
		self.index = New StringMap<FileStream>
		if Self.fileData.Length() > 0
			if Self.fileData.StartsWith(Self._header)
				Self.index.Clear()
				ptr+=Self._header.Length()
				numFiles = Self.StringToInt(Self.fileData[ptr..ptr+4])
				ptr+=4
				if numFiles > 0
					For Local n:Int = 1 to numFiles
						stream = New FileStream
						'filename
						len = Self.StringToInt(Self.fileData[ptr..ptr+4])
						ptr+=4
						if len > 0
							stream.filename = Self.fileData[ptr..ptr+len]
							ptr+=len
						End
						'data
						len = Self.StringToInt(Self.fileData[ptr..ptr+4])
						ptr+=4
						if len > 0
							stream.data = Self.fileData[ptr..ptr+len]
							ptr+=len
						End
						Self.index.Set(stream.filename,stream)
					Next
				End
			End
		Else
			SaveState(Self._header+Self.IntToString(0))'save empty file and indicate no files stored
		End
	End
End

Class FileStream Extends DataConversion
	Field filename:String
	Field fileptr:Int
Private
	Field data:String
Public

	Method ReadInt:Int()
		Local result:string
		result = Self.data[Self.fileptr..self.fileptr+4]
		Self.fileptr+=4
		Return Self.StringToInt(result)
	End

	Method WriteInt:Void(val:Int)
		Self.data+=Self.IntToString(val)
	End

	Method ReadString:String()
		Local result:String
		Local strLen:Int = self.StringToInt(self.data[self.fileptr..self.fileptr+4])
		Self.fileptr+=4
		if strLen > 0
			result = Self.data[Self.fileptr..self.fileptr+strLen]
			Self.fileptr+=strLen
			Return result
		End
	End

	Method WriteString:Void(val:String)
		Self.data+=Self.IntToString(val.Length())
		if val.Length() > 0
			Self.data+=val
		End
	End

	Method ReadFloat:Float()
		Local result:float
		Local s:String
		Local strLen:Int = self.StringToInt(self.data[self.fileptr..self.fileptr+4])
		Self.fileptr+=4
		s = Self.data[Self.fileptr..self.fileptr+strLen]
		result = Self.StringToFloat(s)
		Self.fileptr+=strLen
		Return result
	End

	Method WriteFloat:Void(val:Float)
		Local s:String = self.FloatToString(val)
		Self.data+=Self.IntToString(s.Length())
		Self.data+=s
	End
End

Class DataConversion
	Method IntToString:String(val:Int)
		Local result:String
		result = String.FromChar((val Shr 24) & $FF)
		result+= String.FromChar((val Shr 16) & $FF)
		result+= String.FromChar((val Shr 8) & $FF)
		result+= String.FromChar(val & $FF)
		Return result
	End

	Method FloatToString:String(val:Float)
		Return String(val)
	End

	Method StringToInt:Int(val:String)
		Local result:Int
		result = (val[0] Shl 24)
		result|= (val[1] Shl 16)
		result|= (val[2] Shl 8)
		result|= val[3]
		Return result
	End

	Method StringToFloat:Float(val:String)
		Return Float(val)
	End
End


Fixed FlxEmitter ClassObject

Fixed FlxEmitter ClassObject

Strict

Import reflection

Import flxextern
Import flxgroup
Import flxpoint
Import flxsprite
Import flxparticle
Import flxobject
Import flxg

Class FlxEmitter Extends FlxGroup

	Global ClassObject:Object

	Field x:Float

	Field y:Float

	Field width:Float

	Field height:Float

	Field minParticleSpeed:FlxPoint

	Field maxParticleSpeed:FlxPoint

	Field particleDrag:FlxPoint

	Field minRotation:Float

	Field maxRotation:Float

	Field gravity:Float

	Field on:Bool

	Field frequency:Float

	Field lifespan:Float

	Field bounce:Float

	Field particleClass:ClassInfo

Private
	Field _quantity:Int

	Field _explode:Bool

	Field _timer:Float

	Field _counter:Int

	Field _point:FlxPoint

Public
	Method New(x:Float = 0, y:Float = 0, size:Float = 0)
		Super.New(size)
		Self.x = x
		Self.y = y
		width = 0
		height = 0
		minParticleSpeed = New FlxPoint(-100, -100)
		maxParticleSpeed = New FlxPoint(100, 100)
		minRotation = -360
		maxRotation = 360
		gravity = 0
		particleClass = Null
		particleDrag = New FlxPoint()
		frequency = 0.1
		lifespan = 3
		bounce = 0
		_quantity = 0
		_counter = 0
		_explode = True
		on = False
		_point = New FlxPoint()
	End Method

	Method Destroy:Void()
		minParticleSpeed = Null
		maxParticleSpeed = Null
		particleDrag = Null
		particleClass = Null
		_point = Null

		Super.Destroy()
	End Method

	Method MakeParticles:FlxEmitter(graphic:String, quantity:Int = 50, backedRotations:Int = 16, multiple:Bool = False, collide:Float = 0)
		MaxSize = quantity

		Local totalFrames:Int = 1

		If (multiple) Then
			Local sprite:FlxSprite = New FlxSprite()
			sprite.LoadGraphic(graphic, True)
			totalFrames = sprite.frames
			sprite.Destroy()
		End If

		Local randomFrame:Int
		Local particle:FlxParticle
		Local i:Int = 0

		While (i < quantity)
			If (particleClass = Null) Then
				particle = New FlxParticle()
			Else
				particle = FlxParticle(particleClass.NewInstance())
			End If

			If (multiple) Then
				randomFrame = FlxG.Random() * totalFrames

				If (backedRotations > 0) Then
					particle.LoadRotatedGraphic(graphic, backedRotations, randomFrame)
				Else
					particle.LoadGraphic(graphic, True)
					particle.Frame = randomFrame
				End If
			Else
				If (backedRotations > 0) Then
					particle.LoadRotatedGraphic(graphic, backedRotations)
				Else
					particle.LoadGraphic(graphic)
				End If
			End If

			If (collide > 0) Then
				particle.width *= collide
				particle.height *= collide
				particle.CenterOffsets()
			Else
				particle.allowCollisions = FlxObject.NONE
			End If

			particle.exists = False
			Add(particle)

			i += 1
		Wend

		Return Self
	End Method

	Method Update:Void()
		If (on) Then
			If (_explode) Then
				on = False

				Local i:Int = 0
				Local l:Int = _quantity

				If (l <= 0 Or l > Length) Then
					l = Length
				End If

				While (i < l)
					EmitParticle()
					i += 1
				Wend

				_quantity = 0
			Else
				_timer += FlxG.Elapsed

				While (frequency > 0 And _timer > frequency And on)
					_timer -= frequency
					EmitParticle()

					_counter += 1
					If (_quantity > 0 And _counter >= _quantity) Then
						on = False
						_quantity = 0
					End If
				Wend
			End If
		End If

		Super.Update()
	End Method

	Method Kill:Void()
		on = False
		Super.Kill()
	End Method

	Method Start:Void(explode:Bool = True, lifespan:Float = 0, frequency:Float = .1, quantity:Int = 0)
		Revive()
		visible = True
		on = True

		_explode = explode
		Self.lifespan = lifespan
		Self.frequency = frequency
		_quantity += quantity

		_counter = 0
		_timer = 0
	End Method

	Method EmitParticle:Void()
		Local particle:FlxParticle = FlxParticle(Recycle(FlxParticle.__CLASS__))
		particle.lifespan = lifespan
		particle.elasticity = bounce
		particle.Reset(x - (particle.width Shr 1) + FlxG.Random() * width, y - (particle.height Shr 1) + FlxG.Random() * height)
		particle.visible = True

		If (minParticleSpeed.x <> maxParticleSpeed.x) Then
			particle.velocity.x = minParticleSpeed.x + FlxG.Random() * (maxParticleSpeed.x - minParticleSpeed.x)
		Else
			particle.velocity.x = minParticleSpeed.x
		End If

		If (minParticleSpeed.y <> maxParticleSpeed.y) Then
			particle.velocity.y = minParticleSpeed.y + FlxG.Random() * (maxParticleSpeed.y - minParticleSpeed.y)
		Else
			particle.velocity.y = minParticleSpeed.y
		End If

		particle.acceleration.y = gravity

		If (minRotation <> maxRotation) Then
			particle.angularVelocity = minRotation + FlxG.Random() * (maxRotation - minRotation)
		Else
			particle.angularVelocity = minRotation
		End If

		If (particle.angularVelocity <> 0) Then
			particle.angle = FlxG.Random()*360 - 180
		End If

		particle.drag.x = particleDrag.x
		particle.drag.y = particleDrag.y

		particle.OnEmit()
	End Method

	Method SetSize:Void(width:Int, height:Int)
		Self.width = width
		Self.height = height
	End Method

	Method SetXSpeed:Void(min:Float = 0, max:Float = 0)
		minParticleSpeed.x = min
		maxParticleSpeed.x = max
	End Method

	Method SetYSpeed:Void(min:Float = 0, max:Float = 0)
		minParticleSpeed.y = min
		maxParticleSpeed.y = max
	End Method

	Method SetRotation:Void(min:Float = 0, max:Float = 0)
		minRotation = min
		maxRotation = max
	End Method

	Method At:Void(object:FlxObject)
		object.GetMidpoint(_point)
		x = _point.x - (width Shr 1)
		y = _point.y - (height Shr 1)
	End Method

End Class

Strict

Import reflection

Import flxextern
Import flxgroup
Import flxpoint
Import flxsprite
Import flxparticle
Import flxobject
Import flxg

Class FlxEmitter Extends FlxGroup

	Global __CLASS__:Object

	Field x:Float

	Field y:Float

	Field width:Float

	Field height:Float

	Field minParticleSpeed:FlxPoint

	Field maxParticleSpeed:FlxPoint

	Field particleDrag:FlxPoint

	Field minRotation:Float

	Field maxRotation:Float

	Field gravity:Float

	Field on:Bool

	Field frequency:Float

	Field lifespan:Float

	Field bounce:Float

	Field particleClass:ClassInfo

Private
	Field _quantity:Int

	Field _explode:Bool

	Field _timer:Float

	Field _counter:Int

	Field _point:FlxPoint

Public
	Method New(x:Float = 0, y:Float = 0, size:Float = 0)
		Super.New(size)
		Self.x = x
		Self.y = y
		width = 0
		height = 0
		minParticleSpeed = New FlxPoint(-100, -100)
		maxParticleSpeed = New FlxPoint(100, 100)
		minRotation = -360
		maxRotation = 360
		gravity = 0
		particleClass = Null
		particleDrag = New FlxPoint()
		frequency = 0.1
		lifespan = 3
		bounce = 0
		_quantity = 0
		_counter = 0
		_explode = True
		on = False
		_point = New FlxPoint()
	End Method

	Method Destroy:Void()
		minParticleSpeed = Null
		maxParticleSpeed = Null
		particleDrag = Null
		particleClass = Null
		_point = Null

		Super.Destroy()
	End Method

	Method MakeParticles:FlxEmitter(graphic:String, quantity:Int = 50, backedRotations:Int = 16, multiple:Bool = False, collide:Float = 0)
		MaxSize = quantity

		Local totalFrames:Int = 1

		If (multiple) Then
			Local sprite:FlxSprite = New FlxSprite()
			sprite.LoadGraphic(graphic, True)
			totalFrames = sprite.frames
			sprite.Destroy()
		End If

		Local randomFrame:Int
		Local particle:FlxParticle
		Local i:Int = 0

		While (i < quantity)
			If (particleClass = Null) Then
				particle = New FlxParticle()
			Else
				particle = FlxParticle(particleClass.NewInstance())
			End If

			If (multiple) Then
				randomFrame = FlxG.Random() * totalFrames

				If (backedRotations > 0) Then
					particle.LoadRotatedGraphic(graphic, backedRotations, randomFrame)
				Else
					particle.LoadGraphic(graphic, True)
					particle.Frame = randomFrame
				End If
			Else
				If (backedRotations > 0) Then
					particle.LoadRotatedGraphic(graphic, backedRotations)
				Else
					particle.LoadGraphic(graphic)
				End If
			End If

			If (collide > 0) Then
				particle.width *= collide
				particle.height *= collide
				particle.CenterOffsets()
			Else
				particle.allowCollisions = FlxObject.NONE
			End If

			particle.exists = False
			Add(particle)

			i += 1
		Wend

		Return Self
	End Method

	Method Update:Void()
		If (on) Then
			If (_explode) Then
				on = False

				Local i:Int = 0
				Local l:Int = _quantity

				If (l <= 0 Or l > Length) Then
					l = Length
				End If

				While (i < l)
					EmitParticle()
					i += 1
				Wend

				_quantity = 0
			Else
				_timer += FlxG.Elapsed

				While (frequency > 0 And _timer > frequency And on)
					_timer -= frequency
					EmitParticle()

					_counter += 1
					If (_quantity > 0 And _counter >= _quantity) Then
						on = False
						_quantity = 0
					End If
				Wend
			End If
		End If

		Super.Update()
	End Method

	Method Kill:Void()
		on = False
		Super.Kill()
	End Method

	Method Start:Void(explode:Bool = True, lifespan:Float = 0, frequency:Float = .1, quantity:Int = 0)
		Revive()
		visible = True
		on = True

		_explode = explode
		Self.lifespan = lifespan
		Self.frequency = frequency
		_quantity += quantity

		_counter = 0
		_timer = 0
	End Method

	Method EmitParticle:Void()
		Local particle:FlxParticle = FlxParticle(Recycle(ClassInfo(FlxParticle.__CLASS__)))
		particle.lifespan = lifespan
		particle.elasticity = bounce
		particle.Reset(x - (particle.width Shr 1) + FlxG.Random() * width, y - (particle.height Shr 1) + FlxG.Random() * height)
		particle.visible = True

		If (minParticleSpeed.x <> maxParticleSpeed.x) Then
			particle.velocity.x = minParticleSpeed.x + FlxG.Random() * (maxParticleSpeed.x - minParticleSpeed.x)
		Else
			particle.velocity.x = minParticleSpeed.x
		End If

		If (minParticleSpeed.y <> maxParticleSpeed.y) Then
			particle.velocity.y = minParticleSpeed.y + FlxG.Random() * (maxParticleSpeed.y - minParticleSpeed.y)
		Else
			particle.velocity.y = minParticleSpeed.y
		End If

		particle.acceleration.y = gravity

		If (minRotation <> maxRotation) Then
			particle.angularVelocity = minRotation + FlxG.Random() * (maxRotation - minRotation)
		Else
			particle.angularVelocity = minRotation
		End If

		If (particle.angularVelocity <> 0) Then
			particle.angle = FlxG.Random()*360 - 180
		End If

		particle.drag.x = particleDrag.x
		particle.drag.y = particleDrag.y

		particle.OnEmit()
	End Method

	Method SetSize:Void(width:Int, height:Int)
		Self.width = width
		Self.height = height
	End Method

	Method SetXSpeed:Void(min:Float = 0, max:Float = 0)
		minParticleSpeed.x = min
		maxParticleSpeed.x = max
	End Method

	Method SetYSpeed:Void(min:Float = 0, max:Float = 0)
		minParticleSpeed.y = min
		maxParticleSpeed.y = max
	End Method

	Method SetRotation:Void(min:Float = 0, max:Float = 0)
		minRotation = min
		maxRotation = max
	End Method

	Method At:Void(object:FlxObject)
		object.GetMidpoint(_point)
		x = _point.x - (width Shr 1)
		y = _point.y - (height Shr 1)
	End Method

End Class


add Color.FromHSV

add Color.FromHSV

Strict

Private

Import bono
Import mojo.graphics

Public

Class Color
    Private

    Field oldColor:Color
    Field _red:Float
    Field _green:Float
    Field _blue:Float
    Field _alpha:Float

    Public

    Const MIN:Float = 0.0
    Const MAX:Float = 255.0

    Method New(hex:String)
        FromHex(hex)
    End

    Method New(red:Float=MAX, green:Float=MAX, blue:Float=MAX, alpha:Float=MAX)
        _red = red
        _green = green
        _blue = blue
        _alpha = alpha
        UpdateBounds()
    End

    Method Reset:Void()
        _red = MAX
        _green = MAX
        _blue = MAX
        _alpha = MAX
    End

    Method Randomize:Void()
        _red = MAX * Rnd()
        _green = MAX * Rnd()
        _blue = MAX * Rnd()
        _alpha = MAX * Rnd()
    End

    Method Activate:Void()
        If Not oldColor Then oldColor = New Color(MIN, MIN, MIN, MIN)

        Local colorStack:Float[] = GetColor()
        oldColor.red = colorStack[0]
        oldColor.green = colorStack[1]
        oldColor.blue = colorStack[2]
        oldColor.alpha = GetAlpha()

        MojoSet(Self)
    End

    Method Deactivate:Void()
        If Not oldColor Then Return
        MojoSet(oldColor)
        oldColor = Null
    End

    Method Copy:Color()
        Return New Color(_red, _green, _blue, _alpha)
    End

    Method Set:Void(newColor:Color)
        red = newColor.red
        green = newColor.green
        blue = newColor.blue
        alpha = newColor.alpha
    End

    Method FromHex:Void(hex:String)
        If hex.StartsWith("#") Then hex = hex[1..]
        Local value:Int = MathHelper.HexToInt(hex)

        _red = value Shr 16 & $0000ff
        _green = value Shr 8 & $0000ff
        _blue = value & $0000ff
        _alpha = MAX
    End

    Method ToHex:String()
        Return "#" +
            MathHelper.IntToHex(_red) +
            MathHelper.IntToHex(_green) +
            MathHelper.IntToHex(_blue)
    End

    Method FromHSV:Void(h:Float, s:Float, v:Float)
        Local hi := Int(h * 6)
        Local f := h * 6 - hi
        Local p := v * (1 - s)
        Local q := v * (1 - f * s)
        Local t := v * (1 - (1 - f) * s)

        Select hi
        Case 0
            redFloat = v
            greenFloat = t
            blueFloat = p
        Case 1
            redFloat = q
            greenFloat = v
            blueFloat = p
        Case 2
            redFloat = p
            greenFloat = q
            blueFloat = t
        Case 3
            redFloat = p
            greenFloat = q
            blueFloat = v
        Case 4
            redFloat = t
            greenFloat = p
            blueFloat = v
        Case 5
            redFloat = v
            greenFloat = p
            blueFloat = q
        End
    End

    Method Equals:Bool(color:Color)
        If Not (color.red = _red) Then Return False
        If Not (color.green = _green) Then Return False
        If Not (color.blue = _blue) Then Return False
        If Not (color.alpha = _alpha) Then Return False
        Return True
    End

    Method ToString:String()
        Return "(Red: " + _red + " Green: " + _green + " Blue: " + _blue + " Alpha: " + alphaFloat + ")"
    End

    Method red:Float() Property
        Return _red
    End

    Method red:Void(value:Float) Property
        _red = value
        UpdateBounds()
    End

    Method redFloat:Float() Property
        Return _red / MAX
    End

    Method redFloat:Void(value:Float) Property
        _red = MAX * value
        UpdateBounds()
    End

    Method green:Float() Property
        Return _green
    End

    Method green:Void(value:Float) Property
        _green = value
        UpdateBounds()
    End

    Method greenFloat:Float() Property
        Return _green / MAX
    End

    Method greenFloat:Void(value:Float) Property
        _green = MAX * value
        UpdateBounds()
    End

    Method blue:Float() Property
        Return _blue
    End

    Method blue:Void(value:Float) Property
        _blue = value
        UpdateBounds()
    End

    Method blueFloat:Float() Property
        Return _blue / MAX
    End

    Method blueFloat:Void(value:Float) Property
        _blue = MAX * value
        UpdateBounds()
    End

    Method alpha:Float() Property
        Return _alpha
    End

    Method alpha:Void(value:Float) Property
        _alpha = value
        UpdateBounds()
    End

    Method alphaFloat:Float() Property
        Return _alpha / MAX
    End

    Method alphaFloat:Void(value:Float) Property
        _alpha = MAX * value
        UpdateBounds()
    End

    Private

    Method UpdateBounds:Void()
        _red = Clamp(_red, MIN, MAX)
        _green = Clamp(_green, MIN, MAX)
        _blue = Clamp(_blue, MIN, MAX)
        _alpha = Clamp(_alpha, MIN, MAX)
    End

    Method MojoSet:Void(color:Color)
        SetColor(color.red, color.green, color.blue)
        SetAlpha(color.alphaFloat)
    End
End

Strict

Private

Import bono
Import mojo.graphics

Public

Class Color
    Private

    Field oldColor:Color
    Field _red:Float
    Field _green:Float
    Field _blue:Float
    Field _alpha:Float

    Public

    Const MIN:Float = 0.0
    Const MAX:Float = 255.0

    Method New(hex:String)
        FromHex(hex)
    End

    Method New(red:Float=MAX, green:Float=MAX, blue:Float=MAX, alpha:Float=MAX)
        _red = red
        _green = green
        _blue = blue
        _alpha = alpha
        UpdateBounds()
    End

    Method Reset:Void()
        _red = MAX
        _green = MAX
        _blue = MAX
        _alpha = MAX
    End

    Method Randomize:Void()
        _red = MAX * Rnd()
        _green = MAX * Rnd()
        _blue = MAX * Rnd()
        _alpha = MAX * Rnd()
    End

    Method Activate:Void()
        If Not oldColor Then oldColor = New Color(MIN, MIN, MIN, MIN)

        Local colorStack:Float[] = GetColor()
        oldColor.red = colorStack[0]
        oldColor.green = colorStack[1]
        oldColor.blue = colorStack[2]
        oldColor.alpha = GetAlpha()

        MojoSet(Self)
    End

    Method Deactivate:Void()
        If Not oldColor Then Return
        MojoSet(oldColor)
        oldColor = Null
    End

    Method Copy:Color()
        Return New Color(_red, _green, _blue, _alpha)
    End

    Method Set:Void(newColor:Color)
        red = newColor.red
        green = newColor.green
        blue = newColor.blue
        alpha = newColor.alpha
    End

    Method FromHex:Void(hex:String)
        If hex.StartsWith("#") Then hex = hex[1..]
        Local value:Int = MathHelper.HexToInt(hex)

        _red = value Shr 16 & $0000ff
        _green = value Shr 8 & $0000ff
        _blue = value & $0000ff
        _alpha = MAX
    End

    Method ToHex:String()
        Return "#" +
            MathHelper.IntToHex(_red) +
            MathHelper.IntToHex(_green) +
            MathHelper.IntToHex(_blue)
    End

    Method Equals:Bool(color:Color)
        If Not (color.red = _red) Then Return False
        If Not (color.green = _green) Then Return False
        If Not (color.blue = _blue) Then Return False
        If Not (color.alpha = _alpha) Then Return False
        Return True
    End

    Method ToString:String()
        Return "(Red: " + _red + " Green: " + _green + " Blue: " + _blue + " Alpha: " + alphaFloat + ")"
    End

    Method red:Float() Property
        Return _red
    End

    Method red:Void(value:Float) Property
        _red = value
        UpdateBounds()
    End

    Method redFloat:Float() Property
        Return _red / MAX
    End

    Method redFloat:Void(value:Float) Property
        _red = MAX * value
        UpdateBounds()
    End

    Method green:Float() Property
        Return _green
    End

    Method green:Void(value:Float) Property
        _green = value
        UpdateBounds()
    End

    Method greenFloat:Float() Property
        Return _green / MAX
    End

    Method greenFloat:Void(value:Float) Property
        _green = MAX * value
        UpdateBounds()
    End

    Method blue:Float() Property
        Return _blue
    End

    Method blue:Void(value:Float) Property
        _blue = value
        UpdateBounds()
    End

    Method blueFloat:Float() Property
        Return _blue / MAX
    End

    Method blueFloat:Void(value:Float) Property
        _blue = MAX * value
        UpdateBounds()
    End

    Method alpha:Float() Property
        Return _alpha
    End

    Method alpha:Void(value:Float) Property
        _alpha = value
        UpdateBounds()
    End

    Method alphaFloat:Float() Property
        Return _alpha / MAX
    End

    Method alphaFloat:Void(value:Float) Property
        _alpha = MAX * value
        UpdateBounds()
    End

    Private

    Method UpdateBounds:Void()
        _red = Clamp(_red, MIN, MAX)
        _green = Clamp(_green, MIN, MAX)
        _blue = Clamp(_blue, MIN, MAX)
        _alpha = Clamp(_alpha, MIN, MAX)
    End

    Method MojoSet:Void(color:Color)
        SetColor(color.red, color.green, color.blue)
        SetAlpha(color.alphaFloat)
    End
End


Renamed GlobalPool.Obtain to Allocate to be in line with DiddyPool.

#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

Strict
Private
Import diddy.containers

Public
Class GlobalPool<T>
Private
	Global objects:Stack<T> = New Stack<T>

Public
	Function Allocate:T()
		If Not objects.IsEmpty() Then Return objects.Pop()
		Return New T
	End

	Function Free:Void(obj:T)
		If IPoolable(obj) Then IPoolable(obj).Reset()
		objects.Push(obj)
	End
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

Strict
Private
Import diddy.containers

Public
Class GlobalPool<T>
Private
	Global objects:Stack<T> = New Stack<T>

Public
	Function Obtain:T()
		If Not objects.IsEmpty() Then Return objects.Pop()
		Return New T
	End

	Function Free:Void(obj:T)
		If IPoolable(obj) Then IPoolable(obj).Reset()
		objects.Push(obj)
	End
End