304 lines
8.1 KiB
GDScript
304 lines
8.1 KiB
GDScript
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()
|