crabs-game/scripts/game1/Game1Script.gd

298 lines
7.8 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 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 != '':
$Opening1.queue_free()
start_game()
while levels[current_level] != skipToLevel:
next_level()
return
yield(get_tree().create_timer(6), "timeout")
$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()
is_interacting = false
if fish != null: interact()