extends Node signal can_leave var playing = false onready var player_fab = preload('res://scenes/game1/Player.tscn') var player : AnimatedSprite var player_camera : Camera2D onready var dialogue_box = $UI/Dialog export (String, FILE, '*.json') var dialogue onready var music_player = get_node('/root/MusicPlayer') as MusicPlayer onready var levels = [ #'TestLogEntity', 'Level1', 'Level2', 'Level3', 'Level4', 'Level5', ] export var skipToLevel = '' var current_level = -1 var spawn_pos = Vector2() var exit_points = [] var can_leave = false func _ready(): assert(dialogue != null) if skipToLevel != '': can_leave = true $Opening1.queue_free() start_game() while levels[current_level] != skipToLevel: next_level() return yield(get_tree().create_timer(6), "timeout") music_player.play("Chris Zabriskie - Direct to Video - 03 I Don't See the Branches, I See the Leaves") $Opening1.play('default') $Opening1/Mask.play('default') $Opening1/OpeningOver.play('default') yield($Opening1, 'animation_finished') $Opening1.queue_free() $Opening2/Player.sleep = false yield(dialogue_box.start_dialogue(dialogue), 'end') can_leave = true emit_signal("can_leave") func start_game(): $Opening2/Player.sleep = true if !can_leave: yield(self, 'can_leave') # Hide opening $Opening2.queue_free() next_level() func next_level(): if current_level >= 0: var level = $Game.get_node(levels[current_level]) level.queue_free() current_level += 1 if current_level >= levels.size(): get_tree().change_scene("res://scenes/oil_tanker.tscn") return # Prepare level var level = load("res://scenes/game1/" + levels[current_level] + ".tscn").instance() $Game.add_child(level) spawn_entities(level) # Prepare player player = player_fab.instance() player_camera = player.get_node("Camera2D") level.add_child_below_node(level.get_node("Entities"), player) playing = true player_camera.make_current() player.connect('frame_changed', self, 'update_camera') # Spawn player player.position = spawn_pos * 16 + Vector2(8, 8) func spawn_entities(level : Node): exit_points = [] var entities = Node2D.new() entities.name = 'Entities' level.add_child_below_node(level.get_node('Props'), entities) for layer in level.get_children(): if !(layer is TileMap): continue var tm = layer as TileMap var tileset = tm.tile_set # Flatfish var fishes = [] for tile in ['flatfish_s', 'flatfish_s_hidden', 'flatfish_t', 'flatfish_t_hidden']: fishes += tm.get_used_cells_by_id(tileset.find_tile_by_name(tile)) for cell in fishes: var fish = Flatfish.new() fish.position = cell * 16 + Vector2(8, 8) var t = tm.is_cell_transposed(cell.x, cell.y) var x = tm.is_cell_x_flipped(cell.x, cell.y) var y = tm.is_cell_y_flipped(cell.x, cell.y) if t && x: fish.rotation_degrees = 90 elif x && y: fish.rotation_degrees = 180 elif t && y: fish.rotation_degrees = 270 entities.add_child(fish) tm.set_cell(cell.x, cell.y, -1) # Spawn point for cell in tm.get_used_cells_by_id(tileset.find_tile_by_name('start')): spawn_pos = cell tm.set_cell(cell.x, cell.y, -1) # Exit points for cell in tm.get_used_cells_by_id(tileset.find_tile_by_name('finish')): exit_points.append(cell) # Logs for d in ['horizontal', 'vertical']: for i in [1, 2, 3, 4]: for cell in tm.get_used_cells_by_id(tileset.find_tile_by_name('log_' + d + '_' + String(i))): var log_entity = LogEntity.new(LogEntity.Type.H if d == 'horizontal' else LogEntity.Type.V, i - 1) log_entity.spawn_at(cell * 16 + Vector2(16, 16)) entities.add_child(log_entity) tm.set_cell(cell.x, cell.y, -1) var go_right = false var go_left = false var do_interact = false func _input(event): if playing: if event.is_action_pressed('right'): go_right = true if event.is_action_pressed('left'): go_left = true if event.is_action_pressed('interact'): do_interact = true if event.is_action_released('right'): go_right = false if event.is_action_released('left'): go_left = false if event.is_action_released('interact'): do_interact = false var trying_to_move = false func move(): if !playing || trying_to_move || is_interacting || is_camera_moving: return trying_to_move = true yield(get_tree(), "physics_frame") yield(get_tree(), "physics_frame") if go_right && !go_left && can_move_towards('Right'): move_right() elif go_left && !go_right && can_move_towards('Left'): move_left() trying_to_move = false func _process(_delta): interact() move() func can_move_towards(sensorName : String) -> bool: var sensor = player.get_node("Sensors/" + sensorName) as Area2D var bodies = sensor.get_overlapping_bodies() var areas = sensor.get_overlapping_areas() # Check for pushables and push for body in bodies + areas: var p = body.get_parent() if p is LogEntity: var rot = int(floor(player.rotation_degrees / 90.0)) % 4 var dir = 1 if (rot == 0 || rot == 1) && sensorName == 'Right' || (rot == 2 || rot == 3) && sensorName == 'Left' else -1 # Push and fall if p.push((player.position / 16) - Vector2(0.5, 0.5), dir): var level = $Game.get_node(levels[current_level]) var pos = (p.position / 16) - Vector2(1, 1) for layer in level.get_children(): if !(layer is TileMap): continue var tm = layer as TileMap var tileset = tm.tile_set var name = tileset.tile_get_name(tm.get_cellv(pos)) if name != null && name.rfind('hole_') == 0: tm.set_cellv(pos, tileset.find_tile_by_name("log_in_" + name), tm.is_cell_x_flipped(pos.x, pos.y), tm.is_cell_y_flipped(pos.x, pos.y), tm.is_cell_transposed(pos.x, pos.y)) p.queue_free() return bodies.size() == 0 && areas.size() == 0 func move_right(): is_camera_moving = true player.play('moving') update_camera() yield(player, 'animation_finished') player.play('default') player.frame = 0 offset_player(16) is_camera_moving = false if !check_exit(): move() func move_left(): is_camera_moving = true offset_player(-16) player.play('moving', true) update_camera() yield(player, 'animation_finished') player.play('default') player.frame = 0 is_camera_moving = false if !check_exit(): move() func check_exit() -> bool: var player_pos = (player.position - Vector2(8, 8)) / 16 if !Globals.ui_interact_flatfish_tip: var level = $Game.get_node(levels[current_level]) var shown = false for e in level.get_node('Entities').get_children(): if e is Flatfish && e.position == player.position: $GameControlIndicator.show_press('interact') $GameControlIndicator.position = player.position + Vector2(0, 8 + 16) shown = true break if !shown: $GameControlIndicator.hide() print(player_pos) for exit in exit_points: if player_pos == exit: print('exit') next_level() return true return false func offset_player(offset): var r = int(ceil(player.rotation_degrees / 90.0)) % 4 if r == 0: player.position.x += offset elif r == 1: player.position.y += offset elif r == 2: player.position.x -= offset elif r == 3: player.position.y -= offset const animation_steps = [3, 6, 10, 13] var is_camera_moving = false func update_camera(): if is_camera_moving && !is_interacting: player_camera.position = Vector2(animation_steps[player.frame], 0) else: player_camera.position = Vector2() var is_interacting = false func interact(): if !playing || !do_interact || is_interacting || trying_to_move || is_camera_moving: return is_interacting = true var level = $Game.get_node(levels[current_level]) var entities = level.get_node('Entities').get_children() var fish = null for e in entities: if e is Flatfish && e.position == player.position: fish = e break if fish != null: Globals.ui_interact_flatfish_tip = true $GameControlIndicator.hide() fish.appear() yield(get_tree().create_timer(0.2), "timeout") fish.do_rotation() player.rotation_degrees += 45 yield(get_tree().create_timer(0.2), "timeout") fish.do_rotation() player.rotation_degrees += 45 yield(get_tree().create_timer(0.2), "timeout") fish.disappear() player.rotation_degrees = fmod(player.rotation_degrees, 360.0) is_interacting = false if fish != null: interact()