Player.gd 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. extends Area2D
  2. # Handle player logic and events
  3. signal crash
  4. signal arena_removed
  5. signal drift_started
  6. signal drift_ended
  7. enum Direction {
  8. UP = 0
  9. RIGHT = 1
  10. DOWN = 2
  11. LEFT = 3
  12. }
  13. enum Side {
  14. LEFT = -1
  15. RIGHT = 1
  16. }
  17. const cell_size = 64
  18. const cell_half_size = 32
  19. const LEVEL_SPAWN_DURATION = 2
  20. # State
  21. var running = false
  22. var drifting = false
  23. var landed = false
  24. # Movement
  25. var posix
  26. var posiy
  27. var dirx = 0
  28. var diry = 0
  29. var dire = 0
  30. var dire_delta = 0
  31. var target_pos
  32. # Controls
  33. var turn_left_action:String
  34. var turn_right_action:String
  35. var grid:TileMap
  36. onready var tween = $Tween
  37. func _ready():
  38. assert(turn_left_action)
  39. assert(turn_right_action)
  40. tween.connect_into(self)
  41. func _unhandled_input(event):
  42. if event.is_pressed():
  43. if event.is_action(turn_left_action):
  44. prepare_turn(Side.LEFT)
  45. get_tree().set_input_as_handled()
  46. elif event.is_action(turn_right_action):
  47. prepare_turn(Side.RIGHT)
  48. get_tree().set_input_as_handled()
  49. func _on_round_start():
  50. assert(grid)
  51. run()
  52. func _on_round_won():
  53. stop()
  54. func _on_arena_removed():
  55. grid = null
  56. landed = false
  57. emit_signal("arena_removed")
  58. func _on_tween_completed(_o, key):
  59. if (key == ":position"):
  60. move()
  61. func _on_crash(body):
  62. if landed and running:
  63. stop()
  64. emit_signal("crash")
  65. func spawn(newGrid, newPosition, newOrientation):
  66. # Update arena
  67. grid = newGrid
  68. # Adjust spawn situation
  69. dire_delta = 0
  70. posix = int (newPosition.x / cell_size)
  71. posiy = int (newPosition.y / cell_size)
  72. dire = int((newOrientation + 45) / 90)
  73. apply_turn()
  74. # Animate spawning
  75. tween.rotate_char(self, rotation_degrees, newOrientation, LEVEL_SPAWN_DURATION)
  76. tween.move_char(self, newPosition, LEVEL_SPAWN_DURATION)
  77. tween.start()
  78. func generate_wall():
  79. # TODO : use enum for blocks
  80. grid.set_cell(posix - dirx, posiy - diry, 1)
  81. func prepare_turn(left_or_right:int):
  82. if !running:
  83. return
  84. var current_angle = (dire + dire_delta) * 90
  85. dire_delta += left_or_right
  86. if dire_delta > Side.RIGHT:
  87. dire_delta = Side.RIGHT
  88. return
  89. elif dire_delta < Side.LEFT:
  90. dire_delta = Side.LEFT
  91. return
  92. var aim_angle = current_angle + 90 * left_or_right
  93. tween.rotate_char(self, current_angle, aim_angle)
  94. tween.start()
  95. func can_turn():
  96. return !has_block_on(dire_delta)
  97. func apply_turn():
  98. dire += dire_delta
  99. dire_delta = 0
  100. if dire < 0:
  101. dire = 3
  102. elif dire > 3:
  103. dire = 0
  104. dirx = 0
  105. diry = 0
  106. if dire == Direction.UP:
  107. diry -= 1
  108. elif dire == Direction.RIGHT:
  109. dirx += 1
  110. elif dire == Direction.DOWN:
  111. diry += 1
  112. elif dire == Direction.LEFT:
  113. dirx -= 1
  114. else:
  115. push_error("dire out of range")
  116. func apply_drift():
  117. if !drifting:
  118. drifting = true
  119. emit_signal("drift_started")
  120. func end_drift():
  121. if drifting:
  122. drifting = false
  123. emit_signal("drift_ended")
  124. func move():
  125. if !running:
  126. return
  127. generate_wall()
  128. if is_transversal():
  129. if can_turn():
  130. end_drift()
  131. apply_turn()
  132. else:
  133. apply_drift()
  134. else:
  135. end_drift()
  136. go_forward()
  137. func go_forward():
  138. posix += dirx
  139. posiy += diry
  140. target_pos = Vector2(posix * cell_size + cell_half_size, posiy * cell_size + cell_half_size)
  141. tween.move_char(self, target_pos)
  142. tween.start()
  143. func has_block_on(left_or_right:int):
  144. var bposx:int = posix - diry * left_or_right
  145. var bposy:int = posiy + dirx * left_or_right
  146. # TODO : use enum for blocks
  147. return grid.get_cell(bposx, bposy) == 1
  148. func stop():
  149. if running:
  150. remove_from_group("running")
  151. generate_wall()
  152. running = false
  153. func run():
  154. landed = true # TODO : land at game signal `land`
  155. running = true
  156. add_to_group("running")
  157. move()
  158. func is_running():
  159. return running
  160. func is_transversal():
  161. return dire_delta != 0