102 lines
3.6 KiB
GDScript
102 lines
3.6 KiB
GDScript
extends AbstractScreen
|
|
|
|
const Wall = preload("res://entity/wall.tscn")
|
|
const Chest = preload("res://entity/chest.tscn")
|
|
|
|
# Member variables
|
|
var level: Maze = null
|
|
var player: MazePlayer = null
|
|
# Dictionary of feature to their 3D representations
|
|
var features = {}
|
|
|
|
# Initialization
|
|
func init(lvl: Maze, pl: MazePlayer):
|
|
level = lvl
|
|
player = pl
|
|
|
|
func _ready():
|
|
# Create walls
|
|
for j in range(level.height):
|
|
for i in range(level.width):
|
|
place_walls(level.at(i, j), i, j)
|
|
place_feature(level.at(i, j), i, j)
|
|
# Place Entrance
|
|
$Root3D/Entrance.transform.origin = map_pos_to_3D_pos(level.entrance.x, level.entrance.y)
|
|
# Place Exit
|
|
$Root3D/Exit.transform.origin = map_pos_to_3D_pos(level.exit.x, level.exit.y)
|
|
# Place player
|
|
$Root3D/Player.teleport_at(map_pos_to_3D_pos(player.position.x, player.position.y))
|
|
$Root3D/Player.turn_at(player.forward_dir)
|
|
# Update the level state
|
|
updateLevelState()
|
|
|
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
|
func _process(_delta):
|
|
if (not $Root3D/Player.in_movement()) and (level.at(player.position.x, player.position.y).feature == Cell.Feature.EXIT):
|
|
emit_signal("next_screen", "end")
|
|
if Input.is_action_just_pressed("ui_menu"):
|
|
emit_signal("next_screen", "end")
|
|
if Input.is_action_just_pressed("ui_accept"):
|
|
emit_signal("next_screen", "map")
|
|
if not $Root3D/Player.in_movement():
|
|
if Input.is_action_pressed("ui_up") and player.can_move_forward(level):
|
|
player.move_forward()
|
|
$Root3D/Player.move_forward()
|
|
updateLevelState()
|
|
elif Input.is_action_pressed("ui_down") and player.can_move_backward(level):
|
|
player.move_backward()
|
|
$Root3D/Player.move_backward()
|
|
updateLevelState()
|
|
elif Input.is_action_pressed("ui_left"):
|
|
player.turn_left()
|
|
$Root3D/Player.turn_left()
|
|
updateLevelState()
|
|
elif Input.is_action_pressed("ui_right"):
|
|
player.turn_right()
|
|
$Root3D/Player.turn_right()
|
|
updateLevelState()
|
|
|
|
func map_pos_to_3D_pos(i, j):
|
|
return Vector3(-(level.width - 1) + 2 * i, 0, -(level.height - 1) + 2 * j)
|
|
|
|
func place_walls(c: Cell, i, j):
|
|
new_wall(c, Direction.NORTH, i, j)
|
|
new_wall(c, Direction.SOUTH, i, j)
|
|
new_wall(c, Direction.EAST, i, j)
|
|
new_wall(c, Direction.WEST, i, j)
|
|
|
|
func new_wall(c: Cell, dir, i, j):
|
|
# Compute position and rotation of the element
|
|
var offset = Vector3(0.9 * Direction.offset_x(dir), 0, 0.9 * Direction.offset_y(dir))
|
|
var wall_position = map_pos_to_3D_pos(i, j) + offset
|
|
var wall_angle = PI/2 * Direction.offset_x(dir)
|
|
if c.get_edge(dir) == Cell.Edge.WALL:
|
|
var wall = Wall.instance()
|
|
wall.translate_object_local(wall_position)
|
|
wall.rotate_object_local(Vector3.UP, wall_angle)
|
|
$Root3D/Walls.add_child(wall)
|
|
|
|
func place_feature(c: Cell, i, j):
|
|
if c.feature == Cell.Feature.CHEST:
|
|
new_chest(c, i, j)
|
|
|
|
func new_chest(c: Cell, i, j):
|
|
var chest = Chest.instance()
|
|
chest.translate_object_local(map_pos_to_3D_pos(i, j))
|
|
$Root3D/Chests.add_child(chest)
|
|
features[Vector2(i, j)] = chest
|
|
|
|
func updateHUD():
|
|
$HUD/NbSteps.text = "Steps: " + str(player.nb_steps)
|
|
$HUD/NbChests.text = "Chests: " + str(player.nb_chests_found)
|
|
|
|
func updateLevelState():
|
|
level.visit(player.position)
|
|
var pos = player.position
|
|
if (level.at(pos.x, pos.y).feature == Cell.Feature.CHEST):
|
|
player.open_chest()
|
|
level.at(pos.x, pos.y).feature = Cell.Feature.NONE
|
|
features.get(pos).queue_free()
|
|
features.erase(pos)
|
|
updateHUD()
|