123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- extends Area2D
- # Handle liner logic and events
- signal crash
- signal arena_removed
- signal drift_started
- signal drift_ended
- 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: bool = false
- var drifting: bool = false
- var landed: bool = 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 mover = $Mover
- func _ready():
- assert(turn_left_action)
- assert(turn_right_action)
- 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_move_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
- mover.rotate_char_during(self, rotation_degrees, newOrientation, LEVEL_SPAWN_DURATION)
- mover.move_char_during(self, newPosition, LEVEL_SPAWN_DURATION)
- mover.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
- mover.rotate_char(self, current_angle, aim_angle)
- mover.start()
- func can_turn():
- return !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 apply_drift():
- if !drifting:
- drifting = true
- emit_signal("drift_started")
- func end_drift():
- if drifting:
- drifting = false
- emit_signal("drift_ended")
- func apply_wall_boost():
- var n := 0
- if has_block_on(Side.LEFT):
- n += 1
- if has_block_on(Side.RIGHT):
- n += 1
- mover.set_boost(n)
- func end_wall_boost():
- mover.set_boost(0)
- func move():
- if !running:
- return
- generate_wall()
- if is_transversal():
- if can_turn():
- end_drift()
- apply_turn()
- else:
- apply_drift()
- end_wall_boost()
- else:
- end_drift()
- apply_wall_boost()
- go_forward()
- func go_forward():
- posix += dirx
- posiy += diry
- target_pos = Vector2(posix * cell_size + cell_half_size, posiy * cell_size + cell_half_size)
- mover.move_char(self, target_pos)
- mover.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()
- end_wall_boost()
- running = false
- func run():
- landed = true # TODO : land at game signal `land`
- running = true
- add_to_group("running")
- move()
- func is_running():
- return running
- func is_linear():
- return dire_delta == 0
- func is_transversal():
- return !is_linear()
|