First revision of a SAX-like XML parser.

#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 brl.stream

Public
Interface IContentHandler
	Method StartDocument:Void()
	Method EndDocument:Void()
	Method StartElement:Void(name:String, attrs:StringMap<String>)
	Method EndElement:Void(name:String)
	Method Text:Void(text:String)
End

Class SAXException Extends Throwable
Private
	Field message:String
	Field line:Int
	Field column:Int
Public
	Method New(message:String, line:Int, column:Int)
		Self.message = message
		Self.line = line
		Self.column = column
	End

	Method Message:String() Property; Return message; End
	Method Line:Int() Property; Return line; End
	Method Column:Int() Property; Return column; End

	Method ToString:String()
		Return message + " near line " + line + ", column " + column
	End
End

' based very very loosely on QDParser by Steven R. Brandt
' http://www.javaworld.com/article/2077493/mobile-java/java-tip-128--create-a-quick-and-dirty-xml-parser.html
Class SAXParser
Private
	Function PopMode:Int(st:IntStack)
		If Not st.IsEmpty() Then
			Return st.Pop()
		Else
			Return MODE_PRE
		End
	End

	Const MODE_TEXT% = 1
	Const MODE_ENTITY% = 2
	Const MODE_OPEN_TAG% = 3
	Const MODE_CLOSE_TAG% = 4
	Const MODE_START_TAG% = 5
	Const MODE_ATTRIBUTE_LVALUE% = 6
	Const MODE_ATTRIBUTE_EQUAL% = 7
	Const MODE_ATTRIBUTE_RVALUE% = 8
	Const MODE_QUOTE% = 9
	Const MODE_IN_TAG% = 10
	Const MODE_SINGLE_TAG% = 11
	Const MODE_COMMENT% = 12
	Const MODE_DONE% = 13
	Const MODE_DOCTYPE% = 14
	Const MODE_PRE% = 15
	Const MODE_CDATA% = 16

	Function ParseImpl:Void(handler:IContentHandler, sourceStream:Stream, sourceString:String)
		' prepare
		Local depth:Int = 0, mode:Int = MODE_PRE, c:Int = 0, quotec:Int = "~q"[0]
		Local tagName:String = "", lvalue:String = "", rvalue:String = ""
		Local attrs:StringMap<String> = Null
		Local st := New IntStack
		Local line:Int=1, col:Int=0
		Local eol:Bool = False, usingStream:Bool = (sourceStream <> Null)
		Local position:Int = 0
		Local buffer:DataBuffer
		Local sb := New StringBuffer, etag := New StringBuffer

		If usingStream Then buffer = New DataBuffer(100)

		' start event
		handler.StartDocument()

		' loop through document
		Repeat
			' get the next character
			If usingStream Then
				' TODO: check end of stream
				sourceStream.ReadAll(buffer, position, 1)
				c = buffer.PeekInt(position)
			Else
				' die if we've reached the end
				If position >= sourceString.Length() Then Exit
				c = sourceString[position]
			End

			' increment to the next character
			position += 1

			' some magic to handle EOL types
			If c = "~n"[0] And eol Then
				eol = False
				Continue
			ElseIf eol Then
				eol = False
			ElseIf c = "~n"[0] Then
				line += 1
				col = 0
			ElseIf c = "~r"[0] Then
				eol = True
				c = "~n"[0]
				line += 1
				col = 0
			Else
				col += 1
			End

			' if we're done, end
			If mode = MODE_DONE Then
				handler.EndDocument()
				Return
			End

			' between tags, collecting text
			If mode = MODE_TEXT Then
				If c = "<"[0] Then
					st.Push(mode)
					mode = MODE_START_TAG
					If sb.charCount > 0 Then
						Local txt:String = sb.GetString().Trim()
						If txt Then handler.Text(txt)
					End
				ElseIf c = "&"[0] Then
					st.Push(mode)
					mode = MODE_ENTITY
					etag.charCount = 0
				ElseIf sb.charCount > 0 Or Not IsWhitespace(c) Then
					sb.Append(c)
				End
			' processing closing tag
			ElseIf mode = MODE_CLOSE_TAG Then
				If c = ">"[0] Then
					mode = PopMode(st)
					tagName = sb.GetString()
					depth -= 1
					If depth = 0 Then mode = MODE_DONE
					handler.EndElement(tagName)
				Else
					sb.Append(c)
				End
			' processing CDATA
			ElseIf mode = MODE_CDATA Then
				If c = ">"[0] And sb.EndsWith("]]") Then
					sb.charCount -= 2
					handler.Text(sb.GetString())
				Else
					sb.Append(c)
				End
			' processing comment
			ElseIf mode = MODE_COMMENT Then
				If c = ">"[0] And sb.EndsWith("--") Then
					sb.charCount = 0
					mode = PopMode(st)
				Else
					sb.Append(c)
				End
			' outside root
			ElseIf mode = MODE_PRE Then
				If c = "<"[0] Then
					mode = MODE_TEXT
					st.Push(mode)
					mode = MODE_START_TAG
				End
			' <?...?> or <!DOCTYPE...>
			ElseIf mode = MODE_DOCTYPE Then
				If c = ">"[0] Then
					mode = PopMode(st)
					If mode = MODE_TEXT Then mode = MODE_PRE
				End
			' found <
			ElseIf mode = MODE_START_TAG Then
				mode = PopMode(st)
				If c = "/"[0] Then
					st.Push(mode)
					mode = MODE_CLOSE_TAG
				ElseIf c = "?"[0] Then
					mode = MODE_DOCTYPE
				Else
					st.Push(mode)
					mode = MODE_OPEN_TAG
					tagName = ""
					attrs = Null
					sb.Append(c)
				End
			' entity
			ElseIf mode = MODE_ENTITY Then
				If c = ";"[0] Then
					mode = PopMode(st)
					Local cent:String = etag.GetString()
					If cent = "lt" Then
						sb.Append("<"[0])
					ElseIf cent = "gt" Then
						sb.Append(">"[0])
					ElseIf cent = "amp" Then
						sb.Append("&"[0])
					ElseIf cent = "quot" Then
						sb.Append("~q"[0])
					ElseIf cent = "apos" Then
						sb.Append("'"[0])
					ElseIf cent[0] = "#"[0] Then
						' TODO
					Else
						Exc("Unknown entity: &"+cent+";",line,col)
					End
				Else
					etag.Append(c)
				End
			' self closing tag
			ElseIf mode = MODE_SINGLE_TAG Then
				If tagName = "" And sb.charCount > 0 Then tagName = sb.GetString()
				If c <> ">"[0] Then Exc("Expected > for tag: <"+tagName+"/>",line,col)
				handler.StartElement(tagName, attrs)
				handler.EndElement(tagName)
				If depth = 0 Then
					handler.EndDocument()
					Return
				End
				attrs = Null
				tagName = ""
				mode = PopMode(st)
			' processing inside tag
			ElseIf mode = MODE_OPEN_TAG Then
				If c = ">"[0] Then
					If tagName = "" And sb.charCount > 0 Then tagName = sb.GetString()
					depth += 1
					handler.StartElement(tagName, attrs)
					tagName = ""
					attrs = Null
					mode = PopMode(st)
				ElseIf c = "/"[0] Then
					mode = MODE_SINGLE_TAG
				ElseIf c = "-"[0] And sb.Equals("!-") Then
					mode = MODE_COMMENT
				ElseIf c = "["[0] And sb.Equals("![CDATA") Then
					mode = MODE_CDATA
					sb.charCount = 0
				ElseIf c = "E"[0] And sb.Equals("!DOCTYP") Then
					sb.charCount = 0
					mode = MODE_DOCTYPE
				ElseIf IsWhitespace(c) Then
					tagName = sb.GetString()
					mode = MODE_IN_TAG
				Else
					sb.Append(c)
				End
			' right hand side of attribute value
			ElseIf mode = MODE_QUOTE Then
				If c = quotec Then
					rvalue = sb.GetString()
					If Not attrs Then attrs = New StringMap<String>
					attrs.Set(lvalue, rvalue)
					mode = MODE_IN_TAG
				ElseIf IsWhitespace(c) Then
					sb.Append(" "[0])
				ElseIf c = "&"[0] Then
					st.Push(mode)
					mode = MODE_ENTITY
					etag.charCount = 0
				Else
					sb.Append(c)
				End
			' rvalue
			ElseIf mode = MODE_ATTRIBUTE_RVALUE Then
				If c = "~q"[0] Or c = "'"[0] Then
					quotec = c
					mode = MODE_QUOTE
				ElseIf Not IsWhitespace(c) Then
					Exc("Error in attribute processing",line,col)
				End
			' lvalue
			ElseIf mode = MODE_ATTRIBUTE_LVALUE Then
				If IsWhitespace(c) Then
					lvalue = sb.GetString()
					mode = MODE_ATTRIBUTE_EQUAL
				ElseIf c = "="[0] Then
					lvalue = sb.GetString()
					mode = MODE_ATTRIBUTE_RVALUE
				Else
					sb.Append(c)
				End
			' equal
			ElseIf mode = MODE_ATTRIBUTE_EQUAL Then
				If c = "="[0] Then
					mode = MODE_ATTRIBUTE_RVALUE
				ElseIf Not IsWhitespace(c) Then
					Exc("Error in attribute processing",line,col)
				End
			' in tag
			ElseIf mode = MODE_IN_TAG Then
				If c = ">"[0] Then
					mode = PopMode(st)
					handler.StartElement(tagName, attrs)
					depth += 1
					tagName = ""
				ElseIf c = "/"[0] Then
					mode = MODE_SINGLE_TAG
				ElseIf Not IsWhitespace(c) Then
					mode = MODE_ATTRIBUTE_LVALUE
					sb.Append(c)
				End
			End
		Forever
		If mode = MODE_DONE Then
			handler.EndDocument()
		Else
			Exc("Missing end tag",line,col)
		End
	End

	Function Exc:Void(s:String, line:Int, col:Int)
		Throw New SAXException(s, line, col)
	End

	Function IsWhitespace:Bool(c:Int)
		Return c = " "[0] Or c = "~r"[0] Or c = "~n"[0] Or c = "~t"[0]
	End

Public
	Function Parse:Void(handler:IContentHandler, sourceStream:Stream)
		ParseImpl(handler, sourceStream, "")
	End

	Function Parse:Void(handler:IContentHandler, sourceString:String)
		ParseImpl(handler, Null, sourceString)
	End
End

Private

Class StringBuffer
	Field charArray:Int[]
	Field charCount:Int = 0

	Method Append:Void(c:Int)
		If charCount >= charArray.Length Then charArray = charArray.Resize(charCount*2)
		charArray[charCount] = c
		charCount += 1
	End

	Method GetString:String(reset:Bool=True)
		If charCount = 0 Then Return ""
		Local rv := String.FromChars(charArray[..charCount])
		If reset Then charCount = 0
		Return rv
	End

	Method EndsWith:Bool(str:String)
		Local len:Int = str.Length()
		If charCount = 0 Or len > charCount Then Return False
		For Local i:Int = 0 Until len
			If charArray[charCount-len+i] <> str[i] Then Return False
		Next
		Return True
	End

	Method Equals:Bool(str:String)
		If str.Length() <> charCount Then Return False
		For Local i:Int = 0 Until charCount
			If str[i] <> charArray[i] Then Return False
		Next
		Return True
	End
End

error: pathspec 'src/diddy/sax.monkey' did not match any file(s) known to git


Added getPixel example.

Added getPixel example.

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

Strict

Import diddy

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

Global gameScreen:GameScreen

Class MyGame Extends DiddyApp

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

End

Class GameScreen Extends Screen
	Const max% = 100
	Field r%[max]
	Field g%[max]
	Field b%[max]
	Field x%[max]
	Field y%[max]
	Field w%[max]
	Field h%[max]

	Field pixel:Int[4]

	Method New()
		name = "Game"
	End

	Method Start:Void()
		game.screenFade.Start(50, False)
		For Local i%=0 To max-1
			r[i] = Rnd(0, 255)
			g[i] = Rnd(0, 255)
			b[i] = Rnd(0, 255)

			x[i] = Rnd(SCREEN_WIDTH)
			y[i] = Rnd(SCREEN_HEIGHT)
			w[i] = Rnd(100)
			h[i] = Rnd(100)
		End
		pixel[0] = 0
		pixel[1] = 0
		pixel[2] = 0
		pixel[3] = 1
	End

	Method Render:Void()
		Cls(1,2,3)
		For Local i%=0 To max-1
			SetColor(r[i],g[i],b[i])
			DrawRect x[i], y[i], w[i], h[i]
		Next

		SetColor pixel[0], pixel[1], pixel[2]
		DrawOval 0, 0, 50, 50
		SetColor 255,255,255

		DrawText "Red   = " + pixel[0], 0, 60
		DrawText "Green = " + pixel[1], 0, 70
		DrawText "Blue  = " + pixel[2], 0, 80

		If MouseDown()
			pixel = GetPixel(game.mouseX, game.mouseY)
		'	Print "Red   = " + pixel[0]
		'	Print "Green = " + pixel[1]
		'	Print "Blue  = " + pixel[2]
		End
	End

	Method Update:Void()
		If KeyHit(KEY_ESCAPE)
			game.screenFade.Start(50, True)
			game.nextScreen = game.exitScreen
		End
	End

End

error: pathspec 'examples/Functions/getPixel.monkey' did not match any file(s) known to git


First revision of transformation module.

Strict

Public
Import exception
Import functions
Import collections

Private
Import mojo

Public
Const TRANSFORM_NONE:Int = 0
Const TRANSFORM_POSITION:Int = 1
Const TRANSFORM_ALPHA:Int = 2
Const TRANSFORM_SCALE:Int = 3
Const TRANSFORM_ROTATION:Int = 4
Const TRANSFORM_COLOR:Int = 5
Const TRANSFORM_COUNT:Int = 6

Const EASE_NONE:Int = 0
Const EASE_IN_DOUBLE:Int = 1
Const EASE_IN:Int = 2
Const EASE_IN_HALF:Int = 3
Const EASE_OUT:Int = 4
Const EASE_OUT_HALF:Int = 5
Const EASE_OUT_DOUBLE:Int = 6
Const EASE_IN_OUT:Int = 7

Const COLORSPACE_RGB:Int = 0
Const COLORSPACE_HSL:Int = 1

Class TransformationGroup
Private
	Global hslArray:Float[] = New Float[3]
	Global rgbArray:Int[] = New Int[3]
	Field transformations:ArrayList<Transformation>[] = New ArrayList<Transformation>[TRANSFORM_COUNT]
	Field currentTransform:Transformation[] = New Transformation[TRANSFORM_COUNT]
	Field lastTime:Int = 0

	Field defaultX:Float = 0
	Field defaultY:Float = 0
	Field defaultScaleX:Float = 1
	Field defaultScaleY:Float = 1
	Field defaultRotation:Float = 0
	Field defaultAlpha:Float = 1
	Field defaultRed:Float = 255
	Field defaultGreen:Float = 255
	Field defaultBlue:Float = 255
	Field defaultHue:Float = 0
	Field defaultSaturation:Float = 1
	Field defaultLuminance:Float = 0.5

Public
	Method Add:Void(type:Int, tr:Transformation)
		If type < 0 Or type >= TRANSFORM_COUNT Then Throw New IllegalArgumentException("Invalid transformation type: "+type)
		If Not transformations[type] Then transformations[type] = New ArrayList<Transformation>
		transformations[type].Add(tr)
		transformations[type].Sort()
		tr.Update(lastTime)
	End

	Method Remove:Void(type:Int, tr:Transformation)
		If type < 0 Or type >= TRANSFORM_COUNT Then Throw New IllegalArgumentException("Invalid transformation type: "+type)
		If Not transformations[type] Then Return
		transformations[type].Remove(tr)
	End

	Method Clear:Void(type:Int)
		If type < 0 Or type >= TRANSFORM_COUNT Then Throw New IllegalArgumentException("Invalid transformation type: "+type)
		If Not transformations[type] Then Return
		transformations[type].Clear()
	End

	Method New(x#=0, y#=0, scaleX#=1, scaleY#=1, rotation#=0, alpha#=1, red#=255, green#=255, blue#=255, hue#=0.0, saturation#=1.0, luminance#=0.5, colorSpace%=COLORSPACE_RGB)
		defaultX = x
		defaultY = y
		defaultScaleX = scaleX
		defaultScaleY = scaleY
		defaultRotation = rotation
		defaultAlpha = alpha
		If colorSpace = COLORSPACE_RGB Then
			RGBtoHSL(red, green, blue, hslArray)
			hue = hslArray[0]
			saturation = hslArray[1]
			luminance = hslArray[2]
		ElseIf colorSpace = COLORSPACE_HSL Then
			HSLtoRGB(hue, saturation, luminance, rgbArray)
			red = rgbArray[0]
			green = rgbArray[1]
			blue = rgbArray[2]
		End
		defaultRed = red
		defaultGreen = green
		defaultBlue = blue
		defaultHue = hue
		defaultSaturation = saturation
		defaultLuminance = luminance
	End

	Method Update:Void(currentTime:Int)
		' store time for calls to Add
		lastTime = currentTime

		' clear out current transforms
		For Local i:Int = 0 Until currentTransform.Length
			currentTransform[i] = Null
		Next

		For Local i:Int = 0 Until transformations.Length
			If transformations[i] Then
				' these should be sorted
				For Local j:Int = 0 Until transformations[i].Size
					Local tr:Transformation = transformations[i].Get(j)
					tr.Update(currentTime)
					If currentTime >= tr.startTime Or Not currentTransform[i] And currentTime >= tr.firstStartTime Then
						currentTransform[i] = tr
					End
				Next
			End
		Next
	End

	Method GetCurrentTransformation:Transformation(type:Int)
		If type < 0 Or type >= TRANSFORM_COUNT Then Throw New IllegalArgumentException("Invalid transformation type: "+type)
		Return currentTransform[type]
	End

	' convenience methods

	Method CurrentScaleX:Float() Property
		Local tr:TransformationVector = TransformationVector(currentTransform[TRANSFORM_SCALE])
		If Not tr Then Return defaultScaleX
		Return tr.CurrentX
	End

	Method CurrentScaleY:Float() Property
		Local tr:TransformationVector = TransformationVector(currentTransform[TRANSFORM_SCALE])
		If Not tr Then Return defaultScaleY
		Return tr.CurrentY
	End

	Method CurrentAlpha:Float() Property
		Local tr:TransformationValue = TransformationValue(currentTransform[TRANSFORM_ALPHA])
		If Not tr Then Return defaultAlpha
		Return tr.CurrentValue
	End

	Method CurrentRed:Float() Property
		Local tr:TransformationColor = TransformationColor(currentTransform[TRANSFORM_COLOR])
		If Not tr Then Return defaultRed
		Return tr.CurrentRed
	End

	Method CurrentGreen:Float() Property
		Local tr:TransformationColor = TransformationColor(currentTransform[TRANSFORM_COLOR])
		If Not tr Then Return defaultGreen
		Return tr.CurrentGreen
	End

	Method CurrentBlue:Float() Property
		Local tr:TransformationColor = TransformationColor(currentTransform[TRANSFORM_COLOR])
		If Not tr Then Return defaultBlue
		Return tr.CurrentBlue
	End

	Method CurrentHue:Float() Property
		Local tr:TransformationColor = TransformationColor(currentTransform[TRANSFORM_COLOR])
		If Not tr Then Return defaultHue
		Return tr.CurrentHue
	End

	Method CurrentSaturation:Float() Property
		Local tr:TransformationColor = TransformationColor(currentTransform[TRANSFORM_COLOR])
		If Not tr Then Return defaultSaturation
		Return tr.CurrentSaturation
	End

	Method CurrentLuminance:Float() Property
		Local tr:TransformationColor = TransformationColor(currentTransform[TRANSFORM_COLOR])
		If Not tr Then Return defaultLuminance
		Return tr.CurrentLuminance
	End

	Method CurrentX:Float() Property
		Local tr:TransformationVector = TransformationVector(currentTransform[TRANSFORM_POSITION])
		If Not tr Then Return defaultX
		Return tr.CurrentX
	End

	Method CurrentY:Float() Property
		Local tr:TransformationVector = TransformationVector(currentTransform[TRANSFORM_POSITION])
		If Not tr Then Return defaultY
		Return tr.CurrentY
	End

	Method CurrentRotation:Float() Property
		Local tr:TransformationValue = TransformationValue(currentTransform[TRANSFORM_ROTATION])
		If Not tr Then Return defaultRotation
		Return tr.CurrentValue
	End

	Method Apply:Void()
		SetColor(CurrentRed, CurrentGreen, CurrentBlue)
		Translate(CurrentX, CurrentY)
		Scale(CurrentScaleX, CurrentScaleY)
		Rotate(CurrentRotation)
		SetAlpha(CurrentAlpha)
	End
End

Class Transformation Implements IComparable Abstract
Private
	Field loop:Bool
	Field loopDelay:Int
	Field easeType:Int
	Field firstStartTime:Int
	Field firstEndTime:Int
	Field startTime:Int
	Field endTime:Int
	Field currentTime:Int
	Field started:Bool
	Field finished:Bool
	Field needsRecalc:Bool = True

Public
	Method StartTime:Int() Property Return startTime End
	Method StartTime:Void(startTime:Int) Property Self.startTime = startTime; needsRecalc = True End
	Method EndTime:Int() Property Return endTime End
	Method EndTime:Void(endTime:Int) Property Self.endTime = endTime; needsRecalc = True End
	Method EaseType:Int() Property Return easeType End
	Method EaseType:Void(easeType:Int) Property Self.easeType = easeType End
	Method Loop:Bool() Property Return loop End
	Method Loop:Void(loop:Bool) Property Self.loop = loop End
	Method LoopDelay:Int() Property Return loopDelay End
	Method LoopDelay:Void(loopDelay:Int) Property Self.loopDelay = loopDelay End
	Method Started:Bool() Property Return started End
	Method Finished:Bool() Property Return finished End
	Method Duration:Int() Property Return endTime - startTime End

	Method New(startTime:Int, endTime:Int, easeType:Int=EASE_NONE, loop:Bool=False, loopDelay:Int=0)
		Self.startTime = startTime
		Self.endTime = endTime
		Self.firstStartTime = startTime
		Self.firstEndTime = endTime
		Self.easeType = easeType
		Self.loop = loop
		Self.loopDelay = loopDelay
	End

	Method Update:Void(currentTime:Int)
		Self.currentTime = currentTime
		If loop And endTime < currentTime Then
			Local duration:Int = endTime - startTime + loopDelay
			Local remainder:Int = currentTime - endTime
			startTime += (remainder / duration + 1) * duration
			endTime += (remainder / duration + 1) * duration
		End
		started = currentTime >= startTime
		finished = started And currentTime >= endTime And Not loop
		Recalc(True)
	End

	Method Compare:Int(other:Object)
		If Not Transformation(other) Then Return 1
		If other = Self Then Return 0
		Local o:Transformation = Transformation(other)
		If startTime > o.startTime Then Return 1
		If startTime < o.startTime Then Return -1
		If endTime > o.endTime Then Return 1
		If endTime < o.endTime Then Return -1
		If easeType > o.easeType Then Return 1
		If easeType < o.easeType Then Return -1
		If loop And Not o.loop Then Return 1
		If Not loop And o.loop Then Return -1
		If loopDelay > o.loopDelay Then Return 1
		If loopDelay < o.loopDelay Then Return -1
		If started And Not o.started Then Return 1
		If Not started And o.started Then Return -1
		If finished And Not o.finished Then Return 1
		If Not finished And o.finished Then Return -1
		Return 0
	End

	Method Equals:Bool(other:Object)
		Return Compare(other) = 0
	End

Private
	Method Recalc:Void(force:Bool=False)
		If Not needsRecalc And Not force Then Return
		needsRecalc = False
		DoRecalc()
	End

	Method DoRecalc:Void() Abstract

	Method Calculate:Float(startValue:Float, endValue:Float)
		' if we've never started, return the start value
		If currentTime <= firstStartTime Then Return startValue

		' if we're at the end or between loops, return the end value
		If currentTime >= endTime Or currentTime < startTime Or startTime = endTime Then Return endValue

		' how far through are we?
		Local progress:Float = Float(currentTime - startTime) / Float(endTime - startTime)

		Select easeType
			Case EASE_IN_DOUBLE
				Return Lerp(endValue, startValue, (1-progress)*(1-progress)*(1-progress)*(1-progress))
			Case EASE_IN
				Return Lerp(endValue, startValue, (1-progress)*(1-progress))
			Case EASE_IN_HALF
				Return Lerp(endValue, startValue, Pow(1-progress, 1.5))
			Case EASE_OUT
				Return Lerp(startValue, endValue, progress * progress)
			Case EASE_OUT_HALF
				Return Lerp(startValue, endValue, Pow(progress, 1.5))
			Case EASE_OUT_DOUBLE
				Return Lerp(startValue, endValue, progress*progress*progress*progress)
			Case EASE_IN_OUT
				Return startValue + (-2*(progress*progress*progress) + 3*(progress*progress)) * (endValue - startValue)
			Default
				Return Lerp(startValue, endValue, progress);
		End
	End

	Method Lerp:Float(startValue:Float, endValue:Float, progress:Float)
		Return startValue + (endValue-startValue) * progress
	End
End

Class TransformationColor Extends Transformation
Private
	Global hslArray:Float[] = New Float[3]
	Global rgbArray:Int[] = New Int[3]
	Field startH:Float
	Field startS:Float
	Field startL:Float
	Field startR:Int
	Field startG:Int
	Field startB:Int
	Field endH:Float
	Field endS:Float
	Field endL:Float
	Field endR:Int
	Field endG:Int
	Field endB:Int
	Field currentH:Float
	Field currentS:Float
	Field currentL:Float
	Field currentR:Int
	Field currentG:Int
	Field currentB:Int

Public
	Method StartRed:Int() Property Return startR End
	Method StartGreen:Int() Property Return startG End
	Method StartBlue:Int() Property Return startB End
	Method EndRed:Int() Property Return endR End
	Method EndGreen:Int() Property Return endG End
	Method EndBlue:Int() Property Return endB End
	Method StartHue:Int() Property Return startH End
	Method StartSaturation:Int() Property Return startS End
	Method StartLuminance:Int() Property Return startL End
	Method EndHue:Int() Property Return endH End
	Method EndSaturation:Int() Property Return endS End
	Method EndLuminance:Int() Property Return endL End
	Method CurrentRed:Int() Property Recalc(); Return currentR End
	Method CurrentGreen:Int() Property Recalc(); Return currentG End
	Method CurrentBlue:Int() Property Recalc(); Return currentB End
	Method CurrentHue:Int() Property Recalc(); Return currentH End
	Method CurrentSaturation:Int() Property Recalc(); Return currentS End
	Method CurrentLuminance:Int() Property Recalc(); Return currentL End

	Method New(start1:Float, start2:Float, start3:Float, end1:Float, end2:Float, end3:Float, startTime:Int, endTime:Int, easeType:Int=EASE_NONE, loop:Bool=False, loopDelay:Int=0, colorSpace:Int=COLORSPACE_RGB)
		Super.New(startTime, endTime, easeType, loop, loopDelay)
		If colorSpace = COLORSPACE_RGB Then
			SetStartRGB(Int(start1), Int(start2), Int(start3))
			SetEndRGB(Int(end1), Int(end2), Int(end3))
		ElseIf colorSpace = COLORSPACE_HSL Then
			SetStartHSL(start1, start2, start3)
			SetEndHSL(end1, end2, end3)
		Else
			Throw New IllegalArgumentException("Invalid colorspace: "+colorSpace)
		End
		needsRecalc = True
	End

	Method SetStartRGB:Void(startR:Int, startG:Int, startB:Int)
		Self.startR = Max(0,Min(255,startR))
		Self.startG = Max(0,Min(255,startG))
		Self.startB = Max(0,Min(255,startB))
		RecalcStartHSL()
		needsRecalc = True
	End

	Method SetEndRGB:Void(endR:Int, endG:Int, endB:Int)
		Self.endR = Max(0,Min(255,endR))
		Self.endG = Max(0,Min(255,endG))
		Self.endB = Max(0,Min(255,endB))
		RecalcEndHSL()
		needsRecalc = True
	End

	Method SetStartHSL:Void(startH:Float, startS:Float, startL:Float)
		Self.startH = Max(0.0,Min(1.0,startH))
		Self.startS = Max(0.0,Min(1.0,startS))
		Self.startL = Max(0.0,Min(1.0,startL))
		RecalcStartRGB()
		needsRecalc = True
	End

	Method SetEndHSL:Void(endH:Float, endS:Float, endL:Float)
		Self.endH = Max(0.0,Min(1.0,endH))
		Self.endS = Max(0.0,Min(1.0,endS))
		Self.endL = Max(0.0,Min(1.0,endL))
		RecalcEndRGB()
		needsRecalc = True
	End

Private
	Method RecalcStartRGB:Void()
		HSLtoRGB(startH, startS, startL, rgbArray)
		Self.startR = rgbArray[0]
		Self.startG = rgbArray[1]
		Self.startB = rgbArray[2]
	End

	Method RecalcEndRGB:Void()
		HSLtoRGB(endH, endS, endL, rgbArray)
		Self.endR = rgbArray[0]
		Self.endG = rgbArray[1]
		Self.endB = rgbArray[2]
	End

	Method RecalcStartHSL:Void()
		RGBtoHSL(startR, startG, startB, hslArray)
		Self.startH = hslArray[0]
		Self.startS = hslArray[1]
		Self.startL = hslArray[2]
	End

	Method RecalcEndHSL:Void()
		RGBtoHSL(endR, endG, endB, hslArray)
		Self.endH = hslArray[0]
		Self.endS = hslArray[1]
		Self.endL = hslArray[2]
	End

	Method DoRecalc:Void()
		currentH = Calculate(Self.startH, Self.endH)
		currentS = Calculate(Self.startS, Self.endS)
		currentL = Calculate(Self.startL, Self.endL)
		HSLtoRGB(currentH, currentS, currentL, rgbArray)
		currentR = rgbArray[0]
		currentG = rgbArray[1]
		currentB = rgbArray[2]
	End
End

Class TransformationValue Extends Transformation
Private
	Field startValue:Float
	Field endValue:Float
	Field currentValue:Float

Public
	Method CurrentValue:Float() Property Recalc(); Return currentValue End
	Method StartValue:Float() Property Return startValue End
	Method StartValue:Void(startValue:Float) Property Self.startValue = startValue; needsRecalc = True End
	Method EndValue:Float() Property Return endValue End
	Method EndValue:Void(endValue:Float) Property Self.endValue = endValue; needsRecalc = True End

	Method New(startValue:Float, endValue:Float, startTime:Int, endTime:Int, easeType:Int=EASE_NONE, loop:Bool=False, loopDelay:Int=0)
		Super.New(startTime, endTime, easeType, loop, loopDelay)
		Self.startValue = startValue
		Self.endValue = endValue
	End

Private
	Method DoRecalc:Void()
		currentValue = Calculate(startValue, endValue)
	End
End

Class TransformationVector Extends Transformation
Private
	Field startX:Float
	Field startY:Float
	Field endX:Float
	Field endY:Float
	Field currentX:Float
	Field currentY:Float

Public
	Method CurrentX:Float() Property Recalc(); Return currentX End
	Method CurrentY:Float() Property Recalc(); Return currentY End
	Method StartX:Float() Property Return startX End
	Method StartX:Void(startX:Float) Property Self.startX = startX; needsRecalc = True End
	Method StartY:Float() Property Return startY End
	Method StartY:Void(startY:Float) Property Self.startY = startY; needsRecalc = True End
	Method EndX:Float() Property Return endX End
	Method EndX:Void(endX:Float) Property Self.endX = endX; needsRecalc = True End
	Method EndY:Float() Property Return endY End
	Method EndY:Void(endY:Float) Property Self.endY = endY; needsRecalc = True End

	Method New(startX:Float, startY:Float, endX:Float, endY:Float, startTime:Int, endTime:Int, easeType:Int=EASE_NONE, loop:Bool=False, loopDelay:Int=0)
		Super.New(startTime, endTime, easeType, loop, loopDelay)
		Self.startX = startX
		Self.startY = startY
		Self.endX = endX
		Self.endY = endY
	End

Private
	Method DoRecalc:Void()
		currentX = Calculate(startX, endX)
		currentY = Calculate(startY, endY)
	End
End

error: pathspec 'src/diddy/transformation.monkey' did not match any file(s) known to git


Added Asteroids to MonkeyMax examples

Added Asteroids to MonkeyMax examples

Strict
Import mojo

Global game:MyGame

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

Const PDM_smlparticle%=0
Const PDM_medparticle%=1
Const PDM_bigparticle%=2
Const PDM_spark%=3

Const STATE_TITLE% = 0
Const STATE_GAME% = 1
Const STATE_NEXT_LEVEL% = 2
Const STATE_GAME_OVER% = 3

Global ASTEROIDS_NUM%
Global ASTEROIDS_SIZE%

Class MyGame Extends FrameworkApp
	Field player:Player
	Field cg%, cr%, cb%
	Field level% = 1
	Field score% = 0
	Field bestScore% = 0
	Field noOfStars% = 250
	' Current game state
	Global gameState:Int = STATE_TITLE

	Method OnCreate:Int()
		Super.OnCreate()
		createStars()
		reset()
		Return 0
	End Method

	Method setState:Void(state:Int)
		gameState = state
	End

	Method createStars:Void()
		For Local i% = 0 To noOfStars
			New Star(Rnd(0, SCREEN_WIDTH), Rnd(0, SCREEN_HEIGHT))
		Next
	End Method

	Method reset:Void()
		Bullet.list.Clear()
		Asteroid.list.Clear()
		Particle.list.Clear()
		Spark.list.Clear()
		cg = 0
		cr = 0
		cb = 0
		level = 1
		ASTEROIDS_NUM = 2
		ASTEROIDS_SIZE = 4
		score = 0
		player = New Player(SCREEN_WIDTH2, SCREEN_HEIGHT2)
		fillAsteroids(ASTEROIDS_NUM, ASTEROIDS_SIZE)
	End Method

	Method OnLoading:Int()
		Super.OnLoading()
		Return 0
	End Method

	Method OnUpdate:Int()
		Super.OnUpdate()

		Select gameState
			Case STATE_TITLE
				Asteroid.updateAll()
				If KeyHit(KEY_SPACE)
			   		setState(STATE_GAME)
				Endif
			Case STATE_GAME
				player.Update()
				Spark.updateAll
				Bullet.updateAll()
				Asteroid.updateAll()
				Particle.updateAll()
				checkCollisions()
				clscolor()
			Case STATE_NEXT_LEVEL
				Asteroid.updateAll()
				If KeyHit(KEY_SPACE)
			   		setState(STATE_GAME)
				Endif

			Case STATE_GAME_OVER
				Asteroid.updateAll()
				Particle.updateAll()
				If KeyHit(KEY_SPACE)
			   		setState(STATE_TITLE)
					reset()
				Endif
		End Select

		Return 0
	End Method

	Method clscolor:Void()
		If cr > 0
			cr-=2*dt.delta
		Else
			cr = 0
		Endif
	End Method

	Method OnRender:Int()
		Super.OnRender()

		Select gameState
			Case STATE_TITLE
				Cls 0, 0, 0
				Star.drawAll()
				Asteroid.drawAll()
				DrawText "ASTEROIDS - MONKEY STYLE!", SCREEN_WIDTH2, SCREEN_HEIGHT2, 0.5, 0.5
				DrawText "BEST SCORE: "+Self.bestScore, SCREEN_WIDTH2, SCREEN_HEIGHT2 + 30, 0.5, 0.5
				DrawText "PRESS <SPACE> TO PLAY", SCREEN_WIDTH2, SCREEN_HEIGHT2 + 60, 0.5, 0.5

			Case STATE_GAME
				Cls cr, cg, cb
				Star.drawAll()
				player.draw()
				Spark.drawAll()
				Bullet.drawAll()
				Asteroid.drawAll()
				Particle.drawAll()
				drawHUD()
			Case STATE_NEXT_LEVEL
				Cls cr, cg, cb
				Star.drawAll()

				SetAlpha 0.7
				SetColor 255,0,0
				DrawOval player.x-15, player.y-15, 30, 30

				SetAlpha 0.6
				SetColor 0,55,55
				DrawOval player.x-13, player.y-13, 27, 27

				player.draw()
				Spark.drawAll()
				Bullet.drawAll()
				Asteroid.drawAll()
				Particle.drawAll()
				DrawText "NEXT LEVEL!", SCREEN_WIDTH2, SCREEN_HEIGHT2-60, 0.5, 0.5
				DrawText "PRESS <SPACE> TO PLAY", SCREEN_WIDTH2, SCREEN_HEIGHT2 + 60, 0.5, 0.5
				drawHUD()
			Case STATE_GAME_OVER
				Cls 0, 0, 0
				Star.drawAll()
				Asteroid.drawAll()
				Particle.drawAll()
				DrawText "GAME OVER!", SCREEN_WIDTH2, SCREEN_HEIGHT2, 0.5, 0.5
				DrawText "SCORE: "+score, SCREEN_WIDTH2, SCREEN_HEIGHT2 + 30, 0.5, 0.5
				DrawText "BEST SCORE: "+Self.bestScore, SCREEN_WIDTH2, SCREEN_HEIGHT2 + 60, 0.5, 0.5
				DrawText "PRESS <SPACE> TO RETURN TO THE TITLE SCREEN", SCREEN_WIDTH2, SCREEN_HEIGHT2 + 90, 0.5, 0.5
		End Select

		Return 0
	End Method

	Method checkCollisions:Void()
		For Local a:Asteroid = Eachin Asteroid.list

			If dist(player.x, player.y, a.x, a.y) <= a.avgrad
				If cr = 0 Then cr = Rnd(100, 155)
				player.shield-=2
			Endif

			For Local b:Bullet = Eachin Bullet.list
				If a <> Null Then
					If dist(b.x, b.y, a.x, a.y) <= a.avgrad
						a.life = a.life - 1
						b.life = 0
						For Local t%=1 To 4
							New Particle(a.x, a.y, Rnd(-8,8), Rnd(-8,8), 0.95, 30, PDM_spark, 255, 192, 64, 16)
						Next
						For Local t%=1 To 4
							New Particle(a.x, a.y, Rnd(-4,4), Rnd(-4,4), 0.95, 60, PDM_smlparticle, 160, 160, 160, 0)
						Next
					Endif
					If a.life <= 0

						For Local t%=1 To 4
							New Particle(a.x,a.y,Rnd(-10,10),Rnd(-10,10),0.95,30,PDM_spark,255,192,64,64)
						Next
						For Local t%=1 To 3
							New Particle(a.x,a.y,Rnd(-6,6),Rnd(-6,6),0.95,30,PDM_medparticle,255,192,64,128)
						Next
						For Local t%=1 To 3
							New Particle(a.x,a.y,Rnd(-8,8),Rnd(-8,8),0.99,60,PDM_smlparticle,160,160,160,0)
						Next
						For Local t%=1 To 2
							New Particle(a.x,a.y,Rnd(-6,6),Rnd(-6,6),0.99,60,PDM_medparticle,160,160,160,0)
						Next
						For Local t%=1 To 2
							New Particle(a.x,a.y,Rnd(-4,4),Rnd(-4,4),0.99,60,PDM_bigparticle,160,160,160,0)
						Next

						If a.size > 2
							For Local t% = 1 To 2
								New Asteroid(a.x, a.y, Rnd(-5,5), Rnd(-5,5), a.size-1)
							Next
						Endif
						Asteroid.list.Remove(a)
						a = Null
						score+=5
					Endif
				Endif
			Next
		Next
		If Asteroid.list.Count() = 0
			level+=1
			Asteroid.list.Clear()
			ASTEROIDS_SIZE+=1
			ASTEROIDS_NUM+=1
			fillAsteroids(ASTEROIDS_NUM, ASTEROIDS_SIZE)
			Bullet.list.Clear()
			Spark.list.Clear()
			Particle.list.Clear()
			cg = 0
			cr = 0
			cb = 0
			player.x = SCREEN_WIDTH2
			player.y = SCREEN_HEIGHT2
			player.rotation = 0
			player.acc = 0
			player.xa  =0
			player.xv = 0
			player.drag = 0
			player.ya = 0
			player.yv  =0
			setState(STATE_NEXT_LEVEL)
		Endif
	End Method

	Method drawHUD:Void()
		DrawText "LEVEL: "+level, 0, 0
		DrawText "SCORE: "+score, SCREEN_WIDTH, 0, 1, 0

		FPSCounter.draw(SCREEN_WIDTH,SCREEN_HEIGHT, 1, 1)
	End Method

	Method fillAsteroids:Void(num%, size%)
		Local tx#
		Local ty#
		For Local t% = 1 To num
			Repeat
				tx=Rnd(640)
				ty=Rnd(480)
			Until ( tx<280 Or tx>360 ) And ( ty<200 Or ty>280 )
			New Asteroid(tx, ty, Rnd(-3,3), Rnd(-3,3), size+Rnd(1))
		Next
	End Method
End Class

Class Star
	Global list:List<Star> = New List<Star>
	Field red%, green%, blue%, alpha#
	Field x#, y#
	Method New(x#,y#)
		Self.x=x
		Self.y=y
		Local col:=Rnd(255)
		Self.red = col
		Self.green = col
		Self.blue = col
		list.AddLast Self
	End Method

'	Function updateAll:Void()
'		If not list Return
'		For local b:Star = Eachin list
'			b.update()
'		Next
'	End Function

	Function drawAll:Void()
		If Not list Return
		For Local b:Star = Eachin list
			b.draw()
		Next
	End Function

'	Method update:Void()
'
'	End Method

	Method draw:Void()
		SetColor Self.red, Self.green, Self.blue
		DrawRect x, y, 1, 1
		SetColor 1, 1, 1
	End Method
End Class

Class Particle Extends Sprite
	Global list:List<Particle> = New List<Particle>

	Field xv#,yv#
	Field vm#
	Field life#,mlife#
	Field drawmode%
	Field cr%,cg%,cb%
	Field cflash%

	Method New(x#,y#,xv#,yv#,vm#,life#,drawmode%,cr%,cg%,cb%,cflash%)
		Self.x=x
		Self.y=y
		Self.xv=xv
		Self.yv=yv
		Self.vm=vm
		Self.life=life
		Self.mlife=life
		Self.drawmode=drawmode
		Self.cr=cr
		Self.cg=cg
		Self.cb=cb
		Self.cflash=cflash

		list.AddLast Self
	End Method

	Function updateAll:Void()
		If Not list Return
		For Local b:Particle = Eachin list
			b.update()
		Next
	End Function

	Function drawAll:Void()
		If Not list Return
		For Local b:Particle = Eachin list
			b.draw()
		Next
	End Function

	Method update:Void()
		Self.x =Self.x +Self.xv *dt.delta
		Self.y =Self.y +Self.yv *dt.delta
		Self.xv =Self.xv *(1.0-(1.0-Self.vm )*dt.delta )
		Self.yv =Self.yv *(1.0-(1.0-Self.vm )*dt.delta )
		Self.life =Self.life -dt.delta
		If Self.life <0 Then Self.life =0

		If Self.life =0
			list.Remove(Self)
		Endif
	End Method

	Method draw:Void()
		Local tmul# = Self.life /Self.mlife
		Local tfls#=Rnd(-Self.cflash,Self.cflash)
		SetColor limit (Self.cr*tmul +tfls,Rnd(0,255),Rnd(0,255)),limit (Self.cg*tmul +tfls, Rnd(0,255), Rnd(0,255)),limit (Self.cb *tmul+tfls,Rnd(0,255),Rnd(0,255))
		Select Self.drawmode
			Case PDM_smlparticle
				SetAlpha 0.8
				DrawRect Self.x ,Self.y , 1, 1
			Case PDM_medparticle
				SetAlpha 0.5
				DrawOval Self.x -1,Self.y -1,3,3
			Case PDM_bigparticle
				SetAlpha 0.6
				DrawOval Self.x -2,Self.y -2,5,5
			Case PDM_spark
				SetAlpha 0.8
				DrawLine Self.x ,Self.y ,Self.x +Self.xv ,Self.y +Self.yv
		End Select
		SetAlpha 1
	End Method
End Class

Class Bullet Extends Sprite
	Global list:List<Bullet> = New List<Bullet>
	Field xv# ,yv#
	Field life#
	Field cr%, cg%, cb%

	Method New(x#,y#,xv#,yv#,life#,cr%,cg%,cb%)
		Self.x = x
		Self.y = y
		Self.xv = xv
		Self.yv = yv
		Self.life = life
		Self.cr = cr
		Self.cg = cg
		Self.cb = cb

		list.AddLast Self
	End Method

	Function updateAll:Void()
		If Not list Return
		For Local b:Bullet = Eachin list
			b.update()
			If b.life < 0
				Bullet.list.Remove(b)
				b = Null
			Endif

		Next
	End Function

	Method update:Void()
		x = x + xv * dt.delta
		y = y + yv * dt.delta

		life-=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

	Function drawAll:Void()
		If Not list Return
		For Local b:Bullet = Eachin list
			b.draw()
		Next
	End Function

	Method draw:Void()
		Local tmul#
		If life <= 15.0
			tmul = life / 15.0
		Else
			tmul = 1.0
		Endif
		SetColor cr*tmul, cg*tmul, cb*tmul
		SetAlpha 0.08
		LineB x, y, x + xv, y + yv, 6
		SetAlpha 0.01
		LineB x, y, x + xv, y + yv, 12
		SetAlpha 1
		DrawLine x, y, x + xv, y + yv
	End Method
End Class

Class Asteroid Extends Sprite
	Global list:List<Asteroid> = New List<Asteroid>
	Field xv#,yv#
	Field ang#,angvel#
	Field rad#[9]
	Field avgrad#
	Field size%
	Field life%
	Field cr%, cg%, cb%

	Method New(x#,y#,xv#,yv#,size%)
		Self.x =x
		Self.y =y
		Self.xv =xv
		Self.yv =yv
		Self.ang =Rnd(360)
		Self.angvel =Rnd(-6,6)
		Self.size=size
		Self.life=size
		Local tcol% = Rnd(-48,48)
		Self.cr=128+tcol
		Self.cg=128+tcol
		Self.cb=128+tcol
		' Create "Rockiness"
		Self.avgrad =0
		For Local t% = 0 To 7
			Self.rad[t]=size*8.0+Rnd(-size*4.0,size*4.0)
			Self.avgrad =Self.avgrad +Self.rad[t]
		Next
		Self.avgrad =Self.avgrad /6.0
		Self.rad[8] = Self.rad[0]

		list.AddLast Self
	End Method

	Function drawAll:Void()
		If Not list Return
		For Local b:Asteroid = Eachin list
			b.draw()
		Next
	End Function

	Function updateAll:Void()
		If Not list Return
		For Local b:Asteroid = Eachin list
			b.update()
		Next
	End Function

	Method update:Void()
		Self.x =Self.x +Self.xv * dt.delta
		Self.y =Self.y +Self.yv * dt.delta
		Self.rotation =Self.rotation +Self.angvel * dt.delta

		If Self.x <-Self.avgrad  Then Self.x =Self.x + SCREEN_WIDTH + Self.avgrad *2
		If Self.x >SCREEN_WIDTH+Self.avgrad  Then Self.x =Self.x - SCREEN_WIDTH - Self.avgrad *2
		If Self.y <-Self.avgrad  Then Self.y =Self.y + SCREEN_HEIGHT + Self.avgrad *2
		If Self.y >SCREEN_HEIGHT+Self.avgrad  Then Self.y =Self.y - SCREEN_HEIGHT - Self.avgrad *2
	End Method

	Method draw:Void()
		Local tmul# = 360.0 / 8.0
		Local r% = limit(cr + 100, 0, 255)
		Local g% = limit(cg + 100, 0, 255)

		Local x1#
		Local y1#
		Local x2#
		Local y2#
		Local glowOn% = 1
		SetColor r, g, 0
		For Local t% = 0 To 7
			x1 = (Sin(rotation+(t)*tmul)*rad[t])
			y1 = (Cos(rotation+(t)*tmul)*rad[t])
			x2 = (Sin(rotation+(t+1)*tmul)*rad[t+1])
			y2 = (Cos(rotation+(t+1)*tmul)*rad[t+1])

			If glowOn = 1
			For Local i% = 1 To 3
				Select i
					Case 1
						SetAlpha 0.04
					Case 2
						SetAlpha 0.01
					Case 3
						SetAlpha 0.01
				End Select
				LineB x - x1, y - y1, x - x2, y - y2, i * 6
			Next
			Endif
			SetAlpha 1
			DrawLine x-x1,y-y1,x-x2,y-y2
		Next
	End Method
End Class

Class Spark Extends Sprite
	Global list:List<Spark> = New List<Spark>
	Field life#=1
	Field vx#,vy#,van#
	Field size#

	Method New(_x#,_y#)
		Local v#=Rnd(1,2)
		size=v/2
		x = _x
		y = _y
		rotation=Rnd(360)
		vx=v*Sin(rotation)
		vy=v*Cos(rotation)

		list.AddLast Self

	End
	Function updateAll:Void()

		If Not list Return
		For Local b:Spark = Eachin list
			b.Update()
		Next
	End Function

	Method Update:Void()

		x += vx
		y += vy
		rotation += van

		life-=Rnd(.1)

		If life<=0
			Die
			Return
		Endif

		red=255*(Min(life,.5)+.5)
		green=255*life
		blue=0
	End

	Function drawAll:Void()
		If Not list Return
		For Local b:Spark = Eachin list
			b.Draw()
		Next
	End Function

	Method Draw:Void()
		SetColor red,green,blue
		DrawLine x,y,x-vx,y-vy
	End

	Method Die:Void()
		list.Remove Self
	End
End

Class Player Extends Sprite
	Field angVel#
	Field velmul#
	Field vel#
	Field acc#
	Field drag#
	Field xv#,yv#
	Field xa#,ya#
	Field firedel#

	Field ship_angvel#
	Field ship_acc#
	Field ship_velmul#
	Field ship_firedel#

	Field shield#=100

	Method New(x#, y#)
		Self.x = x
		Self.y = y
		ship_angvel = 6
		ship_acc = 0.16
		ship_velmul = -0.0005
		ship_firedel = 4
		shield = 100
	End Method

	Method Update:Void()

		If KeyDown(KEY_UP)
			acc =  ship_acc
			drag = vel * ship_velmul
			Local tang#=Rnd(-40,40)

			'Local s:=New Spark(x-Sgn(acc)*Sin(rotation)*10,y-Sgn(acc)*Cos(rotation)*10)
			Local s:= New Spark(x + (Sin(rotation)*8), y+(Cos(rotation)*8))
			'Local s:=New Spark(x,y)
			Local san#=Rnd(rotation-10,rotation+10)
			s.vx = Sgn(acc)*Sin(san)+xv
			s.vy = Sgn(acc)*Cos(san)+yv
		Else If KeyDown(KEY_DOWN)
			drag = vel * ship_velmul * 50
		Else
			acc = 0
			drag = 0
		End If
		If KeyDown(KEY_LEFT)
			rotation+=ship_angvel * dt.delta
		End If
		If KeyDown(KEY_RIGHT)
			rotation-=ship_angvel * dt.delta
		End If

		If KeyDown(KEY_SPACE) And Self.firedel<=0
			Local tang#=Rnd(-4,4)
			New Bullet(x - (Sin(rotation)*8), y-(Cos(rotation)*8), xv - (Sin(rotation + tang ) *12), yv-(Cos(rotation + tang ) *12), 45, 255-Rnd(4), 192+Rnd(-4,4), 64+Rnd(4,4))
			firedel = ship_firedel
		Endif
		firedel-=dt.delta

		xa = (drag * xv) - (Sin(rotation) * acc)
		ya = (drag * yv) - (Cos(rotation) * acc)
		xv = xv + xa *dt.delta
		yv = yv + ya * dt.delta
		x = x + xv * dt.delta
		y = y + yv * dt.delta
		vel = dist(0, 0, xv, yv)
'
		If x < 0 x = SCREEN_WIDTH
		If x > SCREEN_WIDTH x = 0
		If y < 0 y = SCREEN_HEIGHT
		If y > SCREEN_HEIGHT y = 0

		If shield <= 0
			For Local t%=1 To 18
				New Particle( x, y,Rnd(-10,10),Rnd(-10,10),0.95,130,PDM_spark,255,192,64,64)
			Next
			For Local t%=1 To 16
				New Particle( x, y,Rnd(-6,6),Rnd(-6,6),0.95,130,PDM_medparticle,255,192,64,128)
			Next
			For Local t%=1 To 16
				New Particle( x, y,Rnd(-8,8),Rnd(-8,8),0.99,160,PDM_smlparticle,160,160,160,0)
			Next
			For Local t%=1 To 15
				New Particle( x, y,Rnd(-6,6),Rnd(-6,6),0.99,160,PDM_medparticle,160,160,160,0)
			Next
			For Local t%=1 To 14
				New Particle( x, y,Rnd(-4,4),Rnd(-4,4),0.99,160,PDM_bigparticle,160,160,160,0)
			Next

			If game.score>game.bestScore
				game.bestScore = game.score
			Endif

			game.setState(STATE_GAME_OVER)
		Endif
	End Method

	Method draw:Void()
		Local x1# = x-(Sin(rotation) * 10)
		Local y1# = y-(Cos(rotation) * 10)
		Local x2# = x-(Sin(rotation + 140 ) * 8)
		Local y2# = y-(Cos(rotation + 140 ) * 8)
		Local x3# = x-(Sin(rotation - 140 ) * 8)
		Local y3# = y-(Cos(rotation - 140 ) * 8)
		SetColor 100, 200, 255

		SetAlpha 0.04
		LineB x1, y1, x2, y2, 6
		LineB x2, y2, x3, y3, 6
		LineB x3, y3, x1, y1, 6

		SetAlpha 0.01
		LineB x1, y1, x2, y2, 12
		LineB x2, y2, x3, y3, 12
		LineB x3, y3, x1, y1, 12

'		SetAlpha 0.1

		SetAlpha 1
		DrawLine x1, y1, x2, y2
		DrawLine x2, y2, x3, y3
		DrawLine x3, y3, x1, y1

		Local x% = 20
		Local y% = SCREEN_HEIGHT - 20
		Local h% = 10
		SetColor 0, 255, 0
		If shield < 50 Then SetColor 255,0,0
		For Local i% = 1 To 3
			SetAlpha 0.1
			DrawRect x - i*2 , y - i*2, Self.shield + i * 4, h + i*4
		Next

		SetAlpha 0.8
		DrawRect x, y, Self.shield, h
		SetAlpha 1
		SetColor 255,0,0
	End Method

End Class

Function dist#(x1#,y1#,x2#,y2#)
	Return Sqrt(Pow((x1-x2),2) + Pow((y1-y2),2))
End Function

Function limit#(value#,low#,high#)
	If value < low Then Return low
	If value > high Then Return high
	Return value
End Function

Function LineB:Void(x1%, y1%, x2%, y2%, thickness%, rect:Bool = True)
	'Ported
	'Bresenham Line Algorithm
	'Source - GameDev.Net - Mark Feldman
	'Public Domain

	Local deltax% = Abs(x2 - x1)
	Local deltay% = Abs(y2 - y1)

	Local numpixels%,d%,dinc1%,dinc2%,xinc1%,xinc2%,yinc1%,yinc2%,x%,y%,i%

	If deltax >= deltay
		numpixels = deltax + 1
		d = (2 * deltay) - deltax
		dinc1 = deltay Shl 1
		dinc2 = (deltay - deltax) Shl 1
		xinc1 = 1
		xinc2 = 1
		yinc1 = 0
		yinc2 = 1
	Else
		numpixels = deltay + 1
		d = (2 * deltax) - deltay
		dinc1 = deltax Shl 1
		dinc2 = (deltax - deltay) Shl 1
		xinc1 = 0
		xinc2 = 1
		yinc1 = 1
		yinc2 = 1
	Endif

	If x1 > x2
		xinc1 = -xinc1
		xinc2 = -xinc2
	Endif

	If y1 > y2
		yinc1 = -yinc1
		yinc2 = -yinc2

	Endif

	x = x1
	y = y1
	Local half% = thickness / 2
	For i = 1 To numpixels
		If rect
			DrawRect x - half, y - half, thickness, thickness
		Else
			DrawOval x - half, y- half, thickness, thickness
		Endif
		If d < 0
			d = d + dinc1
			x = x + xinc1
			y = y + yinc1
		Else
			d = d + dinc2
			x = x + xinc2
			y = y + yinc2
		Endif

	Next

End Function

Global SCREEN_WIDTH%
Global SCREEN_HEIGHT%
Global SCREEN_WIDTH2%
Global SCREEN_HEIGHT2%
Global dt:DeltaTimer

Class FrameworkApp Extends App

	Field FPS% = 60

	Method OnCreate:Int()
		' Store the device width and height
		SCREEN_WIDTH = DeviceWidth()
		SCREEN_HEIGHT = DeviceHeight()
		SCREEN_WIDTH2 = SCREEN_WIDTH / 2
		SCREEN_HEIGHT2 = SCREEN_HEIGHT / 2
		' Set the Random seed
		Seed = Millisecs()
		' Create the delta timer
		dt = New DeltaTimer(FPS)
		SetUpdateRate FPS
		Return 0
	End Method

	Method OnLoading:Int()
		Cls 0,0,0
		DrawText("Loading", SCREEN_WIDTH2, SCREEN_HEIGHT2, 0.5, 0)
		Return 0
	End Method

	Method OnRender:Int()
		Return 0
	End Method

	Method OnUpdate:Int()
		FPSCounter.update()
		dt.UpdateDelta()
		Return 0
	End Method
End Class

Class FPSCounter Abstract
	Global fpsCount:Int
	Global startTime:Int
	Global totalFPS:Int

	Function update:Void()
		If Millisecs() - startTime >= 1000
			totalFPS = fpsCount
			fpsCount = 0
			startTime = Millisecs()
		Else
			fpsCount+=1
		Endif
	End Function

	Function draw:Void(x% = 0, y% = 0, ax# = 0, ay# = 0)
		DrawText("FPS: " + totalFPS, x, y, ax, ay)
	End Function

End Class

' From James Boyd
Class DeltaTimer
	Field targetfps:Float = 60
	Field currentticks:Float
	Field lastticks:Float
	Field frametime:Float
	Field delta:Float

	Method New (fps:Float)
		targetfps = fps
		lastticks = Millisecs()
	End

	Method UpdateDelta:Void()
		currentticks = Millisecs()
		frametime = currentticks - lastticks
		delta = frametime / (1000.0 / targetfps)
		lastticks = currentticks
	End
End

Class Sprite
	Field x#, y#
	Field dx#, dy#
	Field scaleX# = 1, scaleY# = 1
	Field rotation#, rotationSpeed#
	Field red%, green%, blue%, alpha#

	Method move:Void()
		Self.x+=Self.dx * dt.delta
		Self.y+=Self.dy * dt.delta
	End Method

	Method moveForward:Void()
		dx = -Sin(rotation) * speed
        dy = -Cos(rotation) * speed

		move()
	End Method
End Class

error: pathspec 'monkeymax/bananas/bmax/asteroids.monkey' did not match any file(s) known to git


Added GlobalPool class that can be used in a similar way to the official Monkey Pool class, but it is essentially a singleton with the benefit of the IPoolable interface.

--HG--
branch : containers

#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

error: pathspec 'src/diddy/globalpool.monkey' did not match any file(s) known to git


Added Matrix3D module.

Added Matrix3D module.

--HG--
extra : rebase_source : 10b822ec4582b19f2d3fd014bb95b4eb8afd7f29

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

Public
Class Matrix3D
Public
	' +-           -+
	' | M00 M01 M02 |
	' | M10 M11 M12 |
	' | M20 M21 M22 |
	' +-           -+
	Const M00:Int = 0 ' row 0, column 0
	Const M01:Int = 3 ' row 0, column 1
	Const M02:Int = 6 ' row 0, column 2
	Const M10:Int = 1 ' row 1, column 0
	Const M11:Int = 4 ' row 1, column 1
	Const M12:Int = 7 ' row 1, column 2
	Const M20:Int = 2 ' row 2, column 0
	Const M21:Int = 5 ' row 2, column 1
	Const M22:Int = 8 ' row 2, column 2

Private
	Field tmp:Float[] = New Float[9]

Public
	Field val:Float[] = New Float[9]

	Method New()
		Identity()
	End

	Method New(matrix:Matrix3D)
		SetToMatrix(matrix)
	End

	Method Identity:Matrix3D()
		val[M00] = 1
		val[M10] = 0
		val[M20] = 0
		val[M01] = 0
		val[M11] = 1
		val[M21] = 0
		val[M02] = 0
		val[M12] = 0
		val[M22] = 1
		Return Self
	End

	Method CrossMultiply:Matrix3D(m:Matrix3D)
		Local v00:Float = val[M00] * m.val[M00] + val[M01] * m.val[M10] + val[M02] * m.val[M20]
		Local v01:Float = val[M00] * m.val[M01] + val[M01] * m.val[M11] + val[M02] * m.val[M21]
		Local v02:Float = val[M00] * m.val[M02] + val[M01] * m.val[M12] + val[M02] * m.val[M22]

		Local v10:Float = val[M10] * m.val[M00] + val[M11] * m.val[M10] + val[M12] * m.val[M20]
		Local v11:Float = val[M10] * m.val[M01] + val[M11] * m.val[M11] + val[M12] * m.val[M21]
		Local v12:Float = val[M10] * m.val[M02] + val[M11] * m.val[M12] + val[M12] * m.val[M22]

		Local v20:Float = val[M20] * m.val[M00] + val[M21] * m.val[M10] + val[M22] * m.val[M20]
		Local v21:Float = val[M20] * m.val[M01] + val[M21] * m.val[M11] + val[M22] * m.val[M21]
		Local v22:Float = val[M20] * m.val[M02] + val[M21] * m.val[M12] + val[M22] * m.val[M22]

		val[M00] = v00
		val[M10] = v10
		val[M20] = v20
		val[M01] = v01
		val[M11] = v11
		val[M21] = v21
		val[M02] = v02
		val[M12] = v12
		val[M22] = v22

		Return Self
	End

	Method SetToRotation:Matrix3D(degrees:Float)
		Local cos:Float = Cos(degrees)
		Local sin:Float = Sin(degrees)

		val[M00] = cos
		val[M10] = sin
		val[M20] = 0

		val[M01] = -sin
		val[M11] = cos
		val[M21] = 0

		val[M02] = 0
		val[M12] = 0
		val[M22] = 1

		Return Self
	End

	Method SetToTranslation:Matrix3D(x:Float, y:Float)
		val[M00] = 1
		val[M10] = 0
		val[M20] = 0

		val[M01] = 0
		val[M11] = 1
		val[M21] = 0

		val[M02] = x
		val[M12] = y
		val[M22] = 1

		Return Self
	End

	Method SetToTranslation:Matrix3D(translation:Vector2D)
		val[M00] = 1
		val[M10] = 0
		val[M20] = 0

		val[M01] = 0
		val[M11] = 1
		val[M21] = 0

		val[M02] = translation.x
		val[M12] = translation.y
		val[M22] = 1

		Return Self
	End

	Method SetToScaling:Matrix3D(scaleX:Float, scaleY:Float)
		val[M00] = scaleX
		val[M10] = 0
		val[M20] = 0
		val[M01] = 0
		val[M11] = scaleY
		val[M21] = 0
		val[M02] = 0
		val[M12] = 0
		val[M22] = 1
		Return Self
	End

	Method Determinant:Float()
		Return val[M00] * val[M11] * val[M22] + val[M01] * val[M12] * val[M20] + val[M02] * val[M10] * val[M21] - val[M00] * val[M12] * val[M21] - val[M01] * val[M10] * val[M22] - val[M02] * val[M11] * val[M20]
	End

	Method Inverse:Matrix3D()
		Local d:Float = Determinant()
		If d = 0 Then Return Self

		Local inv_det:Float = 1.0 / d

		tmp[M00] = val[M11] * val[M22] - val[M21] * val[M12]
		tmp[M10] = val[M20] * val[M12] - val[M10] * val[M22]
		tmp[M20] = val[M10] * val[M21] - val[M20] * val[M11]
		tmp[M01] = val[M21] * val[M02] - val[M01] * val[M22]
		tmp[M11] = val[M00] * val[M22] - val[M20] * val[M02]
		tmp[M21] = val[M20] * val[M01] - val[M00] * val[M21]
		tmp[M02] = val[M01] * val[M12] - val[M11] * val[M02]
		tmp[M12] = val[M10] * val[M02] - val[M00] * val[M12]
		tmp[M22] = val[M00] * val[M11] - val[M10] * val[M01]

		val[M00] = inv_det * tmp[M00]
		val[M10] = inv_det * tmp[M10]
		val[M20] = inv_det * tmp[M20]
		val[M01] = inv_det * tmp[M01]
		val[M11] = inv_det * tmp[M11]
		val[M21] = inv_det * tmp[M21]
		val[M02] = inv_det * tmp[M02]
		val[M12] = inv_det * tmp[M12]
		val[M22] = inv_det * tmp[M22]

		Return Self
	End

	Method SetToMatrix:Matrix3D(mat:Matrix3D)
		For Local i:Int = 0 Until val.Length
			val[i] = mat.val[i]
		Next
		Return Self
	End

	Method ScalarTranslate:Matrix3D(vector:Vector2D)
		val[M02] += vector.x
		val[M12] += vector.y
		Return Self
	End

	Method ScalarTranslate:Matrix3D(x:Float, y:Float)
		val[M02] += x
		val[M12] += y
		Return Self
	End

	Method Translate:Matrix3D(x:Float, y:Float)
		tmp[M00] = 1
		tmp[M10] = 0
		tmp[M20] = 0

		tmp[M01] = 0
		tmp[M11] = 1
		tmp[M21] = 0

		tmp[M02] = x
		tmp[M12] = y
		tmp[M22] = 1
		CrossMultiply(tmp)
		Return Self
	End

	Method Translate:Matrix3D(translation:Vector2)
		tmp[M00] = 1
		tmp[M10] = 0
		tmp[M20] = 0

		tmp[M01] = 0
		tmp[M11] = 1
		tmp[M21] = 0

		tmp[M02] = translation.x
		tmp[M12] = translation.y
		tmp[M22] = 1
		CrossMultiply(tmp)
		Return Self
	End

	Method Rotate:Matrix3D(angle:Float)
		If angle = 0 Then Return Self
		Local cos:Float = Cos(angle)
		Local sin:Float = Sin(angle)

		tmp[M00] = cos
		tmp[M10] = sin
		tmp[M20] = 0

		tmp[M01] = -sin
		tmp[M11] = cos
		tmp[M21] = 0

		tmp[M02] = 0
		tmp[M12] = 0
		tmp[M22] = 1
		CrossMultiply(tmp)
		Return Self
	End

	Method Scale:Matrix3D(scaleX:Float, scaleY:Float)
		tmp[M00] = scaleX
		tmp[M10] = 0
		tmp[M20] = 0
		tmp[M01] = 0
		tmp[M11] = scaleY
		tmp[M21] = 0
		tmp[M02] = 0
		tmp[M12] = 0
		tmp[M22] = 1
		CrossMultiply(tmp)
		Return Self
	End

	Method Scale:Matrix3D(v:Vector2)
		tmp[M00] = v.x
		tmp[M10] = 0
		tmp[M20] = 0
		tmp[M01] = 0
		tmp[M11] = v.y
		tmp[M21] = 0
		tmp[M02] = 0
		tmp[M12] = 0
		tmp[M22] = 1
		CrossMultiply(tmp)
		Return Self
	End

	Method ScalarScale:Matrix3D(s:Float)
		val[M00] *= s
		val[M11] *= s
		Return Self
	End

	Method ScalarScale:Matrix3D(v:Vector2D)
		val[M00] *= v.x
		val[M11] *= v.y
		Return Self
	End

	Method Transpose:Matrix3D()
		Local v01:Float = val[M10]
		Local v02:Float = val[M20]
		Local v10:Float = val[M01]
		Local v12:Float = val[M21]
		Local v20:Float = val[M02]
		Local v21:Float = val[M12]
		val[M01] = v01
		val[M02] = v02
		val[M10] = v10
		val[M12] = v12
		val[M20] = v20
		val[M21] = v21
		Return Self
	End
End

error: pathspec 'src/diddy/matrix3d.monkey' did not match any file(s) known to git


Added real world example of coroutine usage.

Strict

Import mojo
Import threading

Function Main:Int()
	New MyApp
	Return 0
End

Class MyApp Extends App
	Field robot:Robot

	Method OnCreate:Int()
		SetUpdateRate(60)
		robot = New Robot(50, 50)
		Return 0
	End

	Method OnUpdate:Int()
		' Handle exit
		If KeyHit(KEY_ESCAPE) Then Error ""
		' Update our robot, which handles scripting and movement
		robot.Update()
		Return 0
	End

	Method OnRender:Int()
		Cls
		' Render our robot
		robot.Render()
		Return 0
	End
End

Class Robot Extends Coroutine
	' Our current location
	Field x:Float, y:Float

	' Where we first started moving from
	Field sourceX:Float, sourceY:Float

	' Where we're going
	Field targetX:Float, targetY:Float

	' How many frames it should take us to get there
	Field movementTotalFrames:Int

	' How many frames are left before we get there
	Field movementRemainingFrames:Int

	' How long left to wait
	Field waitFrames:Int

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

	' Tell our robot where to move to
	Method MoveTo:Void(targetX:Float, targetY:Float, distancePerFrame:Float)
		' Store our source and target waypoints
		Self.sourceX = Self.x
		Self.sourceY = Self.y
		Self.targetX = targetX
		Self.targetY = targetY

		' Work out how many frames it will take to get there
		Local distance:Float = Sqrt((Self.targetX-Self.sourceX)*(Self.targetX-Self.sourceX)+(Self.targetY-Self.sourceY)*(Self.targetY-Self.sourceY))
		Local totalFrames:Int = distance/distancePerFrame
		Self.movementTotalFrames = totalFrames
		Self.movementRemainingFrames = totalFrames
	End

	' update our robot
	Method Update:Void()
		' If the robot is waiting, subtract one frame, otherwise resume the coroutine
		If waitFrames > 0 Then
			waitFrames -= 1
		Else
			' The parameter passed to Yield will be the return value for Resume
			waitFrames = Resume()
		End

		' If we're currently moving, interpolate our position
		If movementRemainingFrames > 0 Then
			' We've moved one frame closer
			movementRemainingFrames -= 1

			' This is how far we are into the movement
			Local alpha:Float = 1 - Float(movementRemainingFrames)/Float(movementTotalFrames)

			' Run a smoothstep algorithm on it (optional, but it makes the movement look much nicer)
			' See this website for an explanation: http://sol.gfxile.net/interpolation/
			alpha *= alpha * (3-2*alpha)

			' Update our position
			x = sourceX + alpha * (targetX-sourceX)
			y = sourceY + alpha * (targetY-sourceY)
		End
	End

	' Render our robot.
	Method Render:Void()
		' Our robot isn't very pretty and just looks like a circle
		SetColor 255, 0, 0
		DrawCircle x, y, 20
	End

	' The Run method acts as a kind of AI script, telling the robot what to do
	' This is called on the first call to Resume()
	Method Run:Int(param:Int)
		' Store our starting position
		Local startX:Float = x
		Local startY:Float = y

		' Our robot is fairly stupid and will just follow a set path forever
		Repeat
			' Start moving from start position to 200,200 at a speed of 4 pixels per frame
			MoveTo(200,200,4)

			' Wait until we get there
			Yield(Self.movementTotalFrames)

			' Announce we've arrived
			Print "Arrived at waypoint 1!"

			' Wait there for 60 frames
			Yield(60)

			' Start moving from 200,200 to 350,300 at a speed of 2 pixels per frame
			MoveTo(350,300,2)

			' Wait until we get there
			Yield(Self.movementTotalFrames)

			' Announce we've arrived
			Print "Arrived at waypoint 2!"

			' Wait there for 60 frames
			Yield(60)

			' Start moving back to the start at 5 pixels per frame
			MoveTo(startX,startY,5)

			' Wait until we get there
			Yield(Self.movementTotalFrames)

			' Announce we've arrived
			Print "Arrived at starting point!"

			' Wait there for 60 frames
			Yield(60)

			' Loop, starting all over again!
		Forever
	End
End

error: pathspec 'examples/Threading/coroutineDemo.monkey' did not match any file(s) known to git


Added missing files

Added missing files

Strict

Import flixel.flxextern

Class FlxString Implements FlxStringable

Private
	Field _value:String
	Field _isChanged:Bool

Public
	Method New()
	End Method

	Method New(value:String)
		_value = value
		_isChanged = True
	End Method

	Method ToString:String()
		Return _value
	End Method

	Method FromString:FlxStringable(value:String)
		_value = value
		_isChanged = True
		Return Self
	End Method

	Method IsChanged:Bool()
		If (_isChanged) Then
			_isChanged = False
			Return True
		End If

		Return False
	End Method

End Class

error: pathspec 'system/flxstring.monkey' did not match any file(s) known to git


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

' force strict coding standard
Strict

' import the mojo module
Import mojo
' import the diddy module
Import diddy

' the starting point for a Monkey app
Function Main:Int()
	' create the "game"
	New MyGame
	Return 0
End

' MyGame
Class MyGame Extends App
	' save the starting seed
	Field startingSeed:Int

	Method OnCreate:Int()
		' set the seed to use the system time
		startingSeed = RealMillisecs()
		Seed = startingSeed
		' 60 FPS please
		SetUpdateRate 60
		Return 0
	End

	Method OnUpdate:Int()
		' this will print "No FlushKeys 3 times
		For Local i:Int = 1 To 3
			If KeyHit(KEY_SPACE)
				Print "No FlushKeys"
			End
		Next
		' this will print "FlushKeys once
		For Local i:Int = 1 To 3
			If KeyHit(KEY_SPACE)
				Print "FlushKeys"
				' force the seed to change
				Rnd(0,1000)
			End
			' clear the key hits
			FlushKeys()
		Next
		Return 0
	End

	Method OnRender:Int()
		Cls
		DrawText "Starting Seed = "+startingSeed, 10, 10
		DrawText "Seed          = "+Seed, 10, 20
		DrawText "RealMillisecs = "+RealMillisecs(), 10, 30
		DrawText "Millisecs     = "+Millisecs(), 10, 40

		Return 0
	End

End

error: pathspec 'examples/testApp.monkey' did not match any file(s) known to git


added sample file

added sample file

Strict

#rem
this is a
#rem
nested
#end
comment
even other preproc keywords are nested within!
#If TARGET
#End
#end

Import mojo

Const ONECONST:Int = 1
Const TWOCONST := 2
Const THREECONST := 3, FOURCONST:Int = 4

Class Game Extends App

    ' radial sprial with axis aligned phase

    Function DrawSpiral(clock)
        Local w=DeviceWidth/2
        For Local i#=0 Until w*1.5 Step .2
            Local x#,y#
            x=w+i*Sin(i*3+clock)
            y=w+i*Cos(i*2+clock)
            DrawRect  x,y,1,1
        Next
        hitbox.Collide(event.pos)
    End

    Field updateCount

    Method OnCreate()
        Print "spiral"

        SetUpdateRate 60
    End

    Method OnUpdate()
        updateCount+=1
    End

    Method OnRender()
        Cls
        DrawSpiral updateCount
        DrawSpiral updateCount*1.1
    End

End

Class VectorNode Extends Node<Vector2D>
End

Function Main()
    New Game()
End

error: pathspec 'tests/examplefiles/example.monkey' did not match any file(s) known to git


Added an example showcasing 'ArrayView.Clear'.

Strict

Public

' Imports:
Import regal.util.bufferview

' Functions:
Function Main:Int()
	Local Buffer:= New ShortArrayView(512)

	Local Indices:= [0, 1]
	Local Values:= [1234, 5678]
	Local ItemCount:= Values.Length ' 2

	Print("Storing the following values at the indices posted:")

	For Local I:= 0 Until ItemCount
		Print("[" + Indices[I] + "]: " + Values[I])

		Buffer.Set(Indices[I], Values[I])
	Next

	Print("Retrieving values:")

	RetrieveValues(Buffer, 0, ItemCount)

	Print("Clearing the first entry of the buffer...")

	Buffer.Clear(0, 1)

	Print("Retrieving values again:")

	RetrieveValues(Buffer, 0, ItemCount)

	Print("Clearing the entire buffer...")

	Buffer.Clear()

	Print("Retrieving values again (Should be zero-initialized):")

	RetrieveValues(Buffer, 0, ItemCount)

	Return 0
End

Function RetrieveValues:Void(Buffer:ShortArrayView, Offset:Int, ItemCount:Int) ' Buffer:IntArrayView
	For Local I:= Offset Until ItemCount
		Print("[" + I + "]: " + Buffer.Get(I))
	Next

	Return
End

error: pathspec 'Examples/Buffer_Clear_Example.monkey' did not match any file(s) known to git


added sample file

added sample file


XML examples.

XML examples.

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

Strict

Import diddy.xml

Function Main:Int()
	Local parser:XMLParser = New XMLParser
	Local doc:XMLDocument = parser.ParseString(LoadString("server.xml"))
	'Local doc:XMLDocument = parser.ParseString("<?xml version=~q1.0~q encoding=~qUTF-8~q?><Server port=~q8005~q shutdown=~qSHUTD&<OWN~q>  <Listener className=~qorg.apache.catalina.core.AprLifecycleListener~q/>  <Listener className=~qorg.apache.catalina.mbeans.ServerLifecycleListener~q/>  <Listener className=~qorg.apache.catalina.mbeans.GlobalResourcesLifecycleListener~q/>  <Listener className=~qorg.apache.catalina.storeconfig.StoreConfigLifecycleListener~q/>  <GlobalNamingResources>    <Environment name=~qsimpleValue~q type=~qjava.lang.Integer~q value=~q30~q/>    <Resource auth=~qContainer~q driverClassName=~qoracle.jdbc.OracleDriver~q maxActive=~q20~q maxIdle=~q10~q maxWait=~q-1~q name=~qjdbc/tmsicsd~q password=~qpndev~q type=~qjavax.sql.DataSource~q url=~qjdbc:oracle:thin:@//pnlvsun30:9086/TMSV10D~q username=~qtms_own~q/>    <Resource auth=~qContainer~q driverClassName=~qoracle.jdbc.OracleDriver~q maxActive=~q20~q maxIdle=~q10~q maxWait=~q-1~q name=~qjdbc/tmsicss~q password=~qTMSS1TS~q type=~qjavax.sql.DataSource~q url=~qjdbc:oracle:thin:@//pnlvsun30:9186/TMSV10S~q username=~qTMS_OWN~q/>  </GlobalNamingResources>  <Service name=~qCatalina~q>    <Connector acceptCount=~q100~q connectionTimeout=~q20000~q disableUploadTimeout=~qtrue~q enableLookups=~qfalse~q maxHttpHeaderSize=~q8192~q maxSpareThreads=~q75~q maxThreads=~q150~q minSpareThreads=~q25~q port=~q8080~q redirectPort=~q8443~q/>    <Connector enableLookups=~qfalse~q port=~q8009~q protocol=~qAJP/1.3~q redirectPort=~q8443~q/>    <Engine defaultHost=~qlocalhost~q name=~qCatalina~q>      <Host appBase=~qwebapps~q autoDeploy=~qtrue~q name=~qlocalhost~q unpackWARs=~qtrue~q xmlNamespaceAware=~qfalse~q xmlValidation=~qfalse~q>        <Context docBase=~qFreightWeb~q path=~q/FreightWeb~q reloadable=~qtrue~q source=~qorg.eclipse.jst.j2ee.server:FreightWeb~q>          <!--<ResourceLink global=~qjdbc/tmsicsd~q name=~qjdbc/pnonline~q type=~qjavax.sql.DataSource~q/>-->          <ResourceLink global=~qjdbc/tmsicsd~q name=~qjdbc/pnonline~q type=~qoracle.jdbc.pool.OracleDataSource~q/>          <!-- <ResourceLink global=~qjdbc/tmsicss~q name=~qjdbc/pnonline~q type=~qjavax.sql.DataSource~q/> -->        </Context>      <Context docBase=~qPNOnline~q path=~q/PNOnline~q reloadable=~qtrue~q source=~qorg.eclipse.jst.j2ee.server:PNOnline~q/></Host>    </Engine>  </Service></Server>")
	Print doc.root.GetAttribute("shutdown")
	Print doc.root.Children.Get(0).Parent.Name
	Print doc.ExportString()
#Rem
	Local doc:XMLDocument = New XMLDocument
	doc.root = New XMLElement
	doc.root.name = "root"

	Local child1 := New XMLElement
	child1.name = "mychild"
	child1.SetAttribute("foo", "bar")
	child1.SetAttribute("hello", "world")
	doc.root.AddChild(child1)

	Local child2 := New XMLElement
	child2.name = "mychild"
	child2.SetAttribute("david", "jones")
	child2.SetAttribute("harvey", "norman")
	doc.root.AddChild(child2)

	Print(doc.ExportString())
	Print(doc.ExportString(False))
	Return 0
#End
End

error: pathspec 'examples/XML/testXML.monkey' did not match any file(s) known to git


Added real world example of coroutine usage.

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


Fixed Windows 8/RT support.

Fixed Windows 8/RT support.

Strict

Public

' Preprocessor related:
#If BRL_GAMETARGET_IMPLEMENTED 'LANG = "cpp" And TARGET <> "glfw" And TARGET <> "win8" And TARGET <> "winrt" And TARGET <> "sexy"
	#TIME_MOJO_IMPLEMENTED = True
#Else
	#TIME_MOJO_IMPLEMENTED = False
#End

#If LANG = "cpp" Or LANG = "cs" ' And TARGET <> "ios"
	#DELAY_IMPLEMENTED = True

	#If Not TIME_MOJO_IMPLEMENTED
		#MILLISECS_IMPLEMENTED = True
	#Else
		#MILLISECS_IMPLEMENTED = False
	#End
#End

#If LANG = "cpp" And TARGET <> "win8" And TARGET <> "winrt"
	#DELAY_EXTERNAL_FILE = True
	#MILLISECS_EXTERNAL_FILE = True
#End

' Imports (Monkey):
'Import mojo

' Imports (Native):
#If DELAY_IMPLEMENTED And DELAY_EXTERNAL_FILE
	Import "native/delay.${LANG}"
#End

#If MILLISECS_IMPLEMENTED And MILLISECS_EXTERNAL_FILE
	Import "native/millisecs.${LANG}"

	#Rem
		' No longer needed:
		#If HOST = "linux"
			#CC_LIBS += "-lrt"
		#End
	#End
#End

' External bindings:
Extern

#If DELAY_IMPLEMENTED
	' Private external-wrapper(s):
	#If LANG = "cpp"
		#If TARGET = "win8" Or TARGET = "winrt"
			' Windows 8 specific:
			Function __Native_Delay:Void(MS:Int)="Concurrency::wait"
		#Else
			Function Delay:Bool(MS:Int)="delay"
		#End
	#Elseif LANG = "cs"
		Function __Native_Delay:Void(MS:Int) = "System.Threading.Thread.Sleep"
	#End
#End

#If MILLISECS_IMPLEMENTED
	Function Millisecs:Int()="millisecs"
#End

Public

' Wrappers for external functions:
#If LANG = "cs" Or TARGET = "win8" Or TARGET = "winrt"
	' This wrapper is for external commands which don't have return types:
	Function Delay:Bool(MS:Int)
		__Native_Delay(MS)

		' Return the default response.
		Return True
	End
#End

Strict

Public

' Preprocessor related:
#If BRL_GAMETARGET_IMPLEMENTED 'LANG = "cpp" And TARGET <> "glfw" And TARGET <> "win8" And TARGET <> "sexy"
	#TIME_MOJO_IMPLEMENTED = True
#Else
	#TIME_MOJO_IMPLEMENTED = False
#End

#If LANG = "cpp" Or LANG = "cs" ' And TARGET <> "ios"
	#DELAY_IMPLEMENTED = True

	#If Not TIME_MOJO_IMPLEMENTED
		#MILLISECS_IMPLEMENTED = True
	#Else
		#MILLISECS_IMPLEMENTED = False
	#End
#End

#If LANG = "cs"
	#DELAY_EXTERNAL_FILE = True
#End

' Imports (Monkey):
'Import mojo

' Imports (Native):
#If DELAY_IMPLEMENTED And Not DELAY_EXTERNAL_FILE
	Import "native/delay.${LANG}"
#End

#If MILLISECS_IMPLEMENTED And Not MILLISECS_EXTERNAL_FILE
	Import "native/millisecs.${LANG}"

	#Rem
		' No longer needed:
		#If HOST = "linux"
			#CC_LIBS += "-lrt"
		#End
	#End
#End

' External bindings:
Extern

#If DELAY_IMPLEMENTED
	' Private external-wrapper(s):
	#If LANG = "cpp"
		#If TARGET = "win8"
			' Windows 8 specific:
			Function __Native_Delay:Void(MS:Int)="Concurrency::wait"
		#Else
			Function Delay:Bool(MS:Int)="delay"
		#End
	#Elseif LANG = "cs"
		Function __Native_Delay:Void(MS:Int) = "System.Threading.Thread.Sleep"
	#End
#End

#If MILLISECS_IMPLEMENTED
	Function Millisecs:Int()="millisecs"
#End

Public

' Wrappers for external functions:
#If LANG = "cs" Or TARGET = "win8"
	' This wrapper is for external commands which don't have return types:
	Function Delay:Bool(MS:Int)
		__Native_Delay(MS)

		' Return the default response.
		Return True
	End
#End


FlxBitmapdata class added. Not completed

Strict

Import mojo.graphics
Import flixel.flxpoint
Import flixel.flxrect
Import flixel.system.flxcolor

Class FlxBitmapData

Private
	Field _width:Int

	Field _height:Int

	Field _storePixels:Bool

	Field _image:Image

	Field _color:FlxColor

	Field _rect:FlxRect

	Field _pixels:Int[]

Public
	Method New(width:Int, height:Int, storePixels:Bool = False, fillColor:Int = $00000000)
		_image = CreateImage(width, height)
		_color = New FlxColor(fillColor)
		_rect = New FlxRect()

		_width = width
		_height = height
		_storePixels = storePixels

		If (_storePixels) _pixels = New Int[_width * _height]

		If (_color.a > 0) Then
			If ( Not _storePixels) _pixels = New Int[_width * _height]
			_FillPixels(0, 0, _width, _height, fillColor)

			_image.WritePixels(_pixels, 0, 0, _width, _height)
		End If
	End Method

	Method Destroy:Void()
		_pixels = Null
		_color = Null
		_rect = Null
		_image.Discard()
	End Method

	Method CopyPixels:Void()
		'TODO!
	End Method

	Method Dispose:Void()
		_pixels = New Int[0]
		_storePixels = False
	End Method

	Method FillRect:Void(rect:FlxRect, color:Int)
		If ( Not _storePixels) Then
			_FillPixels(0, 0, rect.width, rect.height, color)
			_image.WritePixels(_pixels, rect.x, rect.y, rect.width, rect.height)
		Else
			_FillPixels(rect.x, rect.y, rect.width, rect.height, color)
			_image.WritePixels(_pixels, rect.x, rect.y, rect.width, rect.height, rect.x + rect.y * rect.width, _width)
		End If
	End Method

	Method FloodFill:Void(x:Int, y:Int, color:Int)
		FillRect(_rect.Make(x, y, _width - x, _height - y), color)
	End Method

	Method GetPixel:Int(x:Float, y:Float)
		If (_storePixels) Then
			Return _pixels[x + y * _width]
		End If

		Return 0
	End Method

	Method GetPixels:Int[] (rect:FlxRect)
		Local result:Int[] = New Int[rect.width * rect.height]

		If (_storePixels) Then
			Local i:Int, j:Int, m:Int, k:Int = rect.x + rect.y * rect.width

			For i = 0 Until rect.height
				For j = 0 Until rect.width
					result[m] = _pixels[k]
					k += 1
					m += 1
				Next
				k += _width - rect.width
			Next
		End If

		Return result
	End Method

	Method Width:Int() Property
		Return _width
	End Method

	Method Height:Int() Property
		Return _height
	End Method

	Method Image:Image() Property
		Return _image
	End Method

Private
	Method _CheckPixelsArray:Void(width:Int, height:Int)
		If (_pixels.Length() < width * height) Then
			_pixels = _pixels.Resize(width * height)
		End If
	End Method

	Method _FillPixels:Void(x:Int, y:Int, width:Int, height:Int, color:Int)
		Local offset:Int = x + y * width

		If ( Not _storePixels) Then
			Local i:Int = offset, l:Int = offset + width * height
			_CheckPixelsArray(width, height)

			While (i < l)
				_pixels[i] = color
				i += 1
			Wend
		Else
			Local i:Int, j:Int, k:Int = offset

			For i = 0 Until height
				For j = 0 Until width
					_pixels[k] = color
					k += 1
				Next
				k += _width - width
			Next
		End If
	End Method

End Class

error: pathspec 'system/flxbitmapdata.monkey' did not match any file(s) known to git


Added Matrix3D module.

Added Matrix3D module.


Create maniacTween.monkey

Create maniacTween.monkey

#Rem monkeydoc Module maniac.maniacTween
	This File provides some tweening-effect stuff.

#End
Import mojo

Import maniacDebug

'--------------------------------------------------------------------------------------------------
'Tween module contents
Const PI := 3.14159265

'---------------
'base classes

Class Tween
    Global Linear:TweenEquationCall = New TweenEquationCallLinear
    Global Back:TweenEquation = New TweenEquationBack
    Global Bounce:TweenEquation = New TweenEquationBounce
    Global Circ:TweenEquation = New TweenEquationCirc
    Global Cubic:TweenEquation = New TweenEquationCubic
    Global Elastic:TweenEquation = New TweenEquationElastic
    Global Expo:TweenEquation = New TweenEquationExpo
    Global Quad:TweenEquation = New TweenEquationQuad
    Global Quart:TweenEquation = New TweenEquationQuart
    Global Quint:TweenEquation = New TweenEquationQuint
    Global Sine:TweenEquation = New TweenEquationSine

    Field equation:TweenEquationCall

    Field start:Float
    Field change:Float
    Field current:Float

    Field isActive := False
    Field isLooping := False
    Field isYoYo := False

    Field duration:Int
    Field loopCount:Int
    Field timeStart:Int
    Field timeCurrent:Int
    Field timePrevious:Int

    ' --- constructors ---
    Method New(equation:TweenEquationCall,startValue:Float,endValue:Float,duration:Int)
    	Maniac_Debug.addRegisteredObject()
        SetEquation(equation)
        SetDuration(duration)
        SetValue(startValue,endValue)
    End

    ' --- private methods ---
    Private
    Method UpdateValue()
        current = equation.Call(timeCurrent,start,change,duration)
    End
    Public

    ' --- value methods ---
    Method Value:Float()
        Return current
    End

    ' --- setup methods methods ---
    Method SetEquation(equation:TweenEquationCall)
        Self.equation = equation
    End

    Method SetDuration(duration:Int)
        Self.duration = duration
    End

    Method SetValue(startValue:Float,endValue:Float)
        start = startValue
        change = endValue - startValue
    End

    Method SetYoYo(flag:Bool)
        isYoYo = flag
    End

    Method SetLooping(flag:Bool)
        isLooping = flag
    End

    ' --- control methods ---
    Method Start()
        ' --- this will re-start the tween ---
        Rewind()
        isActive = True
        loopCount = 0
    End

    Method Stop()
        ' --- stop the tween from updating ---
        isActive = False
    End

    Method Resume()
        ' --- resume the tween from a paused state ---
        isActive = True

        'update the start timer!

    End

    Method Rewind()
        ' --- put the tween at the start of its tween ---
        timeCurrent = 0
        timeStart = Millisecs()
        UpdateValue()
    End

    Method FastForward()
        ' --- set the tween at the end ---
        timeCurrent = duration
        UpdateValue()
        Stop()
    End

    Method ContinueTo(endValue:Float,duration:Int=0)
        ' --- change the end target for teh value
        start = current
        SetValue(start,endValue)

        If isActive
            'isActive so need to continue operation
            If duration = 0
                'no duration specified so use previous duration!
                Self.duration = duration - timeCurrent
            Else
                'override duration
                Self.duration = duration
            Endif

            timeStart = Millisecs()
            timeCurrent = 0

            If duration <= 0
                duration = 0
                Stop()
            Endif
        Else
            If duration > 0 SetDuration(duration)
            Start()
        Endif
    End

    Method YoYo()
        ContinueTo(start)
    End

    ' --- class methods ---
    Method Update()
    	Maniac_Debug.addCalc()
        If isActive
            'update the current time!
            timePrevious = timeCurrent
            Local time := Millisecs() - timeStart

            If time > duration
                'time is beyond length of tween
                If isLooping Or isYoYo
                    'increase the loop count
                    loopCount += 1

                    'look at yoyoing the values
                    If isYoYo
                        timeCurrent = duration
                        current = start + change

                        If isLooping Or loopCount <= 1
                            ContinueTo(start,duration)
                        Else
                            Stop()
                        Endif
                    Else
                        'wrap around the tween to the start
                        timeCurrent = 0'
                        timeStart = Millisecs()
                    Endif
                Else
                    'set the tween to the end
                    timeCurrent = duration
                    current = start + change
                    Stop()
                Endif
            Else If time < 0
                'time is before the start of the tween
                timeCurrent = 0
                timeStart = Millisecs()
                UpdateValue()
            Else
                'time is within the tween
                timeCurrent = time
                UpdateValue()
            Endif
        Endif
    End
End

Class TweenEquation
    ' --- really just a grouping class for user access ---
    Field EaseIn:TweenEquationCall
    Field EaseOut:TweenEquationCall
    Field EaseInOut:TweenEquationCall
End

Class TweenEquationCall
    ' --- base class to provide a call function pointer work around ---
    Method Call:Float(t:Float,b:Float,c:Float,d:Float) Abstract
End

'---------------
'Linear
Class TweenEquationCallLinear Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        Return c*t/d + b
    End
End

'---------------
'Sine
Class TweenEquationSine Extends TweenEquation
    Method New()
        EaseIn = New TweenEquationCallSineEaseIn
        EaseOut = New TweenEquationCallSineEaseOut
        EaseInOut = New TweenEquationCallSineEaseInOut
    End
End

Class TweenEquationCallSineEaseIn Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        'return -c * Cos(t / d * (PI / 2)) + c + b
        Return -c * Cos((t / d * (PI / 2)) * 57.2957795) + c + b
    End
End

Class TweenEquationCallSineEaseOut Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        Return c * Sin((t/d * (PI/2)) * 57.2957795) + b
    End
End

Class TweenEquationCallSineEaseInOut Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        Return -c/2 * (Cos((PI*t/d) * 57.2957795) - 1) + b
    End
End

'---------------
'Back
Class TweenEquationBack Extends TweenEquation
    Method New()
        EaseIn = New TweenEquationCallBackEaseIn
        EaseOut = New TweenEquationCallBackEaseOut
        EaseInOut = New TweenEquationCallBackEaseInOut
    End
End

Class TweenEquationCallBackEaseIn Extends TweenEquationCall
    Field s := 1.70158
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t /= d
		Return c * t * t * ((s + 1) * t - s) + b
    End
End

Class TweenEquationCallBackEaseOut Extends TweenEquationCall
    Field s := 1.70158
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t = t / d - 1
		Return c * (t * t * ((s + 1) * t + s) + 1) + b
    End
End

Class TweenEquationCallBackEaseInOut Extends TweenEquationCall
    Field s := 1.70158
    Field s2:Float
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        s2 = s
        t /= d / 2
        s2 *= 1.525
		If t < 1
            Return c / 2 * (t * t *((s2+1) * t - s2)) + b
        Endif
		t -= 2
		Return c / 2 * (t * t * ((s2 + 1) * t + s2) + 2) + b
    End
End

'---------------
'Elastic
Class TweenEquationElastic Extends TweenEquation
    Method New()
        EaseIn = New TweenEquationCallElasticEaseIn
        EaseOut = New TweenEquationCallElasticEaseOut
        EaseInOut = New TweenEquationCallElasticEaseInOut
    End
End

Class TweenEquationCallElasticEaseIn Extends TweenEquationCall
    Field p:Float
    Field a:Float
    Field s:Float

    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
		If t = 0 Return b
		t /= d
        If t = 1 Return b+c
        p = d *  0.3
		a = c
        s = p / 4
        t -= 1
		Return -(a * Pow(2,10 * (t)) * Sin(((t * d - s) * (2 * PI) / p) * 57.2957795)) + b
    End
End

Class TweenEquationCallElasticEaseOut Extends TweenEquationCall
    Field p:Float
    Field a:Float
    Field s:Float

    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
		If t = 0 Return b
		t /= d
        If t = 1 Return b+c
        p = d * 0.3
		a = c
        s = p / 4
		Return (a * Pow(2,-10 * t) * Sin(((t * d - s) * (2 * PI) / p) * 57.2957795) + c + b)
    End
End

Class TweenEquationCallElasticEaseInOut Extends TweenEquationCall
    Field p:Float
    Field a:Float
    Field s:Float

    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
		If t = 0 Return b
		t /= d / 2
        If t = 2 Return b+c
        p = d * (0.3 * 1.5)
		a = c
        s = p / 4
		If t < 1
            t -= 1
            Return -0.5 * (a * Pow(2,10 * t) * Sin(((t * d - s) * (2 * PI) / p) * 57.2957795)) + b
        Endif
        t -= 1
		Return a * Pow(2,-10 * t) * Sin(((t * d - s) * (2 * PI) / p) * 57.2957795) * 0.5 + c + b
    End
End

'---------------
'Bounce
Class TweenEquationBounce Extends TweenEquation
    Method New()
        EaseIn = New TweenEquationCallBounceEaseIn
        EaseOut = New TweenEquationCallBounceEaseOut
        EaseInOut = New TweenEquationCallBounceEaseInOut
    End
End

Class TweenEquationCallBounceEaseIn Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t = (d-t) / d
		If t < 0.3636363
			Return c - (c * (7.5625 * t * t)) + b
		Else If t < 0.7272727
            t -= 0.5454545
			Return c - (c * (7.5625 * t * t + 0.75)) + b
		Else If t < 0.9090909
            t -= 0.8181818
			Return c - (c * (7.5625 * t * t + 0.9375)) + b
		Else
            t -= 0.9636363
			Return c - (c * (7.5625 * t * t + 0.984375)) + b
        Endif
    End
End

Class TweenEquationCallBounceEaseOut Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t /= d
		If t < 0.3636363
			Return c *(7.5625 * t * t) + b
		Else If t < 0.7272727
            t -= 0.5454545
			Return c * (7.5625 * t * t + 0.75) + b
		Else If t < 0.9090909
            t -= 0.8181818
			Return c * (7.5625 * t * t + 0.9375) + b
		Else
            t -= 0.9636363
			Return c * (7.5625 * t * t + 0.984375) + b
        Endif
    End
End

Class TweenEquationCallBounceEaseInOut Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
		If t < d/2
            t = (d - t * 2) / d
    		If t < 0.3636363
    			Return (c - (c * (7.5625 * t * t))) * 0.5 + b
    		Else If t < 0.7272727
                t -= 0.5454545
    			Return (c - (c * (7.5625 * t * t + 0.75))) * 0.5 + b
    		Else If t < 0.9090909
                t -= 0.8181818
    			Return (c - (c * (7.5625 * t * t + 0.9375))) * 0.5 + b
    		Else
                t -= 0.9636363
    			Return (c - (c * (7.5625 * t * t + 0.984375))) * 0.5 + b
            Endif
        Else
            t = (t * 2 - d) / d
    		If t < 0.3636363
    			Return (c *(7.5625 * t * t)) * 0.5 + c * 0.5 + b
    		Else If t < 0.7272727
                t -= 0.5454545
    			Return (c * (7.5625 * t * t + 0.75)) * 0.5 + c * 0.5 + b
    		Else If t < 0.9090909
                t -= 0.8181818
    			Return (c * (7.5625 * t * t + 0.9375)) * 0.5 + c * 0.5 + b
    		Else
                t -= 0.9636363
    			Return (c * (7.5625 * t * t + 0.984375)) * 0.5 + c * 0.5 + b
            Endif
        Endif
    End
End

'---------------
'Circ
Class TweenEquationCirc Extends TweenEquation
    Method New()
        EaseIn = New TweenEquationCallCircEaseIn
        EaseOut = New TweenEquationCallCircEaseOut
        EaseInOut = New TweenEquationCallCircEaseInOut
    End
End

Class TweenEquationCallCircEaseIn Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t /= d
        Return -c * (Sqrt(1 - t * t) - 1) + b
    End
End

Class TweenEquationCallCircEaseOut Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t = t / d - 1
        Return c * Sqrt(1 - t*t) + b
    End
End

Class TweenEquationCallCircEaseInOut Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t /= d / 2
		If t < 1 Return -c / 2 * (Sqrt(1 - t * t) - 1) + b
		t -= 2
		Return c / 2 * (Sqrt(1 - t * t) + 1) + b
    End
End

'---------------
'Cubic
Class TweenEquationCubic Extends TweenEquation
    Method New()
        EaseIn = New TweenEquationCallCubicEaseIn
        EaseOut = New TweenEquationCallCubicEaseOut
        EaseInOut = New TweenEquationCallCubicEaseInOut
    End
End

Class TweenEquationCallCubicEaseIn Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t /= d
        Return c * t * t * t + b
    End
End

Class TweenEquationCallCubicEaseOut Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t = t / d - 1
        Return c * (t * t * t + 1) + b
    End
End

Class TweenEquationCallCubicEaseInOut Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t /= d / 2
		If t < 1 Return c / 2 * t * t * t + b
		t -= 2
		Return c / 2 *(t * t * t + 2) + b
    End
End

'---------------
'Expo
Class TweenEquationExpo Extends TweenEquation
    Method New()
        EaseIn = New TweenEquationCallExpoEaseIn
        EaseOut = New TweenEquationCallExpoEaseOut
        EaseInOut = New TweenEquationCallExpoEaseInOut
    End
End

Class TweenEquationCallExpoEaseIn Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        If t = 0 Return b
        Return c * Pow(2,10 * (t / d - 1)) + b
    End
End

Class TweenEquationCallExpoEaseOut Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        If t = d Return b + c
        Return c * (-Pow(2,-10 * t / d) + 1) + b
    End
End

Class TweenEquationCallExpoEaseInOut Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
		If t =0 Return b
		If t = d Return b + c
		t /= d / 2
		If t < 1 Return c / 2 * Pow(2,10 * (t - 1)) + b
		t -= 1
		Return c / 2 * (-Pow(2,-10 * t) + 2) + b
    End
End

'---------------
'Quad
Class TweenEquationQuad Extends TweenEquation
    Method New()
        EaseIn = New TweenEquationCallQuadEaseIn
        EaseOut = New TweenEquationCallQuadEaseOut
        EaseInOut = New TweenEquationCallQuadEaseInOut
    End
End

Class TweenEquationCallQuadEaseIn Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t /= d
        Return c * t * t + b
    End
End

Class TweenEquationCallQuadEaseOut Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t /= d
        Return -c * t * (t - 2) + b
    End
End

Class TweenEquationCallQuadEaseInOut Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t /= d / 2
		If t < 1 Return c / 2 * t * t + b
		t -= 1
		Return -c / 2 * (t * (t - 2) - 1) + b
    End
End

'---------------
'Quart
Class TweenEquationQuart Extends TweenEquation
    Method New()
        EaseIn = New TweenEquationCallQuartEaseIn
        EaseOut = New TweenEquationCallQuartEaseOut
        EaseInOut = New TweenEquationCallQuartEaseInOut
    End
End

Class TweenEquationCallQuartEaseIn Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t /= d
        Return c * t * t * t * t + b
    End
End

Class TweenEquationCallQuartEaseOut Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t = t / d-1
        Return -c * (t * t * t * t - 1) + b
    End
End

Class TweenEquationCallQuartEaseInOut Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t /= d / 2
		If t < 1 Return c / 2 * t * t * t * t + b
        t -= 2
		Return -c / 2 * (t * t * t * t - 2) + b
    End
End

'---------------
'Quint
Class TweenEquationQuint Extends TweenEquation
    Method New()
        EaseIn = New TweenEquationCallQuintEaseIn
        EaseOut = New TweenEquationCallQuintEaseOut
        EaseInOut = New TweenEquationCallQuintEaseInOut
    End
End

Class TweenEquationCallQuintEaseIn Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t /= d
        Return c * t * t * t * t * t + b
    End
End

Class TweenEquationCallQuintEaseOut Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t = t / d - 1
        Return c * (t * t * t * t * t + 1) + b
    End
End

Class TweenEquationCallQuintEaseInOut Extends TweenEquationCall
    Method Call:Float(t:Float,b:Float,c:Float,d:Float)
        t /= d / 2
		If t < 1 Return c / 2 * t * t * t * t * t + b
        t -= 2
		Return c / 2 * (t * t * t * t * t + 2) + b
    End
End

error: pathspec 'maniac/maniacTween.monkey' did not match any file(s) known to git


Array utilities, making use of Monkey's new generics reimplementation.

' Example:
' Arrays<Int>.Join([1,2,3], [4,5]) returns a new array [1,2,3,4,5]
' Arrays<String>.Fill(["a","b","c"], "d") fills the existing array and returns it ["d","d","d"] (it doesn't create a new array)
' Arrays<Int>.Slice([1,3,5,7,9], 1, 3) returns a new array [3,5,7]
' Arrays<Float>.Copy([1.0,2.5,3.0]) returns a new array with the same contents [1.0,2.5,3.0]
' Join accepts up to 10 arrays.  Unused parameters are assumed to be empty arrays.
Class Arrays<T>
	Function Join:T[](arr1:T[], arr2:T[], arr3:T[]=[], arr4:T[]=[], arr5:T[]=[], arr6:T[]=[], arr7:T[]=[], arr8:T[]=[], arr9:T[]=[], arr10:T[]=[])
		Local rv:T[] = New T[arr1.Length + arr2.Length + arr3.Length + arr4.Length + arr5.Length + arr6.Length + arr7.Length + arr8.Length + arr9.Length + arr10.Length]
		Local ptr:Int = 0
		If arr1.Length > 0 Then
			For Local i:Int = 0 Until arr1.Length
				rv[i] = arr1[i]
			Next
			ptr += arr1.Length
		End
		If arr2.Length > 0 Then
			For Local i:Int = 0 Until arr2.Length
				rv[i+ptr] = arr2[i]
			Next
			ptr += arr2.Length
		End
		If arr3.Length > 0 Then
			For Local i:Int = 0 Until arr3.Length
				rv[i+ptr] = arr3[i]
			Next
			ptr += arr3.Length
		End
		If arr4.Length > 0 Then
			For Local i:Int = 0 Until arr4.Length
				rv[i+ptr] = arr4[i]
			Next
			ptr += arr4.Length
		End
		If arr5.Length > 0 Then
			For Local i:Int = 0 Until arr5.Length
				rv[i+ptr] = arr5[i]
			Next
			ptr += arr5.Length
		End
		If arr6.Length > 0 Then
			For Local i:Int = 0 Until arr6.Length
				rv[i+ptr] = arr6[i]
			Next
			ptr += arr6.Length
		End
		If arr7.Length > 0 Then
			For Local i:Int = 0 Until arr7.Length
				rv[i+ptr] = arr7[i]
			Next
			ptr += arr7.Length
		End
		If arr8.Length > 0 Then
			For Local i:Int = 0 Until arr8.Length
				rv[i+ptr] = arr8[i]
			Next
			ptr += arr8.Length
		End
		If arr9.Length > 0 Then
			For Local i:Int = 0 Until arr9.Length
				rv[i+ptr] = arr9[i]
			Next
			ptr += arr9.Length
		End
		If arr10.Length > 0 Then
			For Local i:Int = 0 Until arr10.Length
				rv[i+ptr] = arr10[i]
			Next
			ptr += arr10.Length
		End
		Return rv
	End

	Function Fill:T[](arr:T[], val:T)
		For Local i:Int = 0 Until arr.Length
			arr[i] = val
		Next
		Return arr
	End

	Function Copy:T[](arr:T[])
		Local rv:T[] = New T[arr.Length]
		For Local i:Int = 0 Until arr.Length
			rv[i] = arr[i]
		Next
		Return rv
	End

	Function Slice:T[](arr:T[], start:Int, length:Int)
		Local rv:T[] = New T[length]
		For Local i:Int = 0 Until length
			rv[i] = arr[start+i]
		Next
		Return rv
	End
End

error: pathspec 'src/diddy/arrays.monkey' did not match any file(s) known to git


Added FlxSignals helper class

Added FlxSignals helper class

Strict

Import reflection
Import system.signals.flxsignal

Class FlxSignals

Private
	Field _signals:StringMap<FlxSignal>

	Field _methodSlots:List<FlxMethodSlot>

Public
	Method New()
		_signals = New StringMap<FlxSignal>()
		_methodSlots = New List<FlxMethodSlot>()
	End Method

	Method Connect:Void(signal:String, listener:FlxSignalListener)
		GetSignal(signal).RegisterListener(listener)
	End Method

	Method Connect:Void(signal:String, listener:FlxSignalListener, instant:Bool)
		GetSignal(signal).RegisterListener(listener, instant)
	End Method

	Method Connect:Void(signal:String, listener:FlxSignalListener, instant:Bool, priority:Int)
		GetSignal(signal).RegisterListener(listener, instant, priority)
	End Method

	Method Connect:Void(signal:String, methodName:String, context:Object)
		Connect(signal, GetMethodSlot(methodName, context))
	End Method

	Method Connect:Void(signal:String, methodName:String, context:Object, instant:Bool)
		Connect(signal, GetMethodSlot(methodName, context), instant)
	End Method

	Method Connect:Void(signal:String, methodName:String, context:Object, instant:Bool, priority:Int)
		Connect(signal, GetMethodSlot(methodName, context), instant, priority)
	End Method

	Method Emit:Void(signal:String, data:Object = Null)
		GetSignal(signal).Emit(data)
	End Method

Private
	Method GetSignal:FlxSignal(signal:String)
		Local s:FlxSignal = _signals.Get(signal)

		If (s = Null) Then
			s = New FlxSignal()
			_signals.Add(signal, s)
		End If

		Return s
	End Method

	Method GetMethodSlot:FlxMethodSlot(methodName:String, context:Object)
		Local classInfo:ClassInfo = GetClass(context)

		If (classInfo <> Null) Then
			Local methodInfo:MethodInfo = classInfo.GetMethod(methodName,[])

			If (methodInfo <> Null) Then
				Local node:list.Node<FlxMethodSlot> = _methodSlots.FirstNode()

				While (node <> Null)
					If (node.Value()._method = methodInfo And node.Value()._context = context) Then
						Return node.Value()
					End If

					node = node.NextNode()
				Wend

				Return _methodSlots.AddLast(New FlxMethodSlot(context, methodInfo)).Value()
			End If
		End If

		Return Null
	End Method

End Class

Private

Class FlxMethodSlot Implements FlxSignalListener

Private
	Field _context:Object

	Field _method:MethodInfo

Public
	Method New(context:Object, methodInfo:MethodInfo)
		_context = context
		_method = methodInfo
	End Method

	Method OnSignalEmitted:Void(signal:FlxSignal, data:Object)
		_method.Invoke(_context,[])
	End Method

End Class

error: pathspec 'flxsignals.monkey' did not match any file(s) known to git