2019-12-10 13:55:03 +01:00
|
|
|
extends Control
|
2019-11-22 13:38:50 +01:00
|
|
|
class_name Taquin
|
|
|
|
tool
|
2019-11-21 00:25:53 +01:00
|
|
|
|
2019-11-25 01:16:06 +01:00
|
|
|
var Piece = preload("res://src/Piece.tscn")
|
|
|
|
|
2019-11-21 00:25:53 +01:00
|
|
|
export var rows: int = 4
|
|
|
|
export var columns: int = 4
|
2019-11-22 13:38:50 +01:00
|
|
|
export var width: int = 512
|
|
|
|
export var height: int = 512
|
2019-11-26 13:57:50 +01:00
|
|
|
export var difficulty: int = 10
|
|
|
|
|
2019-11-27 22:25:07 +01:00
|
|
|
var interpiece: int = 4
|
2020-01-06 00:12:58 +01:00
|
|
|
var min_padding = 15
|
|
|
|
var padding = Vector2(min_padding, min_padding)
|
2019-11-21 00:25:53 +01:00
|
|
|
|
2019-11-22 13:38:50 +01:00
|
|
|
var pieces: Array = []
|
2019-11-22 13:50:37 +01:00
|
|
|
var missing_piece: Vector2
|
2019-11-25 22:56:50 +01:00
|
|
|
var rng = RandomNumberGenerator.new()
|
2019-11-21 00:25:53 +01:00
|
|
|
|
2019-12-03 13:50:42 +01:00
|
|
|
var current_animation_path: String = "AnimationPlayer/MockPiece:position"
|
|
|
|
|
2020-01-03 14:22:50 +01:00
|
|
|
var swipe = Vector2(0, 0)
|
|
|
|
|
2019-11-25 22:56:50 +01:00
|
|
|
func position_for_index(index: Vector2, size: int) -> Vector2:
|
2020-01-06 00:12:58 +01:00
|
|
|
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
|
|
|
|
return int(min(w_size, h_size))
|
|
|
|
|
|
|
|
func compute_padding(piece_size: int) -> Vector2:
|
|
|
|
var padding = Vector2(0, 0)
|
|
|
|
padding.x = width - columns * piece_size - (columns - 1) * interpiece
|
|
|
|
padding.y = height - rows * piece_size - (rows - 1) * interpiece
|
|
|
|
padding = padding / Vector2(2, 2)
|
|
|
|
return padding
|
2019-11-25 22:56:50 +01:00
|
|
|
|
2019-11-22 13:38:50 +01:00
|
|
|
func _ready() -> void:
|
2019-12-03 13:50:42 +01:00
|
|
|
$AnimationPlayer/MockPiece.visible = false
|
|
|
|
|
|
|
|
$Background.rect_size.x = width
|
|
|
|
$Background.rect_size.y = height
|
2019-11-27 00:50:35 +01:00
|
|
|
|
2019-11-25 22:56:50 +01:00
|
|
|
rng.randomize()
|
2019-11-26 13:42:54 +01:00
|
|
|
var piece_size: int = compute_piece_size()
|
2020-01-06 00:12:58 +01:00
|
|
|
padding = compute_padding(piece_size)
|
|
|
|
print("piece size: ", piece_size)
|
|
|
|
print("padding: ", padding)
|
2019-11-25 22:56:50 +01:00
|
|
|
|
2019-11-22 13:50:37 +01:00
|
|
|
for c in range(columns):
|
|
|
|
var pieces_row: Array = []
|
|
|
|
for r in range(rows):
|
2019-11-25 01:16:06 +01:00
|
|
|
var piece = Piece.instance()
|
|
|
|
|
2019-11-26 13:42:54 +01:00
|
|
|
piece.size = piece_size
|
2019-11-25 22:56:50 +01:00
|
|
|
piece.position = position_for_index(Vector2(c, r), piece.size)
|
2019-11-27 22:25:07 +01:00
|
|
|
piece.number = 1 + c + r * columns
|
|
|
|
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)
|
2019-11-25 22:56:50 +01:00
|
|
|
|
2019-11-22 13:50:37 +01:00
|
|
|
if r == rows - 1 && c == columns - 1:
|
|
|
|
piece.visible = false
|
|
|
|
missing_piece.x = c
|
|
|
|
missing_piece.y = r
|
2019-11-25 01:16:06 +01:00
|
|
|
|
2019-12-03 13:50:42 +01:00
|
|
|
$Background.add_child(piece)
|
2019-11-22 13:50:37 +01:00
|
|
|
pieces_row.append(piece)
|
2019-11-25 01:16:06 +01:00
|
|
|
|
2019-11-25 01:24:38 +01:00
|
|
|
pieces.append(pieces_row)
|
|
|
|
|
2019-11-26 13:57:50 +01:00
|
|
|
shuffle(difficulty)
|
2019-11-25 22:56:50 +01:00
|
|
|
|
2019-11-25 01:24:38 +01:00
|
|
|
func _input(event):
|
2019-12-09 23:54:35 +01:00
|
|
|
if $AnimationPlayer.is_playing():
|
|
|
|
# Disable input during animation
|
|
|
|
return
|
|
|
|
|
2019-11-25 01:24:38 +01:00
|
|
|
if event.is_action_pressed("ui_up"):
|
2019-11-25 21:40:55 +01:00
|
|
|
move_piece(Direction.DOWN)
|
2019-11-25 22:56:50 +01:00
|
|
|
if event.is_action_pressed("ui_down"):
|
|
|
|
move_piece(Direction.UP)
|
2019-11-25 01:24:38 +01:00
|
|
|
if event.is_action_pressed("ui_left"):
|
2019-11-25 21:40:55 +01:00
|
|
|
move_piece(Direction.RIGHT)
|
2019-11-25 22:56:50 +01:00
|
|
|
if event.is_action_pressed("ui_right"):
|
|
|
|
move_piece(Direction.LEFT)
|
2019-11-25 21:40:55 +01:00
|
|
|
|
2020-01-03 14:22:50 +01:00
|
|
|
if event is InputEventScreenDrag:
|
|
|
|
swipe = event.relative
|
|
|
|
if event is InputEventScreenTouch:
|
|
|
|
if not event.pressed: # Touch released
|
|
|
|
var angle = swipe.angle()
|
|
|
|
if angle < PI / 4 and angle >= - PI / 4:
|
|
|
|
move_piece(Direction.LEFT)
|
|
|
|
if angle >= PI / 4 and angle < PI - PI / 4:
|
|
|
|
move_piece(Direction.UP)
|
|
|
|
if angle >= - PI + PI / 4 and angle < - PI / 4:
|
|
|
|
move_piece(Direction.DOWN)
|
|
|
|
if angle >= PI - PI / 4 or angle < -PI + PI / 4:
|
|
|
|
move_piece(Direction.RIGHT)
|
|
|
|
|
2019-11-25 21:40:55 +01:00
|
|
|
enum Direction { UP, DOWN, LEFT, RIGHT }
|
|
|
|
|
|
|
|
func move_piece(direction) -> bool:
|
|
|
|
var destination: Vector2 = missing_piece
|
|
|
|
match direction:
|
|
|
|
Direction.UP:
|
2020-01-04 19:22:11 +01:00
|
|
|
# print("up")
|
2019-11-25 21:40:55 +01:00
|
|
|
destination.y -= 1
|
|
|
|
Direction.DOWN:
|
|
|
|
destination.y += 1
|
2020-01-04 19:22:11 +01:00
|
|
|
# print("down")
|
2019-11-25 21:40:55 +01:00
|
|
|
Direction.LEFT:
|
|
|
|
destination.x -= 1
|
2020-01-04 19:22:11 +01:00
|
|
|
# print("left")
|
2019-11-25 21:40:55 +01:00
|
|
|
Direction.RIGHT:
|
|
|
|
destination.x += 1
|
2020-01-04 19:22:11 +01:00
|
|
|
# print("right")
|
2019-11-25 21:40:55 +01:00
|
|
|
|
2020-01-04 19:22:11 +01:00
|
|
|
# print(destination)
|
2019-11-25 21:40:55 +01:00
|
|
|
if (destination.x < 0 || destination.x >= columns
|
|
|
|
|| destination.y < 0 || destination.y >= rows):
|
|
|
|
print("impossible move")
|
|
|
|
return false
|
|
|
|
|
2019-12-03 13:50:42 +01:00
|
|
|
var moving_piece: Piece = pieces[destination.x][destination.y]
|
|
|
|
var moving_piece_animation: Animation = $AnimationPlayer.get_animation("MovingPiece")
|
|
|
|
|
|
|
|
assert(moving_piece_animation != null)
|
|
|
|
assert(moving_piece_animation.get_track_count() > 0)
|
|
|
|
|
|
|
|
var moving_piece_track_index: int = moving_piece_animation.find_track(current_animation_path)
|
|
|
|
|
|
|
|
assert(moving_piece_track_index != -1)
|
|
|
|
|
|
|
|
var new_animation_path: String = str($AnimationPlayer.get_parent().get_path_to(moving_piece), ":position")
|
|
|
|
moving_piece_animation.track_set_path(moving_piece_track_index, new_animation_path)
|
|
|
|
current_animation_path = new_animation_path
|
|
|
|
|
|
|
|
moving_piece_animation.track_set_key_value(moving_piece_track_index, 0, position_for_index(destination, moving_piece.size))
|
|
|
|
moving_piece_animation.track_set_key_value(moving_piece_track_index, 1, position_for_index(missing_piece, moving_piece.size))
|
|
|
|
$AnimationPlayer.play("MovingPiece")
|
|
|
|
|
2019-11-25 21:40:55 +01:00
|
|
|
swap(missing_piece, destination)
|
|
|
|
missing_piece = destination
|
2019-11-25 22:56:50 +01:00
|
|
|
|
2019-11-25 21:40:55 +01:00
|
|
|
update()
|
2019-11-25 22:56:50 +01:00
|
|
|
if check_solved():
|
2020-01-07 13:54:06 +01:00
|
|
|
var game_state = get_node("/root/Main/GameState") as GameState
|
|
|
|
game_state.transition_to(GameState.State.WINNING)
|
2019-11-26 13:57:50 +01:00
|
|
|
emit_signal("solved")
|
2019-11-25 22:56:50 +01:00
|
|
|
|
2019-11-25 21:40:55 +01:00
|
|
|
return true
|
|
|
|
|
|
|
|
func swap(src: Vector2, dst: Vector2) -> void:
|
|
|
|
var tmp: Piece = pieces[src.x][src.y]
|
|
|
|
pieces[src.x][src.y] = pieces[dst.x][dst.y]
|
|
|
|
pieces[dst.x][dst.y] = tmp
|
2019-12-03 13:50:42 +01:00
|
|
|
# pieces[src.x][src.y].position = position_for_index(src, tmp.size)
|
|
|
|
# pieces[dst.x][dst.y].position = position_for_index(dst, tmp.size)
|
2019-11-25 22:56:50 +01:00
|
|
|
|
|
|
|
func shuffle(count: int) -> void:
|
|
|
|
while count > 0:
|
|
|
|
count -= 1
|
|
|
|
var direction = rng.randi_range(Direction.UP, Direction.RIGHT)
|
|
|
|
move_piece(direction)
|
|
|
|
|
|
|
|
func check_solved() -> bool:
|
|
|
|
for c in range(columns):
|
|
|
|
for r in range(rows):
|
|
|
|
if pieces[c][r].number != 1 + c + r * columns:
|
|
|
|
return false
|
|
|
|
return true
|