I want to add an undo button to my tile-based puzzle game to undo movement actions one at a time. I'm a bit of a beginner, so the documentation has been daunting to me so far. I know of the existence of UndoRedo, but I'm not quite sure how to use it. How would I implement this feature?
extends CharacterBody2D
@onready var raycast = $"Raycast"
@onready var animated_sprite_2d = $AnimatedSprite2D
@onready var audio_stream_player_2d = $AudioStreamPlayer2D
@onready var game_manager: Node = %"Game Manager"
func move(position_x, position_y):
position += Vector2(position_x, position_y)
audio_stream_player_2d.pitch_scale = randf_range(0.9, 1.1)
audio_stream_player_2d.play()
if animated_sprite_2d.frame == 1:
animated_sprite_2d.frame = 0
else:
animated_sprite_2d.frame = 1
func _physics_process(delta):
if game_manager.can_move:
if Input.is_action_just_pressed("up"):
raycast.set_rotation_degrees(0)
raycast.force_raycast_update()
if !raycast.is_colliding():
move(0, -8)
if Input.is_action_just_pressed("down"):
raycast.set_rotation_degrees(180)
raycast.force_raycast_update()
if !raycast.is_colliding():
move(0, 8)
if Input.is_action_just_pressed("left"):
raycast.set_rotation_degrees(270)
raycast.force_raycast_update()
if !raycast.is_colliding():
move(-8, 0)
animated_sprite_2d.flip_h = false
if Input.is_action_just_pressed("right"):
raycast.set_rotation_degrees(90)
raycast.force_raycast_update()
if !raycast.is_colliding():
move(8, 0)
animated_sprite_2d.flip_h = true
It’s a start, but it’s not quite what I’m looking for. Maybe I was a little vague. I’d like to store a list of all the actions taken so that I could undo up to the beginning.
Thanks for your help! What you provided didn’t completely work, but it pointed me toward the solution. I looked into arrays more after seeing you use them and was able to come up with this.
extends CharacterBody2D
@onready var raycast = $"Raycast"
@onready var animated_sprite_2d = $AnimatedSprite2D
@onready var audio_stream_player_2d = $AudioStreamPlayer2D
@onready var game_manager: Node = %"Game Manager"
var last_moves = []
func move(position_x, position_y):
last_moves.append(position)
position += Vector2(position_x, position_y)
audio_stream_player_2d.pitch_scale = randf_range(0.9, 1.1)
audio_stream_player_2d.play()
if animated_sprite_2d.frame == 1:
animated_sprite_2d.frame = 0
else:
animated_sprite_2d.frame = 1
func _physics_process(delta):
if game_manager.can_move:
if Input.is_action_just_pressed("up"):
raycast.set_rotation_degrees(0)
raycast.force_raycast_update()
if !raycast.is_colliding():
move(0, -8)
if Input.is_action_just_pressed("down"):
raycast.set_rotation_degrees(180)
raycast.force_raycast_update()
if !raycast.is_colliding():
move(0, 8)
if Input.is_action_just_pressed("left"):
raycast.set_rotation_degrees(270)
raycast.force_raycast_update()
if !raycast.is_colliding():
move(-8, 0)
animated_sprite_2d.flip_h = false
if Input.is_action_just_pressed("right"):
raycast.set_rotation_degrees(90)
raycast.force_raycast_update()
if !raycast.is_colliding():
move(8, 0)
animated_sprite_2d.flip_h = true
if Input.is_action_just_pressed("undo") and last_moves.size() > 0:
position = last_moves.pop_back()