79 lines
1.6 KiB
GDScript
79 lines
1.6 KiB
GDScript
extends Node3D
|
|
|
|
var microban_1 := "
|
|
####
|
|
# .#
|
|
# ###
|
|
#*@ #
|
|
# $ #
|
|
# ###
|
|
####
|
|
"
|
|
|
|
var states: Array[State] = [State.from_string(microban_1)]
|
|
|
|
const WALL = preload("res://wall.tres")
|
|
const GOAL = preload("res://goal.tres")
|
|
const BOX = preload("res://box.tres")
|
|
|
|
@onready var board: Node3D = $Board
|
|
|
|
func _ready() -> void:
|
|
render()
|
|
|
|
func add_mesh(pos: Vector2i, mesh: Mesh):
|
|
var offset := -current_state().dims/2.0
|
|
var meshinst := MeshInstance3D.new()
|
|
meshinst.position = Vector3(pos.x + offset.x, 0, pos.y + offset.y)
|
|
meshinst.mesh = mesh
|
|
board.add_child(meshinst)
|
|
|
|
func render() -> void:
|
|
var state := current_state()
|
|
for child in board.get_children():
|
|
child.free()
|
|
|
|
for y in state.dims.y:
|
|
for x in state.dims.x:
|
|
var pos := Vector2i(x, y)
|
|
if state.goal_at(pos): add_mesh(pos, GOAL)
|
|
if state.box_at(pos): add_mesh(pos, BOX)
|
|
if state.wall_at(pos) or pos == state.player_pos: add_mesh(pos, WALL)
|
|
|
|
func _input(event: InputEvent) -> void:
|
|
if event.is_action_pressed("u"):
|
|
step(Vector2i.UP)
|
|
elif event.is_action_pressed("d"):
|
|
step(Vector2i.DOWN)
|
|
elif event.is_action_pressed("l"):
|
|
step(Vector2i.LEFT)
|
|
elif event.is_action_pressed("r"):
|
|
step(Vector2i.RIGHT)
|
|
elif event.is_action_pressed("undo"):
|
|
undo()
|
|
elif event.is_action_pressed("redo"):
|
|
pass
|
|
elif event.is_action_pressed("restart"):
|
|
restart()
|
|
|
|
|
|
func current_state() -> State:
|
|
return states[-1]
|
|
|
|
func push_state(state: State):
|
|
states.push_back(state)
|
|
render()
|
|
|
|
func undo():
|
|
if states.size() == 1:
|
|
return
|
|
states.pop_back()
|
|
render()
|
|
|
|
# todo: don't restart multiple times
|
|
func restart():
|
|
push_state(states[0])
|
|
|
|
func step(move: Vector2i):
|
|
push_state(current_state().step(move))
|