diff --git a/src/Main.tscn b/src/Main.tscn index 97f2653..443fce3 100644 --- a/src/Main.tscn +++ b/src/Main.tscn @@ -63,6 +63,8 @@ text = "HINTS" [node name="NewGamePanel" parent="." instance=ExtResource( 3 )] [connection signal="state_changed" from="HSplitContainer/Taquin" to="." method="_on_Taquin_state_changed"] [connection signal="pressed" from="HSplitContainer/VSplitContainer/New game" to="." method="_on_New_game_pressed"] +[connection signal="button_down" from="HSplitContainer/VSplitContainer/Hints" to="HSplitContainer/Taquin" method="_on_Hints_button_down"] +[connection signal="button_up" from="HSplitContainer/VSplitContainer/Hints" to="HSplitContainer/Taquin" method="_on_Hints_button_up"] [connection signal="about_to_show" from="NewGamePanel" to="." method="_on_NewGamePanel_about_to_show"] [connection signal="popup_hide" from="NewGamePanel" to="." method="_on_NewGamePanel_popup_hide"] [connection signal="start_triggered" from="NewGamePanel" to="HSplitContainer/Taquin" method="_on_NewGamePanel_start_triggered"] diff --git a/src/Piece.gd b/src/Piece.gd index 7b33e4c..5824b3b 100644 --- a/src/Piece.gd +++ b/src/Piece.gd @@ -5,8 +5,14 @@ extends Node2D export var size: int = 160 var order: int = 0 -var taquin_position := Vector2.ZERO -var taquin_index := Vector2.ZERO +var taquin_original_index := Vector2.ZERO +var taquin_original_position := Vector2.ZERO +var taquin_current_index := Vector2.ZERO # place inside the taquin as indices (i, j) +var taquin_current_position := Vector2.ZERO # place inside the taquin as coordinates (x, y) + +# position inside the original taquin as normalized coordinates (x, y) (domain: [0, 1]) +# used for offsetting the texture on pieces +var taquin_original_normalized_position := Vector2.ZERO var piece_scale := Vector2(0.25, 0.25) func _ready() -> void: @@ -17,7 +23,7 @@ func _ready() -> void: # otherwise uniforms will be shared. var mat = $ColorRect.material.duplicate() as ShaderMaterial mat.set_shader_param("scale", Vector3(piece_scale.x, piece_scale.y, 1.0)) - mat.set_shader_param("offset", Vector3(taquin_position.x, taquin_position.y, 0.0)) + mat.set_shader_param("offset", Vector3(taquin_original_normalized_position.x, taquin_original_normalized_position.y, 0.0)) mat.set_shader_param("reflection", false) $ColorRect.material = mat @@ -27,5 +33,5 @@ func set_reflection(value: bool) -> void: func debug_print(name: String): print("%s order: %s" % [name, order]) - print("%s taquin index: %s" % [name, taquin_index]) + print("%s taquin index: %s" % [name, taquin_current_index]) print("%s taquin position: %s" % [name, position]) diff --git a/src/Piece.tscn b/src/Piece.tscn index f3349a5..086c901 100644 --- a/src/Piece.tscn +++ b/src/Piece.tscn @@ -251,14 +251,13 @@ shader_param/offset = Vector3( 0, 0, 0 ) [node name="Piece" type="Node2D"] script = ExtResource( 1 ) -size = 64 [node name="ColorRect" type="ColorRect" parent="."] material = SubResource( 16 ) anchor_right = 1.0 anchor_bottom = 1.0 -margin_right = 64.0 -margin_bottom = 64.0 +margin_right = 160.0 +margin_bottom = 160.0 __meta__ = { "_edit_use_anchors_": false } diff --git a/src/Taquin.gd b/src/Taquin.gd index c5baa00..5e8be48 100644 --- a/src/Taquin.gd +++ b/src/Taquin.gd @@ -23,8 +23,7 @@ export var columns: int = 4 export var difficulty: int = 10 export(State) var current_state = State.MAIN -var width: int -var height: int +var board_size := Vector2.ZERO var interpiece := 4 var min_padding := 15 var padding := Vector2(min_padding, min_padding) @@ -48,18 +47,22 @@ var current_touch_slide := Vector2.ZERO var local_min_position := Vector2.ZERO var local_max_position := Vector2.ZERO +var _hint_active := false + +onready var hint_tween = $HintTween + func position_for_index(index: Vector2, size: int) -> Vector2: return padding + Vector2(index.x * (size + interpiece), index.y * (size + interpiece)) func compute_piece_size() -> int: - var w_size: int = (width - (2 * min_padding) - ((columns - 1) * interpiece)) / columns - var h_size: int = (height - (2 * min_padding) - ((rows - 1) * interpiece)) / rows + var w_size: int = (board_size.x - (2 * min_padding) - ((columns - 1) * interpiece)) / columns + var h_size: int = (board_size.y - (2 * min_padding) - ((rows - 1) * interpiece)) / rows return int(min(w_size, h_size)) func compute_padding(piece_size: int) -> Vector2: var p = Vector2(0, 0) - p.x = width - columns * piece_size - (columns - 1) * interpiece - p.y = height - rows * piece_size - (rows - 1) * interpiece + p.x = board_size.x - columns * piece_size - (columns - 1) * interpiece + p.y = board_size.y - rows * piece_size - (rows - 1) * interpiece p = p / Vector2(2, 2) return p @@ -68,11 +71,10 @@ func _ready() -> void: $AnimationPlayer/MockPiece.visible = false $Particles2D.emitting = false - width = min(rect_size.x, rect_size.y) - height = width + board_size.x = min(rect_size.x, rect_size.y) + board_size.y = board_size.x - $Background.rect_size.x = width - $Background.rect_size.y = height + $Background.rect_size = board_size $Background.rect_position = (rect_size - $Background.rect_size) / 2 $Background.set_anchors_preset(Control.PRESET_CENTER) @@ -84,6 +86,8 @@ func _input(event): if $AnimationPlayer.is_playing(): # Disable input during animation return + if _hint_active or hint_tween.is_active(): + return match current_state: # If we are in the winning animation, fast-forward to game over screen @@ -185,7 +189,7 @@ func direction_for_angle(angle: float) -> int: return Direction.DOWN func sliding_piece_for_direction(direction) -> Piece: - var destination: Vector2 = missing_piece.taquin_index + var destination: Vector2 = missing_piece.taquin_current_index match direction: Direction.UP: destination.y += 1 @@ -241,8 +245,8 @@ func commit_slide(audio: bool, check_solved: bool): assert(current_sliding_piece != null) assert(current_origin != Vector2.ZERO) - var x_delta = missing_piece.taquin_index.x - current_sliding_piece.taquin_index.x - var y_delta = missing_piece.taquin_index.y - current_sliding_piece.taquin_index.y + var x_delta = missing_piece.taquin_current_index.x - current_sliding_piece.taquin_current_index.x + var y_delta = missing_piece.taquin_current_index.y - current_sliding_piece.taquin_current_index.y assert(abs(x_delta) + abs(y_delta) == 1) swap_pieces(missing_piece, current_sliding_piece) @@ -262,13 +266,13 @@ func reset_slide(): current_origin = Vector2.ZERO func reset_position(p: Piece): - p.position = position_for_index(p.taquin_index, p.size) + p.position = position_for_index(p.taquin_current_index, p.size) func swap_pieces(a: Piece, b: Piece) -> void: - var a_index := a.taquin_index - a.taquin_index = b.taquin_index - pieces[b.taquin_index.x][b.taquin_index.y] = a - b.taquin_index = a_index + var a_index := a.taquin_current_index + a.taquin_current_index = b.taquin_current_index + pieces[b.taquin_current_index.x][b.taquin_current_index.y] = a + b.taquin_current_index = a_index pieces[a_index.x][a_index.y] = b func shuffle(count: int, speed: float) -> void: @@ -307,8 +311,8 @@ func ensure_validity() -> void: for c in range(columns): for r in range(rows): var piece = pieces[c][r] - assert(piece.taquin_index.x == c) - assert(piece.taquin_index.y == r) + assert(piece.taquin_current_index.x == c) + assert(piece.taquin_current_index.y == r) func set_pieces_reflection(value: bool) -> void: for c in range(columns): @@ -365,34 +369,30 @@ func init(pieces_order: Array, hidden_piece: int) -> void: if pieces.size() > 0: for c in range(pieces.size()): for r in range(pieces[c].size()): - var piece: Piece = pieces[c][r].queue_free() + pieces[c][r].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)) - + piece.piece_scale = Vector2(piece_size, piece_size) / board_size + # 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[c + r * columns] -# 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) + piece.taquin_original_index = Vector2((piece.order - 1) % columns, (piece.order - 1) / columns) + piece.taquin_original_position = position_for_index(piece.taquin_original_index, piece.size) + piece.taquin_current_index = Vector2(c, r) + piece.taquin_current_position = position_for_index(piece.taquin_current_index, piece.size) + piece.taquin_original_normalized_position = piece.taquin_original_position / board_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) + piece.position = piece.taquin_current_position if piece.order == hidden_piece: piece.visible = false @@ -402,6 +402,7 @@ func init(pieces_order: Array, hidden_piece: int) -> void: pieces_row.append(piece) pieces.append(pieces_row) + assert(missing_piece != null) func new_game(difficulty_mode: String) -> void: print_debug("difficulty mode: ", difficulty_mode) @@ -431,6 +432,30 @@ func new_game(difficulty_mode: String) -> void: init(pieces_order, hidden_piece) shuffle(difficulty, 0.0) +# +# Hints +# +func show_hints() -> void: + _hint_active = true + hint_tween.remove_all() + for c in range(columns): + for r in range(rows): + var piece: Piece = pieces[c][r] + if piece.taquin_current_index != piece.taquin_original_index: + piece.taquin_current_position = piece.position + hint_tween.interpolate_property(piece, "position", piece.position, piece.taquin_original_position, 1.0) + hint_tween.start() + +func discard_hints() -> void: + hint_tween.remove_all() + for c in range(columns): + for r in range(rows): + var piece: Piece = pieces[c][r] + if piece.taquin_current_index != piece.taquin_original_index: + hint_tween.interpolate_property(piece, "position", piece.position, piece.taquin_current_position, 1.0) + hint_tween.start() + _hint_active = false + # # Signals # @@ -445,3 +470,10 @@ func _on_AnimationPlayer_animation_finished(anim_name): func _on_NewGamePanel_start_triggered(preferences): var difficulty_mode = preferences.get_value("game", "difficulty", "normal") new_game(difficulty_mode) + + +func _on_Hints_button_down(): + show_hints() + +func _on_Hints_button_up(): + discard_hints() diff --git a/src/Taquin.tscn b/src/Taquin.tscn index f32d43b..9b0b8ff 100644 --- a/src/Taquin.tscn +++ b/src/Taquin.tscn @@ -60,10 +60,10 @@ anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 anchor_bottom = 0.5 -margin_left = -512.0 +margin_left = -300.0 margin_top = -300.0 -margin_right = -512.0 -margin_bottom = -300.0 +margin_right = 300.0 +margin_bottom = 300.0 color = Color( 0.12549, 0.235294, 0.337255, 1 ) __meta__ = { "_edit_use_anchors_": false @@ -75,7 +75,6 @@ anims/MovingPiece = SubResource( 1 ) [node name="MockPiece" parent="AnimationPlayer" instance=ExtResource( 2 )] visible = false position = Vector2( 15, 15 ) -size = 160 [node name="PlaceholderTexture" type="ColorRect" parent="AnimationPlayer/MockPiece"] margin_right = 160.0 @@ -100,5 +99,7 @@ one_shot = true [node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] stream = ExtResource( 3 ) + +[node name="HintTween" type="Tween" parent="."] [connection signal="animation_finished" from="AnimationPlayer" to="." method="_on_AnimationPlayer_animation_finished"] [connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"]