1. ' [Harvest Moon Clone] Online 06 by Tuchs (slugkatten@yahoo.se)
  2. ' --- Client: Animation Manager ---
  3. Global animation_dir$ = "graphics/animations/"
  4.  
  5. Type TSprite
  6. Global _list:TList = New TList
  7. Field actions:TMap
  8. Field images:TMap
  9. Field name:String
  10. Field path:String
  11. Field standard:TAction
  12.  
  13. Function GetSprite:TSprite(name:String)
  14. Local sp:TSprite
  15. For sp = EachIn _list
  16. If sp.path = name Return sp
  17. Next
  18. Return LoadXML(name)
  19. End Function
  20.  
  21. Function LoadXML:TSprite(name:String)
  22. Local doc:TxmlDoc
  23. Local node:TxmlNode
  24.  
  25. doc = TxmlDoc.parseFile( name)
  26.  
  27. If doc = Null Then
  28. Print "Document not parsed successfully."
  29. Return
  30. End If
  31.  
  32. node = doc.GetRootElement()
  33.  
  34. If node = Null Then
  35. Print "empty document"
  36. doc.free()
  37. Return
  38. End If
  39.  
  40. If node.getName() = "sprite"
  41. If debug_io >=2 Print "Animation XML parsed: " +name
  42. Local sp:TSprite = New TSprite
  43. sp.path = name
  44. sp.name = node.getAttribute("name")
  45. sp.actions = CreateMap()
  46. sp.images = CreateMap()
  47. _list.addlast sp
  48.  
  49. Local chnode:TxmlNode
  50. Local children:TList = node.getChildren()
  51. For chnode = EachIn children
  52. If chnode.getName() = "imageset" Then
  53. Local im:TImageset = New TImageset
  54. im.name = chnode.getAttribute("name")
  55. im.width = Int(chnode.getAttribute("width"))
  56. im.height = Int(chnode.getAttribute("height"))
  57. im.offsetX = Int(chnode.getAttribute("offsetX"))
  58. im.offsetY = Int(chnode.getAttribute("offsetY") )
  59. im.zoom = Float(chnode.getAttribute("zoom") )
  60. If im.zoom=0 im.zoom=1
  61. im.image = LoadAnimImage(chnode.getAttribute("src"), im.width, im.height, 0, Int(chnode.getAttribute("count")), MASKEDIMAGE)
  62. If Not im.image Print chnode.getAttribute("src") + " nicht gefunden"
  63. MapInsert(sp.images, im.name, im)
  64. EndIf
  65. Next
  66. ' First load all images, THEN parse actions
  67. For chnode = EachIn children
  68. If chnode.getName() = "action"
  69. Local ac:TAction = New TAction
  70. ac.name = chnode.getAttribute("name")
  71. ac.image = TIMageSet(MapValueForKey(sp.images, chnode.getAttribute("imageset")))
  72. ac.animations = CreateMap()
  73. ac.ParseAction(chnode)
  74. MapInsert(sp.actions, ac.name, ac)
  75. EndIf
  76. Next
  77. sp.standard = TAction(MapValueForKey(sp.actions, node.getAttribute("action")))
  78. Return sp
  79. End If
  80.  
  81. End Function
  82.  
  83.  
  84. End Type
  85.  
  86.  
  87. Type TImageSet
  88. Field name:String
  89. Field width:Int
  90. Field height:Int
  91. Field offsetX:Int
  92. Field offsetY:Int
  93. Field zoom:Float
  94. Field image:TImage
  95. End Type
  96.  
  97. Type TAction
  98. Field name:String
  99. Field image:TImageset
  100. Field animations:TMap
  101. Method ParseAction(node:TxmlNode)
  102. Local children:TList = node.getChildren()
  103. Local chnode:TxmlNode
  104. For chnode = EachIn children
  105. If chnode.getName() = "animation"
  106. Local an:TAnimation = New TAnimation
  107. an.direction = chnode.getAttribute("direction")
  108. an.offsetX = Int(chnode.getAttribute("offsetX"))
  109. an.offsetY = Int(chnode.getAttribute("offsetY"))
  110. an.frames = New TList
  111. MapInsert(animations, an.direction, an)
  112. Local gchildren:TList = chnode.getChildren()
  113. Local gchnode:TxmlNode
  114. Local fr:Tframe
  115. For gchnode = EachIn gchildren
  116. If gchnode.getName() = "frame"
  117. fr = New TFrame
  118. fr.index = Int(gchnode.getAttribute("index"))
  119. fr.fdelay = Int(gchnode.getAttribute("delay"))
  120. an.frames.addlast fr
  121. ElseIf gchnode.getName() = "sequence"
  122. Local co:Int
  123. For co = 1 To Int(gchnode.GetAttribute("count"))
  124. fr = New Tframe
  125. fr.index = Int(Gchnode.getAttribute("start")) + (co-1) * Int(gchnode.getAttribute("step"))
  126. fr.fdelay = Int(gchnode.getAttribute("delay"))
  127. an.frames.addlast fr
  128. Next
  129. EndIf
  130. Next
  131. EndIf
  132. Next
  133. End Method
  134. End Type
  135.  
  136. Type TAnimation
  137. Field frames:TList
  138. Field direction:String
  139. Field offsetX:Int
  140. Field offsetY:Int
  141. End Type
  142.  
  143. Type TFrame
  144. Field index:Int
  145. Field fdelay:Int
  146. End Type
  147.  
  148. Type TAnimationInstance
  149. Field sprite:TSprite
  150. Field action:TAction
  151. Field animation:TAnimation
  152. Field framelink:TLink
  153. Field timepassed:Int 'Time in ms having passed since last frame change
  154. Field continuous:Byte 'Whether the animation shall be repeated until explicit animation change or
  155. Field playspeed:Float
  156.  
  157. Function Start:TAnimationInstance(sp:Tsprite)
  158. Local ai:TAnimationInstance = New TAnimationInstance
  159. ai.playspeed = 1
  160. ai.sprite = sp
  161. ai.action = sp.standard
  162. If ai.action
  163. ai.animation = TAnimation(MapValueForKey(ai.action.animations, "right"))
  164. ai.framelink = ai.animation.frames.firstlink()
  165. EndIf
  166. Return ai
  167. End Function
  168.  
  169. Method Draw(x:Int, y:Int)
  170. If action
  171. SetBlend alphablend
  172. SetScale action.image.zoom, action.image.zoom
  173. DrawImage action.image.image , x + action.image.offsetX + animation.offsetX , y + action.image.offsetY +animation.offsetY , TFrame(framelink.Value() ).index
  174. SetBlend maskblend
  175. EndIf
  176. SetScale 1 , 1
  177. SetColor 255,255,255
  178. End Method
  179.  
  180. Method CollisionRect(rx ,ry , width , height, x, y, sx=1, sy=1)
  181. If action
  182. SetScale action.image.zoom, action.image.zoom
  183. 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
  184. EndIf
  185. SetScale 1,1
  186. Return 0
  187. End Method
  188.  
  189. Method Update()
  190. If action = Null Return
  191. If TFrame(framelink.Value()).fdelay = 0 Then Return
  192. timepassed:+ TDelta.Time * playspeed
  193. While timepassed > TFrame(framelink.Value()).fdelay
  194. timepassed:- TFrame(framelink.Value()).fdelay
  195. If framelink <> animation.frames.lastlink()
  196. framelink = framelink.nextlink()
  197. Else
  198. If continuous
  199. framelink = animation.frames.firstlink()
  200. Else
  201. playspeed = 1
  202. action = sprite.standard
  203. If action
  204. animation = TAnimation(MapValueForKey(action.animations, animation.direction))
  205. framelink = animation.frames.firstlink()
  206. If TFrame(framelink.Value()).fdelay = 0 Then Return
  207. EndIf
  208. EndIf
  209. EndIf
  210. Wend
  211. End Method
  212.  
  213. Method SetAnimation(dir:String)
  214. If dir = animation.direction Return
  215. Local an:TAnimation = TAnimation(MapValueForKey(action.animations, dir))
  216. If an
  217. animation = an
  218. Else
  219. Print "Animation " + dir + " not found in action " + action.name
  220. Return
  221. EndIf
  222. framelink = animation.frames.firstlink()
  223. End Method
  224.  
  225. Method SetAction(name:String, cont:Byte)
  226. Local ac:TAction = TAction(MapValueForKey(sprite.actions, name))
  227. If ac
  228. action = ac
  229. EndIf
  230. playspeed = 1
  231. If action
  232. animation = TAnimation(MapValueForKey(action.animations, animation.direction))
  233. framelink = animation.frames.firstlink()
  234. EndIf
  235. continuous = cont
  236. timepassed = 0
  237. End Method
  238.  
  239. Method HasAction(name:String)
  240. Local ac:TAction = TAction(MapValueForKey(sprite.actions, name))
  241. If ac Return True
  242. Return False
  243. End Method
  244.  
  245. Method rear:Byte()
  246. If animation.direction = "up" Return 0
  247. If animation.direction = "right" Return 1
  248. If animation.direction = "down" Return 2
  249. If animation.direction = "left" Return 3
  250. End Method
  251.  
  252. Method SyncAction(other:TAnimationInstance)
  253. Local ac:TAction = TAction(MapValueForKey(sprite.actions, other.action.name))
  254. If ac
  255. action = ac
  256. playspeed = other.playspeed
  257. animation = TAnimation(MapValueForKey(action.animations, other.animation.direction))
  258. framelink = animation.frames.firstlink()
  259. EndIf
  260. continuous = other.continuous
  261. timepassed = other.timepassed
  262. End Method
  263.  
  264. Method GetAction:String()
  265. Return action.name
  266. End Method
  267.  
  268. Method GetDirection:String()
  269. Return animation.direction
  270. End Method
  271. End Type