Player.gd 3.3 KB

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