ygdra/screen/exploration_screen.gd

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()