save/load current game
This commit is contained in:
parent
a44ec0a41b
commit
0c905be6fc
48
src/Main.gd
48
src/Main.gd
|
@ -3,8 +3,56 @@ extends Control
|
||||||
onready var taquin = $HSplitContainer/Taquin
|
onready var taquin = $HSplitContainer/Taquin
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
|
load_game()
|
||||||
print("Starting state: ", taquin.current_state_name())
|
print("Starting state: ", taquin.current_state_name())
|
||||||
|
|
||||||
|
func _notification(what):
|
||||||
|
if what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST:
|
||||||
|
save_game()
|
||||||
|
get_tree().quit() # default behavior
|
||||||
|
|
||||||
|
# https://docs.godotengine.org/en/3.2/tutorials/io/saving_games.html
|
||||||
|
func save_game():
|
||||||
|
var save_game = File.new()
|
||||||
|
save_game.open("user://savegame.save", File.WRITE)
|
||||||
|
var save_nodes = get_tree().get_nodes_in_group("Persist")
|
||||||
|
for node in save_nodes:
|
||||||
|
# Check the node has a save function
|
||||||
|
if !node.has_method("save"):
|
||||||
|
print("persistent node '%s' is missing a save() function, skipped" % node.name)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Call the node's save function
|
||||||
|
var node_data = node.call("save")
|
||||||
|
|
||||||
|
# Augment data with origin
|
||||||
|
node_data["path"] = node.get_path()
|
||||||
|
|
||||||
|
# Store the save dictionary as a new line in the save file
|
||||||
|
save_game.store_line(to_json(node_data))
|
||||||
|
save_game.close()
|
||||||
|
|
||||||
|
func load_game():
|
||||||
|
var save_game = File.new()
|
||||||
|
if not save_game.file_exists("user://savegame.save"):
|
||||||
|
return # Error! We don't have a save to load.
|
||||||
|
|
||||||
|
# Load the file line by line and process that dictionary to restore
|
||||||
|
# the object it represents.
|
||||||
|
save_game.open("user://savegame.save", File.READ)
|
||||||
|
while save_game.get_position() < save_game.get_len():
|
||||||
|
# Get the saved dictionary from the next line in the save file
|
||||||
|
var node_data = parse_json(save_game.get_line())
|
||||||
|
|
||||||
|
# Call the node's save function
|
||||||
|
var node = get_node(node_data["path"])
|
||||||
|
node.call("load", node_data)
|
||||||
|
|
||||||
|
save_game.close()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Signals
|
||||||
|
#
|
||||||
func _on_Taquin_state_changed(previous, new):
|
func _on_Taquin_state_changed(previous, new):
|
||||||
print("Taquin state: ", Taquin.State.keys()[previous], " -> ", Taquin.State.keys()[new])
|
print("Taquin state: ", Taquin.State.keys()[previous], " -> ", Taquin.State.keys()[new])
|
||||||
match new:
|
match new:
|
||||||
|
|
|
@ -34,7 +34,9 @@ __meta__ = {
|
||||||
"_edit_use_anchors_": false
|
"_edit_use_anchors_": false
|
||||||
}
|
}
|
||||||
|
|
||||||
[node name="Taquin" parent="HSplitContainer" instance=ExtResource( 2 )]
|
[node name="Taquin" parent="HSplitContainer" groups=[
|
||||||
|
"Persist",
|
||||||
|
] instance=ExtResource( 2 )]
|
||||||
margin_right = 540.0
|
margin_right = 540.0
|
||||||
margin_bottom = 560.0
|
margin_bottom = 560.0
|
||||||
rows = 4
|
rows = 4
|
||||||
|
|
101
src/Taquin.gd
101
src/Taquin.gd
|
@ -75,27 +75,12 @@ func _ready() -> void:
|
||||||
padding = compute_padding(piece_size)
|
padding = compute_padding(piece_size)
|
||||||
print("piece size: ", piece_size)
|
print("piece size: ", piece_size)
|
||||||
print("padding: ", padding)
|
print("padding: ", padding)
|
||||||
|
var pieces_order: Array = []
|
||||||
for c in range(columns):
|
for order in range(1, rows * columns + 1):
|
||||||
var pieces_row: Array = []
|
pieces_order.append(order)
|
||||||
for r in range(rows):
|
var hidden_piece = rows * columns # Last piece is hidden
|
||||||
var piece = Piece.instance()
|
|
||||||
|
init(pieces_order, hidden_piece)
|
||||||
piece.size = piece_size
|
|
||||||
piece.position = position_for_index(Vector2(c, r), piece.size)
|
|
||||||
piece.order = 1 + c + r * columns
|
|
||||||
piece.taquin_index = Vector2(c, r)
|
|
||||||
piece.piece_scale = Vector2((float(piece_size) / width), (float(piece_size) / height))
|
|
||||||
piece.taquin_position = Vector2(float(piece.position.x) / width, float(piece.position.y) / height)
|
|
||||||
|
|
||||||
if r == rows - 1 && c == columns - 1:
|
|
||||||
piece.visible = false
|
|
||||||
missing_piece = piece
|
|
||||||
|
|
||||||
$Background.add_child(piece)
|
|
||||||
pieces_row.append(piece)
|
|
||||||
|
|
||||||
pieces.append(pieces_row)
|
|
||||||
|
|
||||||
shuffle(difficulty)
|
shuffle(difficulty)
|
||||||
|
|
||||||
|
@ -326,6 +311,80 @@ func transition_to(state):
|
||||||
$Timer.stop()
|
$Timer.stop()
|
||||||
emit_signal("state_changed", previous_state, current_state)
|
emit_signal("state_changed", previous_state, current_state)
|
||||||
|
|
||||||
|
func save() -> Dictionary:
|
||||||
|
var serialized_pieces = []
|
||||||
|
for c in range(columns):
|
||||||
|
for r in range(rows):
|
||||||
|
var piece: Piece = pieces[c][r]
|
||||||
|
serialized_pieces.append(piece.order)
|
||||||
|
return {
|
||||||
|
"rows": rows,
|
||||||
|
"columns": columns,
|
||||||
|
"pieces": serialized_pieces,
|
||||||
|
"hidden_piece": serialized_pieces.size(),
|
||||||
|
}
|
||||||
|
|
||||||
|
func load(saved_state) -> void:
|
||||||
|
if not saved_state.has_all(["rows", "columns", "pieces", "hidden_piece"]):
|
||||||
|
return
|
||||||
|
rows = saved_state["rows"]
|
||||||
|
columns = saved_state["columns"]
|
||||||
|
init(saved_state["pieces"], saved_state["hidden_piece"])
|
||||||
|
|
||||||
|
func init(pieces_order: Array, hidden_piece: int) -> void:
|
||||||
|
var piece_size: int = compute_piece_size()
|
||||||
|
padding = compute_padding(piece_size)
|
||||||
|
print("piece size: ", piece_size)
|
||||||
|
print("padding: ", padding)
|
||||||
|
|
||||||
|
if pieces.size() > 0:
|
||||||
|
for c in range(columns):
|
||||||
|
for r in range(rows):
|
||||||
|
var piece: Piece = pieces[c][r]
|
||||||
|
$Background.remove_child(piece)
|
||||||
|
piece.queue_free()
|
||||||
|
pieces.clear()
|
||||||
|
|
||||||
|
for c in range(columns):
|
||||||
|
var pieces_row: Array = []
|
||||||
|
for r in range(rows):
|
||||||
|
var piece = Piece.instance()
|
||||||
|
# Uniforms
|
||||||
|
piece.size = piece_size
|
||||||
|
piece.piece_scale = Vector2((float(piece_size) / width), (float(piece_size) / height))
|
||||||
|
|
||||||
|
# order start from top-left (1) and iterate over every row
|
||||||
|
# eg. 1 2 3
|
||||||
|
# 4 5 6
|
||||||
|
# 7 8 9
|
||||||
|
piece.order = pieces_order[r + c * rows]
|
||||||
|
print("piece at ", c, ", ", r, " -> order: ", piece.order)
|
||||||
|
|
||||||
|
# place inside the taquin as indices (i, j)
|
||||||
|
piece.taquin_index = Vector2(c, r)
|
||||||
|
# place inside the taquin as coordinates (x, y)
|
||||||
|
piece.position = position_for_index(piece.taquin_index, piece.size)
|
||||||
|
|
||||||
|
# position inside the original taquin as normalized coordinates (x, y) (domain: [0, 1])
|
||||||
|
# used for offsetting the texture on pieces
|
||||||
|
var original_index = Vector2((piece.order - 1) % columns, (piece.order - 1) / columns)
|
||||||
|
var original_position = position_for_index(original_index, piece.size)
|
||||||
|
piece.taquin_position = Vector2(float(original_position.x) / width, float(original_position.y) / height)
|
||||||
|
|
||||||
|
if piece.order == hidden_piece:
|
||||||
|
piece.visible = false
|
||||||
|
missing_piece = piece
|
||||||
|
|
||||||
|
$Background.add_child(piece)
|
||||||
|
pieces_row.append(piece)
|
||||||
|
|
||||||
|
pieces.append(pieces_row)
|
||||||
|
|
||||||
|
shuffle(difficulty)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Signals
|
||||||
|
#
|
||||||
func _on_Timer_timeout():
|
func _on_Timer_timeout():
|
||||||
transition_to(State.GAME_OVER)
|
transition_to(State.GAME_OVER)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue