Advertisement
dragnoz

Defold - hero script exanple

Feb 19th, 2017
478
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.11 KB | None | 0 0
  1. -- these are the tweaks for the mechanics, feel free to change them for a different feeling
  2. -- the acceleration to move right/left
  3. local move_acceleration = 3500
  4. -- acceleration factor to use when air-borne
  5. local air_acceleration_factor = 0.8
  6. -- max speed right/left
  7. local max_speed = 400
  8. -- gravity pulling the player down in pixel units
  9. local gravity = -1100
  10. -- take-off speed when jumping in pixel units
  11. local jump_takeoff_speed = 700
  12. -- time within a double tap must occur to be considered a jump (only used for mouse/touch controls)
  13. local touch_jump_timeout = 0.2
  14.  
  15. -- pre-hashing ids improves performance
  16. local msg_contact_point_response = hash("contact_point_response")
  17. local msg_animation_done = hash("animation_done")
  18. local group_geometry = hash("geometry")
  19. local input_left = hash("left")
  20. local input_right = hash("right")
  21. local input_jump = hash("jump")
  22. local input_touch = hash("touch")
  23. local anim_run = hash("run")
  24. local anim_idle = hash("idle")
  25. local anim_jump = hash("jump")
  26. local anim_fall = hash("fall")
  27.  
  28. function init(self)
  29. -- this lets us handle input in this script
  30. msg.post(".", "acquire_input_focus")
  31.  
  32. -- initial player velocity
  33. self.velocity = vmath.vector3(0, 0, 0)
  34. -- support variable to keep track of collisions and separation
  35. self.correction = vmath.vector3()
  36. -- if the player stands on ground or not
  37. self.ground_contact = false
  38. -- movement input in the range [-1,1]
  39. self.move_input = 0
  40. -- character direction, for anim selection (-1 or 1)
  41. self.direction = 1
  42. -- the currently playing animation
  43. self.anim = nil
  44. -- timer that controls the jump-window when using mouse/touch
  45. self.touch_jump_timer = 0
  46. end
  47.  
  48. local function play_animation(self, anim)
  49. -- only play animations which are not already playing
  50. if self.anim ~= anim then
  51. -- tell the sprite to play the animation
  52. msg.post("#sprite", "play_animation", {id = anim})
  53. -- remember which animation is playing
  54. self.anim = anim
  55. end
  56. end
  57.  
  58. local function update_animations(self)
  59. -- make sure the player character faces the right way
  60. sprite.set_hflip("#sprite", self.direction < 0)
  61. -- make sure the right animation is playing
  62. if self.ground_contact then
  63. if self.velocity.x == 0 then
  64. play_animation(self, anim_idle)
  65. else
  66. play_animation(self, anim_run)
  67. end
  68. else
  69. if self.velocity.y > 0 then
  70. play_animation(self, anim_jump)
  71. else
  72. play_animation(self, anim_fall)
  73. end
  74. end
  75. end
  76.  
  77. function update(self, dt)
  78. -- determine the target speed based on input
  79. local target_speed = self.move_input * max_speed
  80. -- calculate the difference between our current speed and the target speed
  81. local speed_diff = target_speed - self.velocity.x
  82. -- the complete acceleration to integrate over this frame
  83. local acceleration = vmath.vector3(0, gravity, 0)
  84. if speed_diff ~= 0 then
  85. -- set the acceleration to work in the direction of the difference
  86. if speed_diff < 0 then
  87. acceleration.x = -move_acceleration
  88. else
  89. acceleration.x = move_acceleration
  90. end
  91. -- decrease the acceleration when air-borne to give a slower feel
  92. if not self.ground_contact then
  93. acceleration.x = air_acceleration_factor * acceleration.x
  94. end
  95. end
  96. -- calculate the velocity change this frame (dv is short for delta-velocity)
  97. local dv = acceleration * dt
  98. -- check if dv exceeds the intended speed difference, clamp it in that case
  99. if math.abs(dv.x) > math.abs(speed_diff) then
  100. dv.x = speed_diff
  101. end
  102. -- save the current velocity for later use
  103. -- (self.velocity, which right now is the velocity used the previous frame)
  104. local v0 = self.velocity
  105. -- calculate the new velocity by adding the velocity change
  106. self.velocity = self.velocity + dv
  107. -- calculate the translation this frame by integrating the velocity
  108. local dp = (v0 + self.velocity) * dt * 0.5
  109. -- apply it to the player character
  110. go.set_position(go.get_position() + dp)
  111.  
  112. -- update the jump timer
  113. if self.touch_jump_timer > 0 then
  114. self.touch_jump_timer = self.touch_jump_timer - dt
  115. end
  116.  
  117. update_animations(self)
  118.  
  119. -- reset volatile state
  120. self.correction = vmath.vector3()
  121. self.move_input = 0
  122. self.ground_contact = false
  123.  
  124. end
  125.  
  126. local function handle_geometry_contact(self, normal, distance)
  127. -- project the correction vector onto the contact normal
  128. -- (the correction vector is the 0-vector for the first contact point)
  129. local proj = vmath.dot(self.correction, normal)
  130. -- calculate the compensation we need to make for this contact point
  131. local comp = (distance - proj) * normal
  132. -- add it to the correction vector
  133. self.correction = self.correction + comp
  134. -- apply the compensation to the player character
  135. go.set_position(go.get_position() + comp)
  136. -- check if the normal points enough up to consider the player standing on the ground
  137. -- (0.7 is roughly equal to 45 degrees deviation from pure vertical direction)
  138. if normal.y > 0.7 then
  139. self.ground_contact = true
  140. end
  141. -- project the velocity onto the normal
  142. proj = vmath.dot(self.velocity, normal)
  143. -- if the projection is negative, it means that some of the velocity points towards the contact point
  144. if proj < 0 then
  145. -- remove that component in that case
  146. self.velocity = self.velocity - proj * normal
  147. end
  148. end
  149.  
  150. function on_message(self, message_id, message, sender)
  151. -- check if we received a contact point message
  152. if message_id == msg_contact_point_response then
  153. -- check that the object is something we consider geometry
  154. if message.group == group_geometry then
  155. handle_geometry_contact(self, message.normal, message.distance)
  156. end
  157. end
  158. end
  159.  
  160. local function jump(self)
  161. -- only allow jump from ground
  162. -- (extend this with a counter to do things like double-jumps)
  163. if self.ground_contact then
  164. -- set take-off speed
  165. self.velocity.y = jump_takeoff_speed
  166. -- play animation
  167. play_animation(self, anim_jump)
  168. end
  169. end
  170.  
  171. local function abort_jump(self)
  172. -- cut the jump short if we are still going up
  173. if self.velocity.y > 0 then
  174. -- scale down the upwards speed
  175. self.velocity.y = self.velocity.y * 0.5
  176. end
  177. end
  178.  
  179. function on_input(self, action_id, action)
  180. if action_id == input_left then
  181. self.move_input = -action.value
  182. self.direction = -1
  183. elseif action_id == input_right then
  184. self.move_input = action.value
  185. self.direction = 1
  186. elseif action_id == input_jump then
  187. if action.pressed then
  188. jump(self)
  189. elseif action.released then
  190. abort_jump(self)
  191. end
  192. elseif action_id == input_touch then
  193. -- move towards the touch-point
  194. local diff = action.x - go.get_position().x
  195. -- update direction
  196. if diff > 0 then
  197. self.direction = 1
  198. else
  199. self.direction = -1
  200. end
  201. -- only give input when far away (more than 10 pixels)
  202. if math.abs(diff) > 10 then
  203. -- slow down when less than 100 pixels away
  204. self.move_input = diff / 100
  205. -- clamp input to [-1,1]
  206. self.move_input = math.min(1, math.max(-1, self.move_input))
  207. end
  208. if action.released then
  209. -- start timing the last release to see if we are about to jump
  210. self.touch_jump_timer = touch_jump_timeout
  211. elseif action.pressed then
  212. -- jump on double tap
  213. if self.touch_jump_timer > 0 then
  214. jump(self)
  215. end
  216. end
  217. end
  218. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement