extends Area2D # Handle player logic and events signal crash signal arena_removed enum Direction { UP = 0 RIGHT = 1 DOWN = 2 LEFT = 3 } enum Side { LEFT = -1 RIGHT = 1 } const cell_size = 64 const cell_half_size = 32 const LEVEL_SPAWN_DURATION = 2 # State var running = false var landed = false # Movement var posix var posiy var dirx = 0 var diry = 0 var dire = 0 var dire_delta = 0 var target_pos # Controls var turn_left_action:String var turn_right_action:String var grid:TileMap onready var tween = $Tween func _ready(): assert(turn_left_action) assert(turn_right_action) tween.connect_into(self) func _unhandled_input(event): if event.is_pressed(): if event.is_action(turn_left_action): prepare_turn(Side.LEFT) get_tree().set_input_as_handled() elif event.is_action(turn_right_action): prepare_turn(Side.RIGHT) get_tree().set_input_as_handled() func _on_round_start(): assert(grid) run() func _on_round_won(): stop() func _on_arena_removed(): grid = null landed = false emit_signal("arena_removed") func _on_tween_completed(_o, key): if (key == ":position"): move() func _on_crash(body): if landed and running: stop() emit_signal("crash") func spawn(newGrid, newPosition, newOrientation): # Update arena grid = newGrid # Adjust spawn situation dire_delta = 0 posix = int (newPosition.x / cell_size) posiy = int (newPosition.y / cell_size) dire = int((newOrientation + 45) / 90) apply_turn() # Animate spawning tween.rotate_char(self, rotation_degrees, newOrientation, LEVEL_SPAWN_DURATION) tween.move_char(self, newPosition, LEVEL_SPAWN_DURATION) tween.start() func generate_wall(): # TODO : use enum for blocks grid.set_cell(posix - dirx, posiy - diry, 1) func prepare_turn(left_or_right:int): if !running: return var current_angle = (dire + dire_delta) * 90 dire_delta += left_or_right if dire_delta > Side.RIGHT: dire_delta = Side.RIGHT return elif dire_delta < Side.LEFT: dire_delta = Side.LEFT return var aim_angle = current_angle + 90 * left_or_right tween.rotate_char(self, current_angle, aim_angle) tween.start() func can_turn(): return dire_delta != 0 and !has_block_on(dire_delta) func apply_turn(): dire += dire_delta dire_delta = 0 if dire < 0: dire = 3 elif dire > 3: dire = 0 dirx = 0 diry = 0 if dire == Direction.UP: diry -= 1 elif dire == Direction.RIGHT: dirx += 1 elif dire == Direction.DOWN: diry += 1 elif dire == Direction.LEFT: dirx -= 1 else: push_error("dire out of range") func move(): if !running: return generate_wall() if can_turn(): apply_turn() go_forward() func go_forward(): posix += dirx posiy += diry target_pos = Vector2(posix * cell_size + cell_half_size, posiy * cell_size + cell_half_size) tween.move_char(self, target_pos) tween.start() func has_block_on(left_or_right:int): var bposx:int = posix - diry * left_or_right var bposy:int = posiy + dirx * left_or_right # TODO : use enum for blocks return grid.get_cell(bposx, bposy) == 1 func stop(): if running: remove_from_group("running") generate_wall() running = false func run(): landed = true # TODO : land at game signal `land` running = true add_to_group("running") move() func is_running(): return running