' [Harvest Moon Clone] Online 06 by Tuchs (slugkatten@yahoo.se)
' --- Client: Animation Manager ---
Global animation_dir$ = "graphics/animations/"
Type TSprite
Global _list:TList = New TList
Field actions:TMap
Field images:TMap
Field name:String
Field path:String
Field standard:TAction
Function GetSprite:TSprite(name:String)
Local sp:TSprite
For sp = EachIn _list
If sp.path = name Return sp
Next
Return LoadXML(name)
End Function
Function LoadXML:TSprite(name:String)
Local doc:TxmlDoc
Local node:TxmlNode
doc = TxmlDoc.parseFile( name)
If doc = Null Then
Print "Document not parsed successfully."
Return
End If
node = doc.GetRootElement()
If node = Null Then
Print "empty document"
doc.free()
Return
End If
If node.getName() = "sprite"
If debug_io >=2 Print "Animation XML parsed: " +name
Local sp:TSprite = New TSprite
sp.path = name
sp.name = node.getAttribute("name")
sp.actions = CreateMap()
sp.images = CreateMap()
_list.addlast sp
Local chnode:TxmlNode
Local children:TList = node.getChildren()
For chnode = EachIn children
If chnode.getName() = "imageset" Then
Local im:TImageset = New TImageset
im.name = chnode.getAttribute("name")
im.width = Int(chnode.getAttribute("width"))
im.height = Int(chnode.getAttribute("height"))
im.offsetX = Int(chnode.getAttribute("offsetX"))
im.offsetY = Int(chnode.getAttribute("offsetY") )
im.zoom = Float(chnode.getAttribute("zoom") )
If im.zoom=0 im.zoom=1
im.image = LoadAnimImage(chnode.getAttribute("src"), im.width, im.height, 0, Int(chnode.getAttribute("count")), MASKEDIMAGE)
If Not im.image Print chnode.getAttribute("src") + " nicht gefunden"
MapInsert(sp.images, im.name, im)
EndIf
Next
' First load all images, THEN parse actions
For chnode = EachIn children
If chnode.getName() = "action"
Local ac:TAction = New TAction
ac.name = chnode.getAttribute("name")
ac.image = TIMageSet(MapValueForKey(sp.images, chnode.getAttribute("imageset")))
ac.animations = CreateMap()
ac.ParseAction(chnode)
MapInsert(sp.actions, ac.name, ac)
EndIf
Next
sp.standard = TAction(MapValueForKey(sp.actions, node.getAttribute("action")))
Return sp
End If
End Function
End Type
Type TImageSet
Field name:String
Field width:Int
Field height:Int
Field offsetX:Int
Field offsetY:Int
Field zoom:Float
Field image:TImage
End Type
Type TAction
Field name:String
Field image:TImageset
Field animations:TMap
Method ParseAction(node:TxmlNode)
Local children:TList = node.getChildren()
Local chnode:TxmlNode
For chnode = EachIn children
If chnode.getName() = "animation"
Local an:TAnimation = New TAnimation
an.direction = chnode.getAttribute("direction")
an.offsetX = Int(chnode.getAttribute("offsetX"))
an.offsetY = Int(chnode.getAttribute("offsetY"))
an.frames = New TList
MapInsert(animations, an.direction, an)
Local gchildren:TList = chnode.getChildren()
Local gchnode:TxmlNode
Local fr:Tframe
For gchnode = EachIn gchildren
If gchnode.getName() = "frame"
fr = New TFrame
fr.index = Int(gchnode.getAttribute("index"))
fr.fdelay = Int(gchnode.getAttribute("delay"))
an.frames.addlast fr
ElseIf gchnode.getName() = "sequence"
Local co:Int
For co = 1 To Int(gchnode.GetAttribute("count"))
fr = New Tframe
fr.index = Int(Gchnode.getAttribute("start")) + (co-1) * Int(gchnode.getAttribute("step"))
fr.fdelay = Int(gchnode.getAttribute("delay"))
an.frames.addlast fr
Next
EndIf
Next
EndIf
Next
End Method
End Type
Type TAnimation
Field frames:TList
Field direction:String
Field offsetX:Int
Field offsetY:Int
End Type
Type TFrame
Field index:Int
Field fdelay:Int
End Type
Type TAnimationInstance
Field sprite:TSprite
Field action:TAction
Field animation:TAnimation
Field framelink:TLink
Field timepassed:Int 'Time in ms having passed since last frame change
Field continuous:Byte 'Whether the animation shall be repeated until explicit animation change or
Field playspeed:Float
Function Start:TAnimationInstance(sp:Tsprite)
Local ai:TAnimationInstance = New TAnimationInstance
ai.playspeed = 1
ai.sprite = sp
ai.action = sp.standard
If ai.action
ai.animation = TAnimation(MapValueForKey(ai.action.animations, "right"))
ai.framelink = ai.animation.frames.firstlink()
EndIf
Return ai
End Function
Method Draw(x:Int, y:Int)
If action
SetBlend alphablend
SetScale action.image.zoom, action.image.zoom
DrawImage action.image.image , x + action.image.offsetX + animation.offsetX , y + action.image.offsetY +animation.offsetY , TFrame(framelink.Value() ).index
SetBlend maskblend
EndIf
SetScale 1 , 1
SetColor 255,255,255
End Method
Method CollisionRect(rx ,ry , width , height, x, y, sx=1, sy=1)
If action
SetScale action.image.zoom, action.image.zoom
If ImageRectCollide(action.image.image, x + action.image.offsetX, y + action.image.offsetY, TFrame(framelink.Value()).index, rx,ry,width,height) SetScale 1,1;Return 1
EndIf
SetScale 1,1
Return 0
End Method
Method Update()
If action = Null Return
If TFrame(framelink.Value()).fdelay = 0 Then Return
timepassed:+ TDelta.Time * playspeed
While timepassed > TFrame(framelink.Value()).fdelay
timepassed:- TFrame(framelink.Value()).fdelay
If framelink <> animation.frames.lastlink()
framelink = framelink.nextlink()
Else
If continuous
framelink = animation.frames.firstlink()
Else
playspeed = 1
action = sprite.standard
If action
animation = TAnimation(MapValueForKey(action.animations, animation.direction))
framelink = animation.frames.firstlink()
If TFrame(framelink.Value()).fdelay = 0 Then Return
EndIf
EndIf
EndIf
Wend
End Method
Method SetAnimation(dir:String)
If dir = animation.direction Return
Local an:TAnimation = TAnimation(MapValueForKey(action.animations, dir))
If an
animation = an
Else
Print "Animation " + dir + " not found in action " + action.name
Return
EndIf
framelink = animation.frames.firstlink()
End Method
Method SetAction(name:String, cont:Byte)
Local ac:TAction = TAction(MapValueForKey(sprite.actions, name))
If ac
action = ac
EndIf
playspeed = 1
If action
animation = TAnimation(MapValueForKey(action.animations, animation.direction))
framelink = animation.frames.firstlink()
EndIf
continuous = cont
timepassed = 0
End Method
Method HasAction(name:String)
Local ac:TAction = TAction(MapValueForKey(sprite.actions, name))
If ac Return True
Return False
End Method
Method rear:Byte()
If animation.direction = "up" Return 0
If animation.direction = "right" Return 1
If animation.direction = "down" Return 2
If animation.direction = "left" Return 3
End Method
Method SyncAction(other:TAnimationInstance)
Local ac:TAction = TAction(MapValueForKey(sprite.actions, other.action.name))
If ac
action = ac
playspeed = other.playspeed
animation = TAnimation(MapValueForKey(action.animations, other.animation.direction))
framelink = animation.frames.firstlink()
EndIf
continuous = other.continuous
timepassed = other.timepassed
End Method
Method GetAction:String()
Return action.name
End Method
Method GetDirection:String()
Return animation.direction
End Method
End Type