ParentalGate added

ParentalGate added

Strict

Private

Import bono

Public

Interface ParentalGateCallback
    Method OnParentalGate:Void()
End

Class ParentalGate Implements AlertCallback
    Private

    Const DISABLED:Int = -1
    Global instance:ParentalGate
    Field callback:ParentalGateCallback
    Field rightIndex := DISABLED

    Public

    Function Show:Void(cb:ParentalGateCallback)
        If Target.IS_IOS
            Shared().callback = cb
            Shared().ShowAlert()
        Else
            cb.OnParentalGate()
        End
    End

    Method OnAlertCallback:Void(index:Int, title:String)
        If rightIndex = DISABLED Then Return
        If (index > 0) And (index = rightIndex)
            callback.OnParentalGate()
        End
        rightIndex = DISABLED
    End

    Private

    Function Shared:ParentalGate()
        If Not instance Then instance = New ParentalGate()
        Return instance
    End

    Method ShowAlert:Void()
        Local a:Int = Floor(Rnd() * 4) + 1
        Local b:Int = Floor(Rnd() * 4) + 1
        Local c:Int = a + b
        rightIndex = 1

        Local w:Int = Floor(Rnd() * 9) + 1
        While (w = c)
            w = Floor(Rnd() * 9) + 1
        End

        If (Rnd() > 0.5)
            Local tmp := c
            c = w
            w = tmp
            rightIndex = 2
        End

        If Device.GetLanguage() = "de"
            Device.ShowAlert(
                "Kindersicherung",
                a + " + " + b + " = ?",
                ["Abbrechen", c, w],
                Self)
        Else
            Device.ShowAlert(
                "Are You An Adult?",
                a + " + " + b + " = ?",
                ["Cancel", c, w],
                Self)
        End
    End
End

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


First revision.

First revision.

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

Strict

Const ASSERT_MESSAGE$ = "Assertion failed!"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


Missing FlxMusic files added

Missing FlxMusic files added

Strict

Import mojo.audio

Import flxsound

Class FlxMusic Extends FlxSound

Private
	Field _filename:String

Public
	Method Kill:Void()
		Super.Kill()
		Stop()
	End Method

	Method Load:FlxMusic(music:String, looped:Bool = False, autoDestroy:Bool = True)
		Stop()
		_CreateSound()
		_filename = music
		_looped = looped
		_UpdateTransform()
		exists = True
		Return Self
	End Method

	Method Play:Void(forceRestart:Bool)
		If (forceRestart) Then
			Local oldAutoDestroy:Bool = autoDestroy
			autoDestroy = False
			Stop()
			autoDestroy = oldAutoDestroy
		End If

		_UpdateTransform()

		If (Not _paused) Then
			PlayMusic(_filename, _looped)
		Else
			ResumeMusic()
		End If

		active = True
		_paused = False
	End Method

	Method Resume:Void()
		If (Not _paused) Return

		ResumeMusic()
		_paused = False
		active = True
	End Method

	Method Pause:Void()
		PauseMusic()
		_paused = True
		active = False
	End Method

	Method Stop:Void()
		_paused = False
		active = False

		StopMusic()

		If (autoDestroy) Then
			Destroy()
		End If
	End Method

	Method ToString:String()
		Return "FlxMusic"
	End Method

	Method _SetTransform:Void(volume:Float, pan:Float)
		SetMusicVolume(_channel, volume)
	End Method

End Class

error: pathspec 'flxmusic.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.

#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


Initial revision.

Initial revision.

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

#rem
[March 11 2011]
 - added support for xml standard single and double quotes. Single quote must end with single and double with double
 - added support for comments <!-- comment -->
 - added destructor .Free() to clean up xml data (needs to be called manually)
 - tweaked parser to remove some unnecessary steps

 Included with permission from Jonathan Pittock.
#end

Class ConfigError
    Field message:String
    Field context:String
    Field line:Int
    Field column:Int
    Field data:String

    Method New(message:String,context:String="",data:String="",line:Int=0,column:Int=0)
        Self.message = message
        Self.context = context
        Self.data = data
        Self.line = line
        Self.column = column
    End

    Method ToString:String()
        Local error := ""
        If context.Length() > 0
            error += "Error In '"+context+"': "+message
        Else
            error += "Error: "+message
        Endif
        If line > 0
            error += " (line:"+line+")"
            If column > 0 error += " (column: "+column+")"
        Endif
        If data.Length() > 0 error += "~nData: "+data
        Return error
    End
End

Class ConfigNode
	Field name:String
	Field value:String
	Field parent:ConfigNode
	Field attributes:List<ConfigAttribute>
	Field children:List<ConfigNode>
	Field line:Int
	Field column:Int
	Field scriptOffset:Int

	Method New(name:String)
		Self.name = name
	End

	Method Free:Void()
		' --- free resources ---
		name = ""
		value = ""
		parent = Null
		line = 0
		column = 0
		scriptOffset = 0

		'free attributes
		If attributes
			For Local attribute := EachIn attributes
				attribute.Free()
			Next
			attributes.Clear()
		EndIf

		'free children
		If children
			For Local node := EachIn children
				node.Free()
			Next
			children.Clear()
		EndIf
	End

	Method ToString:String()
		' --- create debuggable print output ---
		Local build := "<"+name
		If attributes
			For Local attribute := Eachin attributes
				build += " "+attribute.name+"=~q"+attribute.value+"~q"
			Next
		Endif
		build += ">"
		Return build
	End

	Method FindValue:String(path:String,defaultValue:String="")
		Local configNode := FindNodeByPath(path)
		If configNode Return configNode.GetValue()
	End

	Method FindNodeByPath:ConfigNode(path:String)
		' --- returns first node with given path ---
		'return self if no path is given
		If path.Length() = 0 Return Self

		'skip if no children
		If children = Null Return Null

		'split the path into bits
		Local pathParts := path.ToLower().Split("/")
		Local nodeFound := False
		Local pointerNode:ConfigNode = Self

		'scan the path
		For Local pathIndex := 0 Until pathParts.Length()
			'validate all bits of the path
			If pathParts[pathIndex].Length() = 0 Return Null

			'check children of this pointer
			nodeFound = False
			If pointerNode.children
				For Local childNode := Eachin pointerNode.children
					If childNode.name = pathParts[pathIndex]
						pointerNode = childNode
						nodeFound = True
						Exit
					Endif
				Next
			Endif

			'check for node not found
			If nodeFound = False Return Null
		Next

		'return
		Return pointerNode
	End

	Method FindNodesByPath:List<ConfigNode>(path:String)
		' --- this will find a path within the children ---
		Local pointerNodes:List<ConfigNode>

		'return self if no path is given
		If path.Length() = 0
			pointerNodes = New List<ConfigNode>
			pointerNodes.AddLast(Self)
			Return pointerNodes
		Endif

		'skip if no children
		If children = Null Return Null

		'split the path into bits
		Local pathParts := path.ToLower().Split("/")
		pointerNodes = New List<ConfigNode>
		Local newPointerNodes := New List<ConfigNode>

		'add self as root
		pointerNodes.AddLast(Self)

		'scan the path
		For Local pathIndex := 0 Until pathParts.Length()
			'validate all bits of the path
			If pathParts[pathIndex].Length() = 0 Return Null

			'scan children of each pointer
			For Local pointerNode := Eachin pointerNodes
				'check children of this pointer
				If pointerNode.children
					For Local childNode := Eachin pointerNode.children
						If childNode.name = pathParts[pathIndex] newPointerNodes.AddLast(childNode)
					Next
				Endif
			Next
			pointerNodes.Clear()

			'add new pointers to scan
			For Local pointerNode := Eachin newPointerNodes
				pointerNodes.AddLast(pointerNode)
			Next
			newPointerNodes.Clear()
		Next

		'return
		If pointerNodes.IsEmpty() Return Null
		Return pointerNodes
	End

	Method FindNodesByName:List<ConfigNode>(name:String)
		' --- find all nodes of a given type ---
		If children = Null Or children.IsEmpty() Return Null

		Local returnNodes := New List<ConfigNode>
		Local stackNodes := New List<ConfigNode>
		Local stackNode:ConfigNode

		stackNodes.AddLast(Self)

		While stackNodes.IsEmpty() = False
			stackNode = stackNodes.RemoveLast()
			For Local scanNode := Eachin stackNode.children
				If scanNode.name = name returnNodes.AddLast(scanNode)
				If scanNode.children And scanNode.children.IsEmpty() = False stackNodes.AddLast(scanNode)
			Next
		Wend

		If returnNodes.IsEmpty() Return Null
		Return returnNodes
	End

	Method AddChild(childNode:ConfigNode)
		' --- add child to this node ---
		'set the parent of the child being added
		childNode.parent = Self

		'create the children list
		If children = Null children = New List<ConfigNode>

		'add the child
		children.AddLast(childNode)
	End

	Method GetAttribute:String(name:String,defaultValue:String="")
		' --- get an attribute value ---
		Local attribute := GetConfigAttribute(name)
		If attribute = Null Return defaultValue
		Return attribute.value
	End

	Method GetAttributes:List<ConfigAttribute>()
		' --- return all of thr attributes ---
		Return attributes
	End

	Method GetValue:String()
		Return value
	End

	Method GetName:String()
		Return name
	End

	Method GetChildren:List<ConfigNode>()
		Return children
	End

	Method GetConfigAttribute:ConfigAttribute(name:String)
		' --- find a property ---
		'make sure there are attributes
		If attributes = Null Return Null

		'fix casing of attribute
		name = name.ToLower()

		'search for matching attribute
		For Local attribute := Eachin attributes
			If name = attribute.name Return attribute
		Next

		Return Null
	End

	Method SetAttribute(name:String,value:String)
		' --- add a new property to this node ---
		'create properties list for first time
		If attributes = Null attributes = New List<ConfigAttribute>

		'find existing property
		Local attribute := GetConfigAttribute(name)

		'add / update attribute
		If attribute
			'update (overwrite)
			attribute.SetValue(value)
		Else
			'add
			attributes.AddLast(New ConfigAttribute(name,value))
		Endif
	End

	Method Remove()
		If parent parent.children.Remove(Self)
	End
End

Class ConfigAttribute
	Field name:String
	Field value:String
	Field segments:String[]

	Method New(name:String,value:String)
		' --- setup new attribute ---
		SetName(name.ToLower())
		SetValue(value)
	End

	Method Free:Void()
		' --- free resources ---
		name = ""
		value = ""
		segments = []
	End

	Private
	Method UpdateValue()
		Local length = segments.Length()

		If length = 0
			value = ""
			Return
		Endif

		If length = 1
			value = segments[0]
			Return
		Endif

		Local build := ""
		value = ""
		For Local index := 0 Until length
			value += segments[index]
		Next
	End
	Public

	Method IsSegmented:Bool()
		Return segments.Length() > 1
	End

	Method SetName(name:String)
		Self.name = name
	End

	Method GetSegments:String[]()
		Return segments
	End

	Method GetName:String()
		Return name
	End

	Method SetValue(value:String)
		segments = [value]
		UpdateValue()
	End

	Method AddSegment(segment:String)
		Local index := segments.Length()
		segments = segments.Resize(index+1)
		segments[index] = segment
		UpdateValue()
	End

	Method GetBoolString:String()
		If value = "1" Or value = "true"
			Return "1"
		Else
			Return "0"
		Endif
	End

	Method GetIntString:String()
		Return Int(value)
	End

	Method GetFloatString:String()
		Return Float(value)
	End

	Method GetInt:Int()
		Return Int(value)
	End

	Method GetFloat:Float()
		Return Float(value)
	End

	Method GetBool:Bool()
		If value = "1" Or value = "true" Return True
	End

	Method GetString:String()
		Return value
	End

	Method IsBool:Bool()
		'returns true if the value is a valid true/false definition
		Return value = "1" Or value = "0" Or value = "true" Or value = "false"
	End

	Method IsInt:Bool()
		' --- make sure this is a valid int ---
		Local asc:Int
		If value = "-" Return False
		For Local index := 0 Until value.Length()
			asc = value[index]
			If asc <> 45
				If asc < 48 Or value[index] > 57 Return False
			Else
				If index > 0 Return False
			Endif
		Next
		Return True
	End

	Method IsFloat:Bool()
		' --- make sure this is a valid float ---
		Local asc:Int
		Local countPeriod := 0
		If value = "-" Return False
		For Local index := 0 Until value.Length()
			asc = value[index]
			If asc <> 45
				If asc = 46
					If countPeriod > 0 Return False
					countPeriod += 1
				Else
					If (asc < 48 Or value[index] > 57) Return False
				Endif
			Else
				If index > 0 Return False
			Endif
		Next
		Return True
	End
End

Class Config Extends ConfigNode
	Field path:String
	Field script:String
	Field error:ConfigError

	Private
	Method Parse:Bool(scriptRaw:String)
		' --- parse the string and fill the data objects ---
		'setup root item
		name = "root"

		'fix the raw script
		script = scriptRaw.Replace("~r~n","~n")

		'setup the stack
		Local stack := New List<ConfigNode>
		stack.AddLast(Self)

		'setup some parsing values (quite a few)
		Local stackTag:ConfigNode

		Local scriptLength = script.Length()
		Local scriptIndex := 0

		Local findTagQuote := -1
		Local findTagStart := -1
		Local findTagStartSize := 0
		Local findTagTemp := -1
		Local findTagEnd := -1
		Local findTagEndSize := 0
		Local findTag:ConfigNode
		Local findAttribute:ConfigAttribute
		Local findQuoteCharacter:Int
		Local findTagLine := 0
		Local findTagColumn := 0
		Local findName := ""
		Local findOperator := ""
		Local findSegment := ""
		Local findWhitespace := ""
		Local findLine := 1
		Local findLineStart := 0
		Local findHasPair := False
		Local findHasClose := False
		Local findHasFirst := False
		Local findHasStart := False
		Local findHasName := False
		Local findHasNameEnd := False
		Local findHasEquals := False
		Local findHasValue := False
		Local findHasComment := False
		Local findHasQuotes := False
		Local findHasEnd := False
		Local findHasSegment := False
		Local findHasSegmentEnd := False
		Local findHasOperator := False

		'parse the script
		While scriptIndex < scriptLength-1
			'parse looking for a complete bracket! (also skip comments)
			For Local findIndex := scriptIndex Until scriptLength
				'test for new line
				If script[findIndex] = 10
					findLine += 1
					findLineStart = findIndex + 1
				EndIf

				'not in comment
				If findHasStart = False
					'check to see if in comment
					If findHasComment = False
						'looking for <
						If script[findIndex] = 60
							'bracket starting
							'check if comment
							If findIndex < scriptLength-4 And script[findIndex..findIndex+4] = "<!--"
								'comment
								findHasComment = True
								findIndex += 3
							Else
								'process looking for start
								If findIndex < scriptLength-1 And script[findIndex+1] = 47
									findHasClose = True
									findTagStartSize = 2
								Else
									findTagStartSize = 1
								EndIf
								findHasStart = True
								findTagStart = findIndex
								findTagLine = findLine
								findTagColumn = (findIndex-findLineStart)+1
							EndIf
						Else
							findWhitespace += String.FromChar(script[findIndex])
						EndIf
					Else
						'in comment look for end of comment
						If script[findIndex] = 45 And findIndex + 3 < scriptLength And script[findIndex..findIndex+3] = "-->"
							findHasComment = False
							findIndex += 2
						EndIf
					EndIf
				Else
					'looking for >
					If findHasQuotes = False
						'not in quotes
						If script[findIndex] = 34
							'quote (double)
							findHasQuotes = True
							findQuoteCharacter = 34
						Else If script[findIndex] = 39
							'quote (single)
							findHasQuotes = True
							findQuoteCharacter = 39
						Else If script[findIndex] = 60
							'illegal open bracket
							Return SetError("unexpected opening bracket",findLine,(findIndex-findLineStart)+1)
						Else If script[findIndex] = 62
							'bracket ending
							If findIndex > 0 And script[findIndex-1] = 47
								findTagEndSize = 2
								findHasClose = True
								findTagEnd = findIndex - 1
							Else
								findHasPair = True
								findTagEndSize = 1
								findTagEnd = findIndex
							EndIf
							findHasEnd = True
							Exit
						EndIf
					Else
						'in quotes, can we get out please?
						If script[findIndex] = findQuoteCharacter findHasQuotes = False
					EndIf
				EndIf
			Next

			'check for errors
			If findHasQuotes Return SetError("expecting ending quote",findLine,scriptLength-findLineStart)
			If findHasStart And findHasEnd = False Return SetError("expecting ending bracket",findLine,scriptLength-findLineStart)

			'perform further parse on tag if found
			If findHasEnd = False
				'there are no more tags to retrieve from the string
				'check to see if any items waiting on the stack (other than root)
				If stack.Count() > 1 Return SetError("unexpected end of file",findLine,scriptLength-findLineStart)

				'dont add white space to root
				'Self.value += script[scriptIndex..scriptLength]

				Exit
			Else
				'reset
				findName = ""
				findOperator = ""
				findSegment = ""
				findHasEnd = False
				findHasName = False
				findHasNameEnd = False
				findHasEquals = False
				findHasValue = False
				findHasQuotes = False
				findHasSegment = False
				findHasSegmentEnd = False
				findHasOperator = False

				'add the white space
				stackTag = stack.Last()
				stackTag.value += findWhitespace'script[scriptIndex..findTagStart]

				'move the script index
				scriptIndex = findTagEnd+findTagEndSize

				'we now have an opening node so parse the node data!
				findTag = New ConfigNode()
				findTag.line = findTagLine
				findTag.column = findTagColumn

				For Local findIndex := findTagStart+findTagStartSize Until findTagEnd
					If findHasName = False
						'scanning for name
						If script[findIndex] = 32
							'space
							If findName findHasNameEnd = True

						Else If script[findIndex] = 10
							'new line
							If findName findHasNameEnd = True
							findLine += 1
							findLineStart = findIndex + 1

						Else If script[findIndex] = 61
							'=
							If findName
								findIndex -= 1
								findHasNameEnd = True
							Else
								Return SetError("expecting tag or attribute name",findLine,(findIndex-findLineStart)+1)
							EndIf

						Else If script[findIndex] = 95 or (script[findIndex] >= 48 and script[findIndex] <= 57) or (script[findIndex] >= 65 and script[findIndex] <= 90) or (script[findIndex] >= 97 and script[findIndex] <= 122)
							'_ a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
							findName += String.FromChar(script[findIndex])

						Else
							'illegal character
							Return SetError("illegal character asc='"+script[findIndex]+"' chr='"+script[findIndex..findIndex+1]+"'",findLine,(findIndex-findLineStart)+1)

						EndIf
					Else
						'check for what to scan for next
						If findHasEquals = False
							'searching for equals so can start the value!
							If script[findIndex] = 32
								'space

							Else If script[findIndex] = 10
								'new line
								findLine += 1
								findLineStart = findIndex + 1

							Else If script[findIndex] = 61
								'=
								findHasEquals = True

							Else If script[findIndex] = 95 or (script[findIndex] >= 48 and script[findIndex] <= 57) or (script[findIndex] >= 65 and script[findIndex] <= 90) or (script[findIndex] >= 97 and script[findIndex] <= 122)
								'_ a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
								'alpha numerics
								findHasEnd = True
								findIndex -= 1

							Else
								'illegal character
								Return SetError("illegal character asc='"+script[findIndex]+"' chr='"+script[findIndex..findIndex+1]+"'",findLine,(findIndex-findLineStart)+1)

							EndIf
						Else
							'scan through the value until an end is found!
							If findHasQuotes = False
								'look to see if there is a waiting segment to continue processing
								If findHasSegment = False
									'value hasn't completed a segment yet
									If script[findIndex] = 32
										'space
										If findSegment
											findHasSegment = True
											findHasSegmentEnd = True
										EndIf

									Else If script[findIndex] = 10
										'new line
										If findSegment
											findHasSegment = True
											findHasSegmentEnd = True
										EndIf

										findLine += 1
										findLineStart = findIndex + 1

									Else If script[findIndex] = 34 Or script[findIndex] = 39
										'"
										'looking for start quote
										If findSegment
											'unexepcted quote
											Return SetError("unexpected opening quote",findLine,(findIndex-findLineStart)+1)
										Else
											'start quotes
											findHasQuotes = True
											findHasValue = True
											findQuoteCharacter = script[findIndex]
										EndIf

									Else If script[findIndex] = 45
										'-
										'looking for negative value or operator
										If findSegment
											'operator
											findHasSegment = True
											findHasSegmentEnd = True
											findHasOperator = True
											findOperator = String.FromChar(script[findIndex])
										Else
											'negative value
											findSegment += String.FromChar(script[findIndex])
											findHasValue = True
										EndIf

									Else If script[findIndex] = 42 or script[findIndex] = 43 or script[findIndex] = 47
										'+
										'looking for (other non -) operators
										If findHasValue = False
											'unexpected oeprator
											Return SetError("unexpected operator asc='"+script[findIndex]+"' chr='"+script[findIndex..findIndex+1]+"'",findLine,(findIndex-findLineStart)+1)
										Else
											'end of value
											findHasSegmentEnd = True
											findHasOperator = True
											findOperator = String.FromChar(script[findIndex])
										EndIf

									Else If script[findIndex] = 36 or script[findIndex] = 46 or script[findIndex] = 95 or (script[findIndex] >= 48 and script[findIndex] <= 57) or (script[findIndex] >= 65 and script[findIndex] <= 90) or (script[findIndex] >= 97 and script[findIndex] <= 122)
										'$ . _ a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
										'looking for unquoted attribute value
										findSegment += String.FromChar(script[findIndex])
										findHasValue = True

									Else
										'ilegal character
										Return SetError("illegal character asc='"+script[findIndex]+"' chr='"+script[findIndex..findIndex+1]+"'",findLine,(findIndex-findLineStart)+1)
									EndIf

								Else
									'value already has segment so need to look for end or operator
									If script[findIndex] = 32
										'space

									Else If script[findIndex] = 10
										'new line
										findLine += 1
										findLineStart = findIndex + 1

									Else If script[findIndex] = 95 or (script[findIndex] >= 48 and script[findIndex] <= 57) or (script[findIndex] >= 65 and script[findIndex] <= 90) or (script[findIndex] >= 97 and script[findIndex] <= 122)
										'_ a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9
										'looking for new attribute so must rescan this character
										findHasSegment = False
										findIndex -= 1
										findHasEnd = True

									Else If script[findIndex] = 42 Or script[findIndex] = 43 or script[findIndex] = 45 or script[findIndex] = 47
										'+ -
										'looking for operators
										findHasSegment = False
										findHasOperator = True
										findOperator = String.FromChar(script[findIndex])

									Else
										Return SetError("illegal character asc='"+script[findIndex]+"' chr='"+script[findIndex..findIndex+1]+"'",findLine,(findIndex-findLineStart)+1)
									EndIf
								EndIf
							Else
								'quotes mode (anything goes) (possibly need to do escape quote character at some point)
								If script[findIndex] = 10
									'new line
									findLine += 1
									findLineStart = findIndex + 1

								Else If script[findIndex] = findQuoteCharacter
									'looking for end of quotes
									findHasSegment = True
									findHasSegmentEnd = True
									findHasQuotes = False
									findQuoteCharacter = 0
								Else
									'any character add to value
									findSegment += String.FromChar(script[findIndex])

								EndIf
							EndIf
						EndIf
					EndIf

					'look for forced end (eol)
					If findIndex = findTagEnd-1
						findHasEnd = True

						If findHasQuotes
							'unclosed "
							Return SetError("exepcting closing quote",findLine,(findIndex-findLineStart)+1)
						Else
							If findHasName = False
								If findName findHasNameEnd = True
							Else
								If findHasEquals = True
									If findHasValue = False And findSegment = ""
										'nothing after =
										Return SetError("expecting attribute value",findLine,(findIndex-findLineStart)+1)
									Else
										If findHasOperator
											'nothing after operator
											Return SetError("unexcpected end of attribute",findLine,(findIndex-findLineStart)+1)
										Else
											If findSegment <> "" findHasSegmentEnd = True
										EndIf
									EndIf
								EndIf
							EndIf
						EndIf
					EndIf

					'look at setting up tag name
					If findHasNameEnd
						'tag name
						If findHasFirst = False
							findHasFirst = True
							findTag.name = findName.ToLower()
						Else
							findHasStart = True
						EndIf

						'say that name is found
						findHasName = True

						'reset
						findHasNameEnd = False
					EndIf

					If findHasName
						'look at adding segment to value
						If findHasSegmentEnd = True
							'look for appending existing attribute
							findAttribute = findTag.GetConfigAttribute(findName)
							If findAttribute = Null
								findTag.SetAttribute(findName,findSegment)
							Else
								findAttribute.AddSegment(findSegment)
							EndIf

							'reset
							findHasSegmentEnd = False
							findSegment = ""
						EndIf

						'look for adding operator to value
						If findHasOperator = True
							'look for appending existing attribute
							findAttribute = findTag.GetConfigAttribute(findName)
							If findAttribute = Null
								findTag.SetAttribute(findName,findOperator)
							Else
								findAttribute.AddSegment(findOperator)
							EndIf

							'reset
							findHasOperator = False
							findOperator = ""
						EndIf
					EndIf

					If findHasEnd
						'reset
						findName = ""
						findOperator = ""
						findSegment = ""
						findHasEnd = False
						findHasName = False
						findHasNameEnd = False
						findHasEquals = False
						findHasValue = False
						findHasQuotes = False
						findHasSegment = False
						findHasSegmentEnd = False
						findHasOperator = False
					EndIf
				Next

				'node is complete - what next
				If findHasClose
					If findHasPair
						'close the node from the stack
						stackTag = stack.RemoveLast()
						If stackTag <> Null
							If stackTag.name = findTag.name
								'close the node and add to parent
								stackTag.parent.AddChild(stackTag)
							Else
								'mis matched node
								Return SetError("open tag name '"+stackTag.name+"' doesn't match closing tag name '"+findTag.name+"'",findTag.line,findTag.column)
							EndIf
						Else
							'error - closing unopened node
							Return SetError("unexpected closing tag '"+findTag.name+"'",findTag.line,findTag.column)
						EndIf
					Else
						'close the node by itself and add to parent!
						findTag.parent = stack.Last()
						findTag.parent.AddChild(findTag)
					EndIf
				Else
					'add the node to the stack!
					'set parent first
					findTag.parent = stack.Last()
					stack.AddLast(findTag)
				EndIf

				'reset flags/values
				findHasStart = False
				findHasClose = False
				findHasPair = False
				findHasFirst = False
				findWhitespace = ""
			EndIf
		Wend

		'return parse ok
		Return True
	End

	Method SetError:Bool(message:String,line:Int=0,column:Int=0,data:String="")
		' --- error in parse ---
		error = New ConfigError(message,path,data,line,column)
		If attributes attributes.Clear()
		If children children.Clear()
		Return False
	End
	Public

	Method Free:Void()
		' --- free resources ---
		'call chain
		Super.Free()

		'free own resources
		path = ""
		script = ""
		error = Null
	End

	Method HasError:Bool()
		Return error <> Null
	End
End

Function LoadConfig:Config(script:String)
	'create the config
	Local config := New Config
	config.path = ""

	'parse the script
	config.Parse(script)
	Return config
End

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


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

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

' 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


flxconfig added

flxconfig added

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


Example for InputCache.

Example for InputCache.

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

Strict

Import mojo
Import diddy

Global testScreen:InputTestScreen

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

Class InputTestApp Extends DiddyApp
	Method OnCreate:Int()
		Super.OnCreate()
		drawFPSOn = True
		testScreen = New InputTestScreen
		testScreen.PreStart()
		Return 0
	End
End

Class InputTestScreen Extends Screen
	Method New()
		name = "Game"
	End

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

	Method Render:Void()
		Cls
	End

	Method Update:Void()
		For Local event:KeyEvent = EachIn game.inputCache.KeysHit
			' do something for each key hit since the last frame
			Print "KeyHit: key,at="+String.FromChar(event.KeyCode)+","+event.EventTime
		Next
		For Local event:KeyEvent = EachIn game.inputCache.KeysDown
			' do something for each key held down
			'Print "KeyDown: key,at="+String.FromChar(event.KeyCode)+","+event.EventTime
		Next
		For Local event:KeyEvent = EachIn game.inputCache.KeysReleased
			' do something for each key released since the last frame
			Print "KeyReleased: key,at="+String.FromChar(event.KeyCode)+","+event.EventTime
		Next

		If game.inputCache.keyHit[KEY_ESCAPE] Then
			game.screenFade.Start(50, true)
			game.nextScreen = game.exitScreen
		End
	End
End

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


new String Module

new String Module

provides BlitzBasic-Like String Manipulation ...

Strict

Public

#Rem
	This library was created for the sake of restoring the original string-manipulation commands from BlitzBasic.
	This module is useful for porting programs from BlitzBasic and BlitzMax.

	If you find any bugs while using this module, please report them.
#End

' Preprocessor related:

' This acts as the standard implementation-flag for this module.
' If this isn't defined, this module was not imported.
#RETROSTRINGS_IMPLEMENTED = True

#Rem
	This standard has not yet been properly implemented.
	The idea behind this functionality is to only provide the
	original standard BlitzBasic commands, and their usual behavior.

	This can be problematic for other modules which use features and other
	behaviors which are not compatible/available with BlitzBasic's original implementation.

	Configure this with caution, if you're unsure (Which you generally should be), don't mess with this.

	If this is disabled, it means full functionality is available; don't worry about this variable.
#End

#RETROSTRINGS_AUTHENTIC = False

#Rem
	Enabling this will cause extra checks to take place to ensure
	there isn't any issue with the input supplied to the commands of this module.
	Under normal situations, "strict-mode" is enabled,
	so 'RETROSTRINGS_AUTHENTIC' does not need to be check for this.
#End

#RETROSTRINGS_STRICT = True

#Rem
	This currently has variable results, and could change.
	The idea behind this variable is to provide
	better configuration for what 'RETROSTRINGS_STRICT' applied.

	This functionality has yet to be properly implemented.
	Very few places (If any) actually use this.
#End

#RETROSTRINGS_SAFE = True

#If CONFIG = "debug" Or RETROSTRINGS_AUTHENTIC Or RETROSTRINGS_SAFE
	#Rem
		This is currently only defined when compiling in debug-mode.
		If this is disabled, errors detected within the module will be ignored silently,
		and possibly not even checked altogether (Unlikely; see 'RETROSTRINGS_STRICT').
	#End

	#RETROSTRINGS_REPORT_ERRORS = True
#End

' Imports (Public):
#If Not RETROSTRINGS_AUTHENTIC
	Import stringutil
#End

' Imports (Private):
Private

' Non-standard imports (Proprietary):

#Rem
	For the sake of backward compatibility, make sure the
	user isn't trying to force standard internals.
	Technically, this check isn't needed, it's just here
	so we don't import the module when we're not supposed to be using it.
#End

#If Not RETROSTRINGS_STANDARD_INTERNALS
	Import retrostringsextension
#End

Public

#Rem
	The following routine is done for the sake of automating non-standard extensions to this module:
	This routine will be attempted if a preprocessor variable was already defined or not.
	No problems will occur if variables were manually defined beforehand.
#End

#If Not RETROSTRINGS_STANDARD_INTERNALS
	' Check if we were able to import the extension-module:
	#If Not RETROSTRINGS_EXTENSION_IMPLEMENTED
		' No module was found, use standard internals.
		#RETROSTRINGS_STANDARD_INTERNALS = True
	#Else
		' We found an extension-module, do not define the "standard-internals" variable.
	#End
#End

' Aliases (Public):
' Nothing so far.

' Aliases (Private):
Private

' Check for standard internals:
#If Not RETROSTRINGS_STANDARD_INTERNALS
	' This will act as a module-independent alias for extensions.
	Alias ext = retrostringsextension
#End

Public

' Constant variable(s) (Public):

#If Not RETROSTRINGS_AUTHENTIC
	' These are mainly used for internal routines, such as hexadecimal conversion:
	Const ASCII_NUMBERS_POSITION:Int = 48

	Const ASCII_CHARACTER_0:= ASCII_NUMBERS_POSITION
	Const ASCII_CHARACTER_1:= ASCII_CHARACTER_0 + 1
	Const ASCII_CHARACTER_2:= ASCII_CHARACTER_1 + 1
	Const ASCII_CHARACTER_3:= ASCII_CHARACTER_2 + 1
	Const ASCII_CHARACTER_4:= ASCII_CHARACTER_3 + 1
	Const ASCII_CHARACTER_5:= ASCII_CHARACTER_4 + 1
	Const ASCII_CHARACTER_6:= ASCII_CHARACTER_5 + 1
	Const ASCII_CHARACTER_7:= ASCII_CHARACTER_6 + 1
	Const ASCII_CHARACTER_8:= ASCII_CHARACTER_7 + 1
	Const ASCII_CHARACTER_9:= ASCII_CHARACTER_8 + 1

	Const ASCII_CHARACTER_UPPERCASE_POSITION:= 65
	Const ASCII_CHARACTER_LOWERCASE_POSITION:= 97

	' The alphabet is currently not available / available publicly.
#End

' Constant variable(s) (Private):
Private

#If Not RETROSTRINGS_AUTHENTIC
	' This represents the number of characters
	' representing numbers in the ascii-table.
	Const ASCII_NUMBER_COUNT:Int = 10
#End

Public

' Functions:

' Classic BlitzBasic-styled string-commands:
Function Left:String(Str:String, n:Int)
	#If RETROSTRINGS_SAFE
		If (n = 0) Then Return ""
	#End

	#If RETROSTRINGS_STRICT Or RETROSTRINGS_SAFE
		If (n < 0) Then
			#If RETROSTRINGS_REPORT_ERRORS
				Error("Illegal function call.")
			#End

			Return ""
		Endif
	#End

	Return Str[..Min(n, Len(Str))]
End

Function Right:String(Str:String, n:Int)
	If (n = 0) Then Return ""

	#If RETROSTRINGS_STRICT Or RETROSTRINGS_SAFE
		If (n < 0) Then
			#If RETROSTRINGS_REPORT_ERRORS
				Error("Illegal function call.")
			#End

			Return ""
		Endif
	#End

	Return Str[-Min(n, Len(Str))..]
End

Function Mid:String(Str:String, Pos:Int, Size:Int=-1)
	#If RETROSTRINGS_STRICT Or RETROSTRINGS_SAFE
		If (Pos = 0) Then
			#If RETROSTRINGS_REPORT_ERRORS
				'Error("Parameter must be greater than zero. ('Pos': " + Pos + ")")
				Error("Parameter must be greater than zero. ('Pos': 0")
			#End

			Return ""
		Endif
	#End

	If (Pos > Len(Str)) Then
		Return ""
	Endif

	Pos -= 1

	If (Size < 0) Then
		Return Str[Pos..]
	Endif

	If (Pos < 0) Then
		Size += Pos

		Pos = 0
	Endif

	If (Pos+Size > Len(Str)) Then
		Size = Len(Str) - Pos
	Endif

	Return Str[Pos..Pos+Size]
End

Function Len:Int(Str:String)
	Return Str.Length()
End

Function Instr:Int(Str:String, Sub:String, Start:Int=1, Left:Bool=True)
	Return Str.Find(Sub, Start-1)+1
End

Function Lower:String(S:String)
	Return S.ToLower()
End

Function Upper:String(S:String)
	Return S.ToUpper()
End

Function LSet:String(Str:String, N:Int)
	#If RETROSTRINGS_SAFE Or RETROSTRINGS_REPORT_ERRORS
		If (N < 0) Then
			#If RETROSTRINGS_REPORT_ERRORS
				Error("Parameter must be positive. ('N': " + N + ")")
			#End

			Return ""
		Endif
	#End

	Return Str[..N]
End

Function RSet:String(Str:String, N:Int)
	#If RETROSTRINGS_SAFE Or RETROSTRINGS_REPORT_ERRORS
		If (N < 0) Then
			#If RETROSTRINGS_REPORT_ERRORS
				Error("Parameter must be positive. ('N': " + N + ")")
			#End

			Return ""
		Endif
	#End

	Return Str[-N..]
End

Function Replace:String(Str:String, Sub:String, ReplaceWith:String)
	Return Str.Replace(Sub, ReplaceWith)
End

Function Trim:String(Str:String)
	Return Str.Trim()
End

Function Chrs:String(In:Int[])
	Return String.FromChars(In)
End

Function Chr:String(In:Int)
	Return String.FromChar(In)
End

Function Asc:Int(Str:String)
	Return Str[0]
End

Function StrToInt:Int(Str:String)
	Return (Str[0]-48)
End Function

Function Ascs:Int[](Str:String)
	Return Str.ToChars()
End

' The output of this command is completely defined by the implementation of 'retrostrings'.
' This could use either 'HexBE', or 'HexLE'. Usually, the version used is the fastest.
Function Hex:String(Value:Int)
	Return HexBE(Value)
End

Function Bin:String(Value:Int)
	' Local variable(s):
	Local Buf:Int[32]

	For Local k:Int = 31 To 0 Step -1
		Buf[k] = (Value&1) + ASCII_NUMBERS_POSITION

		Value Shr= 1
	Next

	Return String.FromChars(Buf)
End

' Functions (Private?) (These functions are not always private):
#If RETROSTRINGS_AUTHENTIC
	Private
#End

Function HexLE:String(Value:Int)
	#If RETROSTRINGS_STANDARD_INTERNALS Or Not RETROSTRINGS_EXTENSION_HEXLE
		' The current standard implementation of this may change in the future:

		' Local variable(s):
		Local S:= HexBE(Value)

		' Return the result of 'HexBE' in corrected order. (Not the most efficient method)
		Return S[6..8] + S[4..6] + S[2..4] + S[0..2]
	#Else
		Return rsext.HexLE(Value)
	#End
End

' This command may be overhauled at a later date.
Function HexBE:String(Value:Int)
	#If RETROSTRINGS_STANDARD_INTERNALS Or Not RETROSTRINGS_EXTENSION_HEXBE
		' Local variable(s):
		Local Buf:Int[8]

		For Local k:= 7 To 0 Step -1
			Local n:Int = (Value & 15) + ASCII_NUMBERS_POSITION

			If (n > ASCII_CHARACTER_9) Then
				n += (ASCII_CHARACTER_UPPERCASE_POSITION-ASCII_CHARACTER_9-1)
			Endif

			Buf[k]=n
			Value Shr= 4
		Next

		Return String.FromChars(Buf)
	#Else
		Return rsext.HexBE(Value)
	#End
End

' This will return an offset version of the number specified,
' based on the standard ascii position of zero.
' The 'Number' argument should be less than 'ASCII_NUMBER_COUNT', and no smaller than zero.
Function NumberInAsc:Int(Number:Int=0)
	Return ASCII_NUMBERS_POSITION +

	#If RETROSTRINGS_SAFE
		(Abs(Number) Mod ASCII_NUMBER_COUNT)
	#Else
		(Number Mod ASCII_NUMBER_COUNT)
	#End
End

Function LongHex:String(Value:Int)
	Return Hex(Value)
End

Function LongBin:String(Value:Int)
	Return Bin(Value)
End

#If RETROSTRINGS_AUTHENTIC
	Public
#End

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


Framework started

Framework started

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

Strict

Import mojo
Import functions

' Store the device width and height
Global SCREEN_WIDTH%
Global SCREEN_HEIGHT%
' Half of SCREEN_WIDTH and HEIGHT
Global SCREEN_WIDTH2%
Global SCREEN_HEIGHT2%

' THE GAME!!
Global game:DiddyApp

' Used for delta timing movement
Global dt:DeltaTimer

Class DiddyApp Extends App

	Field FPS% = 60

	' current Screen
	Field currentScreen:Screen
	' next Screen
	Field nextScreen:Screen
	' exit Screen
	Field exitScreen:ExitScreen = new ExitScreen()
	' used for fading
	Field screenFade:ScreenFade = New ScreenFade

	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 = RealMillisecs()
		' Create the delta timer
		dt = New DeltaTimer(FPS)
		SetUpdateRate FPS

		Return 0
	End

	Method OnRender:Int()
		FPSCounter.Update()
		currentScreen.Render()
		If screenFade.active then screenFade.Render()
		Return 0
	End

	Method OnUpdate:Int()
		dt.UpdateDelta()
		FPSCounter.Update()

		If screenFade.active then screenFade.Update()
		currentScreen.Update()
		Return 0
	End
End

Class ScreenFade
	Field fadeTime:Float
	Field fadeOut:Bool
	Field ratio# = 0
	Field active:Bool
	Field counter:Float

	Method Start:Void(fadeTime:Float, fadeOut:Bool)
		If active Then Return
		active = true
		self.fadeTime = fadeTime
		self.fadeOut = fadeOut

		If fadeOut Then
			ratio = 1
		Else
			ratio = 0
		End
		counter = 0
	End

	Method Update:Void()
		if not active return
		counter += dt.delta
		CalcRatio()

		if counter > fadeTime
			active = false
			if fadeOut
				game.currentScreen.PostFadeOut()
			else
				game.currentScreen.PostFadeIn()
			End
		End
	End

	Method CalcRatio:Void()
		ratio = counter/fadeTime
		If ratio < 0 Then ratio = 0
		If ratio > 1 Then ratio = 1
		If fadeOut Then
			ratio = 1 - ratio
		End
	End

	Method Render:Void()
		if not active return

		SetAlpha 1 - ratio
		SetColor 0, 0, 0
		DrawRect 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT
		SetAlpha 1
		SetColor 255, 255, 255
	End

End Class

Class ExitScreen Extends Screen
	Method New()
		name = "exit"
	End

	method Start:Void()
		ExitApp()
	End

	method Render:Void()

	End

	method Update:Void()

	End

End

Class Screen Abstract
	Field name$ = ""

	Method PreStart:Void()
		game.currentScreen = self
		Start()
	End

	Method Start:Void() Abstract

	Method Render:Void() Abstract

	Method Update:Void() Abstract

	Method PostFadeOut:Void()
		game.nextScreen.PreStart()
	End

	Method PostFadeIn:Void()

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

	Function Draw:Void(x% = 0, y% = 0, ax# = 0, ay# = 0)
		DrawText("FPS: " + totalFPS, x, y, ax, ay)
	End
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

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


Example for InputCache.

Example for InputCache.


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


add Spline Module

add Spline Module

New Feature:
Drawing a Interpolated Spline

#Rem monkeydoc Module maniac.maniacSpline
	Spline - Version 0.1 (alpha)  ~n

	Converted from BlitzMax Code ...

#End

Function MakePoints(Points:Point[])
	For Local p:Int=0 Until Points.Length
		Points[p]=New Point
		Points[p].x=Rnd(50,750)
		Points[p].y=Rnd(100,550)
	Next
End Function

' akima interpolation requires 6 points
' interpolate between y3 And y4 at position mu (0..1)
'----------------------------------------------------------------------------
Function AkimaInterpolate:Float(y1:Float, y2:Float, y3:Float, y4:Float, y5:Float, y6:Float, mu:Float)

	Local num1:Float = Abs((y5-y4)- (y4-y3))*(y3-y2) + Abs((y3-y2) - (y2-y1))*(y4-y3)
	Local den1:Float = Abs((y5-y4) - (y4-y3)) + Abs((y3-y2) - (y2-y1))

	Local num2:Float = Abs((y6-y5)- (y5-y4))*(y4-y3) + Abs((y4-y3) - (y3-y2))*(y5-y4)
	Local den2:Float = Abs((y6-y5) - (y5-y4)) + Abs((y4-y3) - (y3-y2))

	Local t1:Float
	If den1>0.00001 Then   '0
		t1=num1/den1
	Else
		t1=0.0
	EndIf

	Local t2:Float
	If den2>0.00001 Then   '0
		t2=num2/den2
	Else
		t2=0.0
	EndIf

	Local C:Float = (3*(y4-y3) - 2*t1 - t2)
	Local D:Float = (t1 + t2 - 2*(y4-y3))

	Return  y3 + (t1 + (C + D*mu)*mu)*mu

End Function

'interpolate between y1 and y2
Function CubicInterpolate:Float(y0:Float, y1:Float, y2:Float, y3:Float, mu:Float)
   Local a0#,a1#,a2#,a3#,mu2#

   mu2 = mu*mu
   a0 = y3-y2-y0+y1
   a1 = y0-y1-a0
   a2 = y2-y0
   a3 = y1

   Return a0*mu*mu2+a1*mu2+a2*mu+a3
End Function

Class Point
	Field x:Int
	Field y:Int

	#rem
	Method New(_X:Float,_Y:Float)
		x = _X
		y = _Y
	End Method
	#end
	Function Create:point(x#,y#)
		Local p:point=New point
		p.x=x
		p.y=y
		Return p
	End Function
End Class

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


Added Asteroids to MonkeyMax examples

Added Asteroids to MonkeyMax examples

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

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 a redirection module for 'os'. ('os' -> 'virtualos')

Strict

Public

' Imports:
Import virtualos

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


Framework example

Framework example

Strict

Import mojo
Import diddy

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

Global titleScreen:TitleScreen
Global gameScreen:GameScreen

Class MyGame extends DiddyApp
	Method OnCreate:Int()
		Super.OnCreate()

		titleScreen = New TitleScreen
		gameScreen = new GameScreen
		titleScreen.PreStart()
		return 0
	End Method
End

Class TitleScreen Extends Screen
	Method New()
		name = "Title"
	End

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

	Method Render:Void()
		Cls
		DrawText "TITLE SCREEN!", SCREEN_WIDTH2, SCREEN_HEIGHT2, 0.5, 0.5
		DrawText "Press Space to Play!", SCREEN_WIDTH2, SCREEN_HEIGHT2 + 20, 0.5, 0.5
		DrawText "Press Escape to Quit!", SCREEN_WIDTH2, SCREEN_HEIGHT2 + 40, 0.5, 0.5
	End

	Method Update:Void()
		If KeyHit(KEY_SPACE)
			game.screenFade.Start(50, true)
			game.nextScreen = gameScreen
		End

		If KeyHit(KEY_ESCAPE)
			game.screenFade.Start(50, true)
			game.nextScreen = game.exitScreen
		End
	End
End

Class GameScreen Extends Screen
	Method New()
		name = "Game"
	End

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

	Method Render:Void()
		Cls
		DrawText "GAME SCREEN!", SCREEN_WIDTH2, SCREEN_HEIGHT2, 0.5, 0.5
	End

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

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


Added an example for 'RC4' encryption.

Added an example for 'RC4' encryption.

Strict

Public

' Imports:
Import regal.ioutil.publicdatastream
Import regal.hash.rc4

' Functions:
Function ReadString:String(input:Stream, start_at_beginning:Bool=True)
	Local position:= input.Position

	If (start_at_beginning) Then
		input.Seek(0)
	Endif

	Local value:= input.ReadString(input.Length)

	input.Seek(position)

	Return value
End

Function WriteString:Void(output:Stream, value:String, start_at_beginning:Bool=True)
	Local position:= output.Position

	If (start_at_beginning) Then
		output.Seek(0)
	Endif

	output.WriteString(value)

	output.Seek(position)
End

Function Main:Int()
	Local key:= "abcdefghijklmnopqrstuvwxyz"
	Local value:= "Hello world."

	Local length:= value.Length

	Local input:= New PublicDataStream(length)
	Local output:= New PublicDataStream(length)
	Local result:= New PublicDataStream(length)

	WriteString(input, value)

	' Process the
	RC4(input, output, key)

	output.Seek(0)

	RC4(output, result, key)

	Print("Input: " + ReadString(input))
	Print("Output: " + ReadString(output))
	Print("Result: " + ReadString(result))

	input.Close()
	output.Close()
	result.Close()

	Return 0
End

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


Angelfont simple textbox added

Angelfont simple textbox added

Strict

'Import mojo
Import angelfont

Class SimpleTextBox
	Global lineGap:Int = 5

	Global yOffset:Int = 0

	Global font:AngelFont

	Global align:Int = AngelFont.ALIGN_LEFT

	Function Draw:Void(text:String, x:Int, y:Int, width:Int, alignment:Int = AngelFont.ALIGN_LEFT)

		Local thisLine:String = ""
		Local charOffset:Int = 0

		Local wordLen:Int = 0
		Local word:String = ""

		font = AngelFont.current
		align = alignment

		yOffset = 0
		For Local i := 0 Until text.Length
			If y+yOffset > DeviceHeight()
				Return
			Endif

			Local asc:Int = text[i]
			Select asc
				Case 32	' space
					wordLen = font.TextWidth(word)
					If charOffset + wordLen > width
						DrawTextLine(thisLine, x,y+yOffset)
						thisLine = ""
						charOffset = 0
					Endif
'					Local chars:Char[] = font.GetChars()
					charOffset += wordLen+font.GetChars()[32].xAdvance
					thisLine += word + " "

					word = ""
					'wordLen = 0
				Case 10	' newline or "~n"
					wordLen = font.TextWidth(word)
					If charOffset + wordLen > width
						DrawTextLine(thisLine, x,y+yOffset)
						thisLine = ""
					Endif
					thisLine += word

					DrawTextLine(thisLine, x,y+yOffset)

					thisLine = ""
					charOffset = 0
					word = ""
				Default
					'Local ch:Char = font.GetChars()[asc]
					word += String.FromChar(asc)
			End Select
		Next

		If word <> ""
			wordLen = font.TextWidth(word)
			If charOffset + wordLen > width
				DrawTextLine(thisLine, x,y+yOffset)
				thisLine = ""
			Endif
			thisLine += word
		Endif
		If thisLine <> ""
			DrawTextLine(thisLine, x,y+yOffset)
		Endif
	End

	Function DrawHTML:Void(text:String, x:Int, y:Int, width:Int, alignment:Int = AngelFont.ALIGN_LEFT)
		Local thisLine:String = ""
		Local charOffset:Int = 0

		Local wordLen:Int = 0
		Local word:String = ""

		font = AngelFont.current
		align = alignment

		yOffset = 0
		For Local i := 0 Until text.Length
			If y+yOffset > DeviceHeight()
				Return
			Endif

			Local asc:Int = text[i]
			Select asc
				Case 32	' space
					wordLen = font.TextWidth(AngelFont.StripHTML(word))
					If charOffset + wordLen > width
						DrawTextLineHTML(thisLine, x,y+yOffset)
						thisLine = ""
						charOffset = 0
					Endif
'					Local chars:Char[] = font.GetChars()
					charOffset += wordLen+font.GetChars()[32].xAdvance
					thisLine += word + " "

					word = ""
					'wordLen = 0
				Case 10	' newline or "~n"
					wordLen = font.TextWidth(AngelFont.StripHTML(word))
					If charOffset + wordLen > width
						DrawTextLineHTML(thisLine, x,y+yOffset)
						thisLine = ""
					Endif
					thisLine += word

					DrawTextLineHTML(thisLine, x,y+yOffset)

					thisLine = ""
					charOffset = 0
					word = ""
				Case 60	' <
					If text[i+1..i+3] = "i>" Or text[i+1..i+3] = "b>"
						word += text[i..i+3]
						i += 2
					Else
						If text[i+1..i+4] = "/i>" Or text[i+1..i+4] = "/b>"
							word += text[i..i+4]
							i += 3
						End
					End
				Default
					'Local ch:Char = font.GetChars()[asc]
					word += String.FromChar(asc)
			End Select
		Next

		If word <> ""
			wordLen = font.TextWidth(AngelFont.StripHTML(word))
			If charOffset + wordLen > width
				DrawTextLineHTML(thisLine, x,y+yOffset)
				thisLine = ""
			Endif
			thisLine += word
		Endif
		If thisLine <> ""
			DrawTextLineHTML(thisLine, x,y+yOffset)
		Endif
	End

	Function DrawTextLine:Void(txt:String, x:Int,y:Int)
		font.DrawText(txt, x,y, align)
		yOffset += lineGap+font.height
	End

	Function DrawTextLineHTML:Void(txt:String, x:Int,y:Int)
		font.DrawHTML(txt, x,y, align)
		yOffset += lineGap+font.height
	End

End Class

error: pathspec 'vendor/angelfont/simpletextbox.monkey' did not match any file(s) known to git


Added a new StringBuilder class since Monkey now has String.FromChars.

Import arrays

Class StringBuilder
Public
	Const DEFAULT_SIZE:Int = 128

Private
	Field characters:Int[]
	Field length:Int

	Field dirty:Bool = False
	Field cache:String = ""

	Method ResizeArray:Void(targetSize:Int=-1, shrink:Bool=False)
		Local temp:Int = 2
		If targetSize < 0 Then targetSize = length
		While temp < targetSize
			temp *= 2
		End
		If temp = characters.Length Or temp < characters.Length And Not shrink Then Return
		If characters.Length = 0 Then
			characters = New Int[temp]
		Else
			characters = characters.Resize(temp)
		End
	End

	Method CachedString:String()
		If length <= 0 Then
			cache = ""
		Else
			cache = String.FromChars(characters[0..length])
		End
	End

Public
	Method Capacity:Int() Property
		Return characters.Length
	End

	Method Length:Int() Property
		Return length
	End

	Method Length:Void(length:Int) Property
		If length < 0 Then length = 0
		Local oldLength:Int = Self.length
		ResizeArray(length, True)
		If oldLength < length Then
			For Local i:Int = oldLength Until length
				characters[i] = $20 ' pad with spaces
			Next
		End
		Self.length = length
		dirty = True
	End

	Method New()
		characters = New Int[DEFAULT_SIZE]
		length = 0
		dirty = False
		cache = ""
	End

	Method New(defaultSize:Int)
		If defaultSize <= 0 Then defaultSize = DEFAULT_SIZE
		characters = New Int[defaultSize]
		length = 0
		dirty = False
		cache = ""
	End

	Method New(defaultValue:String)
		SetValue(defaultValue)
	End

	Method ToString:String()
		If length <= 0 Then Return ""
		If dirty Then
			cache = String.FromChars(characters[0..length])
			dirty = False
		End
		Return cache
	End

' SetValue
	Method SetValue:StringBuilder(value:Int)
		Return SetValue(String(value))
	End

	Method SetValue:StringBuilder(value:Float)
		Return SetValue(String(value))
	End

	Method SetValue:StringBuilder(value:Bool)
		If value Then Return SetValue("True")
		Return SetValue("False")
	End

	Method SetValue:StringBuilder(value:StringBuilder)
		Return SetValue(value.ToString())
	End

	Method SetValue:StringBuilder(value:String)
		dirty = True
		length = 0
		Return Append(value)
	End

	Method SetValue:StringBuilder(value:Int[])
		dirty = True
		length = 0
		Return Append(value)
	End

' Append
	Method Append:StringBuilder(value:Int)
		Return Append(String(value))
	End

	Method Append:StringBuilder(value:Float)
		Return Append(String(value))
	End

	Method Append:StringBuilder(value:Bool)
		If value Then Return Append("True")
		Return Append("False")
	End

	Method Append:StringBuilder(value:StringBuilder)
		Return Append(value.ToString())
	End

	Method Append:StringBuilder(value:String)
		dirty = True
		Local temp:Int = length + value.Length
		ResizeArray(temp)
		For Local i:Int = 0 Until value.Length
			characters[length+i] = value[i]
		Next
		length += value.Length
		Return Self
	End

	Method Append:StringBuilder(value:Int[])
		dirty = True
		Local temp:Int = length + value.Length
		ResizeArray(temp)
		Arrays<Int>.Copy(value, 0, characters, length, value.Length)
		length += value.Length
		Return Self
	End

' Delete
	Method Delete:StringBuilder(startIndex:Int, endIndex:Int)
		If startIndex < 0 Or startIndex > length Then Error("Start index ("+startIndex+") out of range [0-"+(length-1)+"]")
		If startIndex > endIndex Then Error("Start index ("+startIndex+") greater than end index ("+endIndex+")")
		If endIndex > length Then endIndex = length
		Local len:Int = endIndex - startIndex
		If len > 0 Then
			dirty = True
			Arrays<Int>.Copy(characters, endIndex, characters, startIndex, length-endIndex)
			Self.length -= len
		End
		Return Self
	End

' Find/FindLast (from Monkey strings)
	Method Find:Int(str:String, start:Int=0)
		Return ToString().Find(str, start)
	End

	Method FindLast:Int(str:String)
		Return ToString().FindLast(str)
	End

	Method FindLast:Int(str:String, start:Int)
		Return ToString().FindLast(str, start)
	End

' Insert
	Method Insert:StringBuilder(index:Int, value:Int)
		Return Insert(index, String(value))
	End

	Method Insert:StringBuilder(index:Int, value:Float)
		Return Insert(index, String(value))
	End

	Method Insert:StringBuilder(index:Int, value:Bool)
		If value Then Return Insert(index, "True")
		Return Insert(index, "False")
	End

	Method Insert:StringBuilder(index:Int, value:StringBuilder)
		Return Insert(index, value.ToString())
	End

	Method Insert:StringBuilder(index:Int, value:String)
		dirty = True
		If index < 0 Or index > length Then Error("Index ("+index+") out of range [0-"+(length-1)+"]")
		Local len:Int = value.Length()
		Local newlen:Int = length + len
		ResizeArray(newlen)
		Arrays<Int>.Copy(characters, index, characters, index+len, length-index)
		For Local i:Int = 0 Until len
			characters[index+i] = value[i]
		Next
		length += value.Length
		Return Self
	End

	Method Insert:StringBuilder(index:Int, value:Int[])
		dirty = True
		If index < 0 Or index > length Then Error("Index ("+index+") out of range [0-"+(length-1)+"]")
		Local len:Int = value.Length
		Local newlen:Int = length + len
		ResizeArray(newlen)
		Arrays<Int>.Copy(characters, index, characters, index+len, length-index)
		Arrays<Int>.Copy(value, 0, characters, index, len)
		length += value.Length
		Return Self
	End

' Replace
	Method Replace:StringBuilder(startIndex:Int, endIndex:Int, value:Int)
		Return Replace(startIndex, endIndex, String(value))
	End

	Method Replace:StringBuilder(startIndex:Int, endIndex:Int, value:Float)
		Return Replace(startIndex, endIndex, String(value))
	End

	Method Replace:StringBuilder(startIndex:Int, endIndex:Int, value:Bool)
		If value Then Return Replace(startIndex, endIndex, "True")
		Return Replace(startIndex, endIndex, "False")
	End

	Method Replace:StringBuilder(startIndex:Int, endIndex:Int, value:StringBuilder)
		Return Replace(startIndex, endIndex, value.ToString())
	End

	Method Replace:StringBuilder(startIndex:Int, endIndex:Int, value:String)
		If startIndex < 0 Or startIndex > length Then Error("Start index ("+startIndex+") out of range [0-"+(length-1)+"]")
		If startIndex > endIndex Then Error("Start index ("+startIndex+") greater than end index ("+endIndex+")")
		If endIndex > length Then endIndex = length
		dirty = True
		Local len:Int = value.Length()
		Local newlen:Int = length + len - (endIndex - startIndex)
		ResizeArray(newlen)
		Arrays<Int>.Copy(characters, endIndex, characters, startIndex + len, length - endIndex)
		For Local i:Int = 0 Until len
			characters[startIndex+i] = value[i]
		Next
		length -= endIndex-startIndex
		length += value.Length
		Return Self
	End

	Method Replace:StringBuilder(startIndex:Int, endIndex:Int, value:Int[])
		If startIndex < 0 Or startIndex > length Then Error("Start index ("+startIndex+") out of range [0-"+(length-1)+"]")
		If startIndex > endIndex Then Error("Start index ("+startIndex+") greater than end index ("+endIndex+")")
		If endIndex > length Then endIndex = length
		dirty = True
		Local len:Int = value.Length
		Local newlen:Int = length + len - (endIndex - startIndex)
		ResizeArray(newlen)
		Arrays<Int>.Copy(characters, endIndex, characters, startIndex + len, length - endIndex)
		Arrays<Int>.Copy(value, 0, characters, startIndex, len)
		length -= endIndex-startIndex
		length += value.Length
		Return Self
	End

' Reverse
	Method Reverse:StringBuilder()
		If length <= 0 Then Return Self
		dirty = True
		Arrays<Int>.Reverse(characters)
		Return Self
	End

' Substring
	Method Substring:String(startIndex:Int, endIndex:Int)
		If startIndex < 0 Or startIndex > length Then Error("Start index ("+startIndex+") out of range [0-"+(length-1)+"]")
		If startIndex > endIndex Then Error("Start index ("+startIndex+") greater than end index ("+endIndex+")")
		If endIndex > length Then endIndex = length
		Local len:Int = endIndex-startIndex
		If len = 0 Then Return ""
		Return ToString()[startIndex..endIndex]
	End

' GetChars
	Method GetChars:Void(startIndex:Int, endIndex:Int, dest:Int[], destIndex:Int)
		If startIndex < 0 Or startIndex > length Then Error("Start index ("+startIndex+") out of range [0-"+(length-1)+"]")
		If startIndex > endIndex Then Error("Start index ("+startIndex+") greater than end index ("+endIndex+")")
		If endIndex > length Then endIndex = length
		Local len:Int = endIndex-startIndex
		If len > 0 Then Arrays<Int>.Copy(characters, startIndex, dest, destIndex, len)
	End

	Method GetChars:Int[](startIndex:Int, endIndex:Int)
		If startIndex < 0 Or startIndex > length Then Error("Start index ("+startIndex+") out of range [0-"+(length-1)+"]")
		If startIndex > endIndex Then Error("Start index ("+startIndex+") greater than end index ("+endIndex+")")
		If endIndex > length Then endIndex = length
		Local len:Int = endIndex-startIndex
		If len = 0 Then Return []
		Return Arrays<Int>.Slice(characters, startIndex, endIndex)
	End

' SetCharAt
	Method SetCharAt:Void(index:Int, ch:Int)
		If index < 0 Or index > length Then Error("Index ("+index+") out of range [0-"+(length-1)+"]")
		characters[index] = ch
	End

' DeleteCharAt
	Method DeleteCharAt:Void(index:Int)
		If index < 0 Or index > length Then Error("Index ("+index+") out of range [0-"+(length-1)+"]")
		Arrays<Int>.Copy(characters, index+1, characters, index, characters.Length-index-1)
		length -= 1
	End
End

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


FrameRecord added. Currently omly keyboard and mouse support

Strict

Import keyrecord
Import xyrecord

Class FrameRecord

	Field frame:Int

	Field keys:Stack<KeyRecord>

	Field mouse:XYRecord

Private
	Global _stringBuffer:StringStack = New StringStack()

	Method New()
		frame = 0
		keys = Null
		mouse = Null
	End Method

	Method Create:FrameRecord(frame:Int, keys:Stack<KeyRecord> = Null, mouse:XYRecord)
		Self.frame = frame
		Self.keys = keys
		Self.mouse = mouse

		Return Self
	End Method

	Method Destroy:Void()
		keys = Null
		mouse = Null
	End Method

	Method Save:String()
		Return Save(New StringStack()).Join("")
	End Method

	Method Save:StringStack(output:StringStack)
		output.Push(frame + "k")

		If (keys <> Null) Then
			Local key:KeyRecord
			Local i:Int = 0
			Local l:Int = keys.Length()

			While (i < l)
				If (i > 0) output.Push(",")

				key = keys.Get(i)

				output.Push(key.code + ":" + key.value))

				i += 1
			Wend
		End If

		output.Push("m")

		If (mouse <> Null) Then
			output.Push(mouse.x + "," + mouse.y)
		End If

		Return output
	End Method

	Method Load:FrameRecord(data:String)
		Local i:Int
		Local l:Int

		Local array:String[] = data.Split("k")
		frame = Int(array[0])

		array = array[1].Split("m")

		Local keyData:String = array[0]
		Local mouseData:String = array[1]

		If (keyData.Length() > 0) Then
			array = keyData.Split(",")

			Local keyPair:String[]
			i = 0
			l = array.Length()

			While (i < l)
				keyPair = array[i].Split(":")

				If (keyPair.Length() = 2) Then
					If (keys = Null) keys = New Stack<KeyRecord>()

					keys.Push(New KeyRecord(Int(keyPair[0]), Int(keyPair[1])))
				End If

				i += 1
			Wend
		End If

		If (mouseData.Length() > 0) Then
			array = mouseData.Split(",")

			If (array.Length = 2) Then
				mouse = New XYRecord(Int(array[0]), Int(array[1]))
			End If
		End If

		Return Self
	End Method
End Class

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


Initial revision of config demo, included with permission from Jonathan Pittock.

Import mojo
Import config

Function Main()
	New App
	Local c1 := LoadConfig("<options><option>one</option><option>two</option><option>three</option></options>")
	Local c2 := LoadConfig("<items><item id=apple x=0 y=0 width=128 height=128 /><item id=orange x=128 y=0 width=128 height=128 /><item id=pear x=256 y=0 width=128 height=128 /></items>")

	'parse c1
	Print "config1:"
	Local nodes := c1.FindNodesByPath("options/option")
	For Local node := Eachin nodes
		Print " -> "+node.GetName()+" = "+node.GetValue()
	Next

	'parse c2
	Print "config2:"
	nodes = c2.FindNodesByPath("items/item")
	For Local node := Eachin nodes
		Print " -> "+node.GetName()+"(x="+node.GetAttribute("x")+" y="+node.GetAttribute("y")+" width="+node.GetAttribute("width")+" height="+node.GetAttribute("height")+" )"
	Next
End

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