animated_sprite.nim 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. # author: Ethosa
  2. ## It provides display animated sprites.
  3. import
  4. ../thirdparty/opengl,
  5. ../core/vector2,
  6. ../core/rect2,
  7. ../core/anchor,
  8. ../core/input,
  9. ../core/enums,
  10. ../core/image,
  11. ../core/color,
  12. ../core/animation,
  13. ../nodes/node,
  14. node2d
  15. type
  16. AnimatedSpriteObj* = object of Node2DObj
  17. reversed*, paused*: bool
  18. filter*: ColorRef
  19. animation*: string
  20. animations*: AnimationArray[GlTextureObj]
  21. AnimatedSpritePtr* = ptr AnimatedSpriteObj
  22. proc AnimatedSprite*(name: string, variable: var AnimatedSpriteObj): AnimatedSpritePtr =
  23. ## Creates a new AnimatedSprite pointer.
  24. ##
  25. ## Arguments:
  26. ## - `name` is a node name.
  27. ## - `variable` is a AnimatedSpriteObj variable.
  28. runnableExamples:
  29. var
  30. node_obj: AnimatedSpriteObj
  31. node = AnimatedSprite("AnimatedSprite", node_obj)
  32. nodepattern(AnimatedSpriteObj)
  33. node2dpattern()
  34. variable.filter = Color(1f, 1f, 1f)
  35. variable.animations = @[Animation[GlTextureObj]("default", 2f)]
  36. variable.animation = "default"
  37. variable.paused = true
  38. variable.reversed = false
  39. variable.kind = ANIMATED_SPRITE_NODE
  40. proc AnimatedSprite*(obj: var AnimatedSpriteObj): AnimatedSpritePtr {.inline.} =
  41. ## Creates a new AnimatedSprite pointer with default node name "AnimatedSprite".
  42. ##
  43. ## Arguments:
  44. ## - `variable` is a AnimatedSpriteObj variable.
  45. runnableExamples:
  46. var
  47. node_obj: AnimatedSpriteObj
  48. node = AnimatedSprite(node_obj)
  49. AnimatedSprite("AnimatedSprite", obj)
  50. method draw*(self: AnimatedSpritePtr, w, h: GLfloat) =
  51. ## this method uses in the `window.nim`.
  52. {.warning[LockLevel]: off.}
  53. let
  54. frame = self.animations[self.animation].frame
  55. frames_count = self.animations[self.animation].frames.len()
  56. if frame >= 0 and frame < frames_count:
  57. var texture = self.animations[self.animation].frames[frame]
  58. if texture.texture > 0:
  59. self.rect_size = texture.size
  60. # Recalculate position.
  61. self.position = self.timed_position
  62. if self.centered:
  63. self.position = self.timed_position - self.rect_size/2
  64. else:
  65. self.position = self.timed_position
  66. let
  67. x = -w/2 + self.global_position.x
  68. y = h/2 - self.global_position.y
  69. # Draw frame
  70. if frame >= 0 and frame < frames_count:
  71. var texture = self.animations[self.animation].frames[frame]
  72. if texture.texture > 0:
  73. if self.centered:
  74. glTranslatef(x + (self.rect_size.x / 2), y - (self.rect_size.y / 2), self.z_index_global)
  75. self.position = self.rect_size / 2
  76. else:
  77. glTranslatef(x, y, self.z_index_global)
  78. self.position = Vector2()
  79. glRotatef(self.rotation, 0, 0, 1)
  80. glColor4f(self.filter.r, self.filter.g, self.filter.b, self.filter.a)
  81. glEnable(GL_TEXTURE_2D)
  82. glEnable(GL_DEPTH_TEST)
  83. glBindTexture(GL_TEXTURE_2D, texture.texture)
  84. glBegin(GL_QUADS)
  85. glTexCoord2f(0, 0)
  86. glVertex3f(-self.position.x, self.position.y, self.z_index_global)
  87. glTexCoord2f(0, 1)
  88. glVertex3f(-self.position.x, self.position.y - self.rect_size.y, self.z_index_global)
  89. glTexCoord2f(1, 1)
  90. glVertex3f(-self.position.x + self.rect_size.x, self.position.y - self.rect_size.y, self.z_index_global)
  91. glTexCoord2f(1, 0)
  92. glVertex3f(-self.position.x + self.rect_size.x, self.position.y, self.z_index_global)
  93. glEnd()
  94. glDisable(GL_DEPTH_TEST)
  95. glDisable(GL_TEXTURE_2D)
  96. glRotatef(-self.rotation, 0, 0, 1)
  97. if self.centered:
  98. glTranslatef(-x - (self.rect_size.x / 2), -y + (self.rect_size.y / 2), -self.z_index_global)
  99. self.position = self.timed_position - self.rect_size/2
  100. else:
  101. glTranslatef(-x, -y, -self.z_index_global)
  102. self.position = self.timed_position
  103. else:
  104. self.rect_size = Vector2()
  105. # Change frame
  106. if not self.paused:
  107. if self.animations[self.animation].current < 60f:
  108. self.animations[self.animation].current += self.animations[self.animation].speed
  109. else:
  110. self.animations[self.animation].current = 0f
  111. if self.reversed:
  112. if frame - 1 < 0:
  113. self.animations[self.animation].frame = frames_count-1
  114. else:
  115. self.animations[self.animation].frame -= 1
  116. else:
  117. if frame + 1 > frames_count-1:
  118. self.animations[self.animation].frame = 0
  119. else:
  120. self.animations[self.animation].frame += 1
  121. method duplicate*(self: AnimatedSpritePtr, obj: var AnimatedSpriteObj): AnimatedSpritePtr {.base.} =
  122. ## Duplicates AnimatedSprite object and create a new AnimatedSprite pointer.
  123. obj = self[]
  124. obj.addr
  125. method getGlobalMousePosition*(self: AnimatedSpritePtr): Vector2Ref {.inline.} =
  126. ## Returns mouse position.
  127. Vector2Ref(x: last_event.x, y: last_event.y)
  128. method addAnimation*(self: AnimatedSpritePtr, name: string, speed: float = 2f) {.base.} =
  129. ## Adds a new animation to the AnimatedSprite animations.
  130. ##
  131. ## Arguments:
  132. ## - `name` is an animation name.
  133. ## - `speed` is an animation speed.
  134. var newanim = Animation[GlTextureObj](name, speed)
  135. if newanim notin self.animations:
  136. self.animations.add(newanim)
  137. method addFrame*(self: AnimatedSpritePtr, name: string, frame: GlTextureObj) {.base.} =
  138. ## Adds a new frame in the animation.
  139. ##
  140. ## Arguments:
  141. ## - `name` is an animation name.
  142. self.animations[name].addFrame(frame)
  143. method removeAnimation*(self: AnimatedSpritePtr, name: string) {.base.} =
  144. ## Deletes animation from the AnimatedSprite animations.
  145. ## If `name` is a current animation name, then animation will not delete.
  146. ##
  147. ## Arguments:
  148. ## - `name` is an animation name.
  149. if name == self.animation:
  150. return
  151. for i in 0..self.animations.high:
  152. if self.animations[i].name == name:
  153. self.animations.delete(i)
  154. break
  155. method pause*(self: AnimatedSpritePtr) {.base.} =
  156. ## Stops animation.
  157. self.paused = true
  158. method play*(self: AnimatedSpritePtr, name: string = "", backward: bool = false) {.base.} =
  159. ## Plays animation.
  160. ##
  161. ## Arguments:
  162. ## - `name` is an animation name. if it is "" than plays current animation.
  163. ## - if `backward` is true then plays animation in reverse order.
  164. if name != "":
  165. self.animation = name
  166. self.reversed = backward
  167. self.animations[self.animation].current = 0f
  168. if self.reversed:
  169. self.animations[self.animation].frame = self.animations[self.animation].frames.len()-1
  170. else:
  171. self.animations[self.animation].frame = 0
  172. self.paused = false
  173. method resume*(self: AnimatedSpritePtr) {.base.} =
  174. ## Resumes animation.
  175. self.paused = false
  176. method setSpeed*(self: AnimatedSpritePtr, name: string = "", speed: float = 2f) {.base.} =
  177. ## Changes animation speed.
  178. ## If `name` is "" then changes the speed of the current animation.
  179. ##
  180. ## Arguments:
  181. ## - `name` is an animation name.
  182. ## - `speed` is a new speed.
  183. if name == "":
  184. self.animations[self.animation].speed = speed
  185. else:
  186. self.animations[name].speed = speed