UndoRedo poc
This commit is contained in:
parent
3653f2a18d
commit
498554be29
3 changed files with 87 additions and 38 deletions
65
board.gd
65
board.gd
|
@ -3,32 +3,47 @@ extends Node3D
|
|||
|
||||
@export var dims: Vector2i
|
||||
|
||||
var pieces: Dictionary[Vector2i, Array] = {}
|
||||
# idea: board has very little logic, delegates to something else
|
||||
# l8r tho
|
||||
|
||||
# literally just linearly search to find pieces at a position
|
||||
# children
|
||||
|
||||
# todo: Array[Piece]
|
||||
func pieces() -> Array:
|
||||
return get_children()
|
||||
|
||||
func pieces_at(pos: Vector2i) -> Array[Piece]:
|
||||
return pieces.get(pos, [])
|
||||
var out: Array[Piece] = []
|
||||
for piece in get_children():
|
||||
if piece.lpos == pos:
|
||||
out.push_back(piece)
|
||||
return out
|
||||
|
||||
func remove_piece(piece: Piece, from: Vector2i):
|
||||
pieces[from] = pieces_at(from).filter(func (p): return p != piece)
|
||||
func find_piece_at(pos: Vector2i, filter: Callable) -> Piece:
|
||||
var at := pieces_at(pos)
|
||||
var idx := at.find_custom(filter)
|
||||
if idx < 0: return
|
||||
return at[idx]
|
||||
|
||||
func add_piece(piece: Piece, to: Vector2i):
|
||||
pieces.get_or_add(to, []).push_back(piece)
|
||||
piece.position = Vector3(to.x, 0, to.y)
|
||||
func any_at(pos: Vector2i, filter: Callable) -> bool:
|
||||
return pieces_at(pos).any(filter)
|
||||
|
||||
func solid_at(pos: Vector2i) -> bool:
|
||||
return any_at(pos, func(p): return p.type == Piece.Type.Wall or p.type == Piece.Type.Box)
|
||||
|
||||
func passable_at(pos: Vector2i) -> bool:
|
||||
return not solid_at(pos)
|
||||
|
||||
func remove_piece(piece: Piece):
|
||||
remove_child(piece)
|
||||
|
||||
func add_piece(piece: Piece):
|
||||
add_child(piece)
|
||||
|
||||
func add_pieces(piece: Array[Piece], to: Vector2i):
|
||||
func add_pieces(piece: Array[Piece]):
|
||||
for p in piece:
|
||||
add_piece(p, to)
|
||||
|
||||
func do_move(piece: Piece, from: Vector2i, to: Vector2i) -> Callable:
|
||||
return func():
|
||||
remove_piece(piece, from)
|
||||
add_piece(piece, to)
|
||||
|
||||
func undo_move(piece: Piece, from: Vector2i, to: Vector2i) -> Callable:
|
||||
return func():
|
||||
remove_piece(piece, to)
|
||||
add_piece(piece, from)
|
||||
add_piece(p)
|
||||
|
||||
static func from_string(src: String) -> Board:
|
||||
var lines := src.lstrip("\n").rstrip("\n").split("\n")
|
||||
|
@ -48,10 +63,10 @@ static func from_string(src: String) -> Board:
|
|||
var c := line[x]
|
||||
var pos := Vector2i(x, y)
|
||||
match c:
|
||||
".": board.add_piece(Piece.goal(), pos)
|
||||
"*": board.add_pieces([Piece.goal(), Piece.box()], pos)
|
||||
"+": board.add_pieces([Piece.goal(), Piece.player()], pos)
|
||||
"$": board.add_piece(Piece.box(), pos)
|
||||
"@": board.add_piece(Piece.player(), pos)
|
||||
"#": board.add_piece(Piece.wall(), pos)
|
||||
".": board.add_piece(Piece.goal(pos))
|
||||
"*": board.add_pieces([Piece.goal(pos), Piece.box(pos)])
|
||||
"+": board.add_pieces([Piece.goal(pos), Piece.player(pos)])
|
||||
"$": board.add_piece(Piece.box(pos))
|
||||
"@": board.add_piece(Piece.player(pos))
|
||||
"#": board.add_piece(Piece.wall(pos))
|
||||
return board
|
||||
|
|
24
main.gd
24
main.gd
|
@ -13,9 +13,14 @@ var microban_1 := "
|
|||
var hist := UndoRedo.new()
|
||||
|
||||
@onready var board := Board.from_string(microban_1)
|
||||
var player: Piece
|
||||
|
||||
func _ready() -> void:
|
||||
add_child(board)
|
||||
for piece in board.pieces():
|
||||
if piece.type == Piece.Type.Player:
|
||||
player = piece
|
||||
break
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("u"):
|
||||
|
@ -29,7 +34,6 @@ func _input(event: InputEvent) -> void:
|
|||
elif event.is_action_pressed("undo"):
|
||||
hist.undo()
|
||||
elif event.is_action_pressed("redo"):
|
||||
print('hi')
|
||||
hist.redo()
|
||||
elif event.is_action_pressed("restart"):
|
||||
restart()
|
||||
|
@ -39,6 +43,18 @@ func restart():
|
|||
pass
|
||||
|
||||
func step(move: Vector2i):
|
||||
hist.create_action("move")
|
||||
|
||||
hist.commit_action()
|
||||
var pos := player.lpos
|
||||
var box := board.find_piece_at(pos + move, func(p): return p.type == Piece.Type.Box)
|
||||
if board.passable_at(pos + move):
|
||||
hist.create_action("move")
|
||||
hist.add_do_method(player.do_move(move))
|
||||
hist.add_undo_method(player.undo_move())
|
||||
hist.commit_action()
|
||||
elif box != null and board.passable_at(pos + move * 2):
|
||||
hist.create_action("push")
|
||||
hist.add_do_method(player.do_move(move))
|
||||
hist.add_do_method(box.do_move(move))
|
||||
hist.add_undo_method(player.undo_move())
|
||||
hist.add_undo_method(box.undo_move())
|
||||
hist.commit_action()
|
||||
|
||||
|
|
36
piece.gd
36
piece.gd
|
@ -13,22 +13,40 @@ enum Type {
|
|||
Player,
|
||||
}
|
||||
|
||||
# logical position
|
||||
@export var lpos: Vector2i:
|
||||
get:
|
||||
return lpos
|
||||
set(val):
|
||||
lpos = val
|
||||
position = Vector3(val.x, 0, val.y)
|
||||
|
||||
@export var type: Piece.Type
|
||||
|
||||
static func make(type: Piece.Type, mesh: Mesh) -> Piece:
|
||||
func do_move(move: Vector2i) -> Callable:
|
||||
return func():
|
||||
lpos += move
|
||||
|
||||
func undo_move() -> Callable:
|
||||
var old_pos := lpos
|
||||
return func():
|
||||
lpos = old_pos
|
||||
|
||||
static func make(lpos: Vector2i, type: Piece.Type, mesh: Mesh) -> Piece:
|
||||
var piece := Piece.new()
|
||||
piece.lpos = lpos
|
||||
piece.mesh = mesh
|
||||
piece.type = type
|
||||
return piece
|
||||
|
||||
static func wall() -> Piece:
|
||||
return make(Piece.Type.Wall, WALL)
|
||||
static func wall(lpos: Vector2i) -> Piece:
|
||||
return make(lpos, Piece.Type.Wall, WALL)
|
||||
|
||||
static func goal() -> Piece:
|
||||
return make(Piece.Type.Goal, GOAL)
|
||||
static func goal(lpos: Vector2i) -> Piece:
|
||||
return make(lpos, Piece.Type.Goal, GOAL)
|
||||
|
||||
static func box() -> Piece:
|
||||
return make(Piece.Type.Box, BOX)
|
||||
static func box(lpos: Vector2i) -> Piece:
|
||||
return make(lpos, Piece.Type.Box, BOX)
|
||||
|
||||
static func player() -> Piece:
|
||||
return make(Piece.Type.Player, PLAYER)
|
||||
static func player(lpos: Vector2i) -> Piece:
|
||||
return make(lpos, Piece.Type.Player, PLAYER)
|
||||
|
|
Loading…
Reference in a new issue