godot-puzzle/main.gd
2025-04-29 18:14:44 -04:00

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