refactor keyboard handling
This commit is contained in:
parent
197704b82b
commit
90a1fdd5ac
|
@ -19,3 +19,8 @@ func _ready() -> void:
|
||||||
mat.set_shader_param("scale", Vector3(piece_scale.x, piece_scale.y, 1.0))
|
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_position.x, taquin_position.y, 0.0))
|
||||||
$ColorRect.material = mat
|
$ColorRect.material = mat
|
||||||
|
|
||||||
|
func debug_print(name: String):
|
||||||
|
print("%s order: %s" % [name, order])
|
||||||
|
print("%s taquin index: %s" % [name, taquin_index])
|
||||||
|
print("%s taquin position: %s" % [name, position])
|
||||||
|
|
|
@ -12,25 +12,27 @@ export var difficulty: int = 10
|
||||||
|
|
||||||
enum Direction { UP, DOWN, LEFT, RIGHT }
|
enum Direction { UP, DOWN, LEFT, RIGHT }
|
||||||
|
|
||||||
var interpiece: int = 4
|
var interpiece := 4
|
||||||
var min_padding = 15
|
var min_padding := 15
|
||||||
var padding = Vector2(min_padding, min_padding)
|
var padding := Vector2(min_padding, min_padding)
|
||||||
|
|
||||||
var pieces: Array = []
|
var pieces: Array = []
|
||||||
var missing_piece: Vector2
|
var rng := RandomNumberGenerator.new()
|
||||||
var rng = RandomNumberGenerator.new()
|
|
||||||
|
|
||||||
var current_animation_path: String = "AnimationPlayer/MockPiece:position"
|
var current_animation_path := "AnimationPlayer/MockPiece:position"
|
||||||
|
|
||||||
|
var swipe := Vector2(0, 0)
|
||||||
|
var is_sliding := false
|
||||||
|
|
||||||
var swipe = Vector2(0, 0)
|
|
||||||
var is_sliding = false
|
|
||||||
var current_sliding_piece: Piece = null
|
var current_sliding_piece: Piece = null
|
||||||
var current_origin = Vector2.ZERO
|
var missing_piece: Piece = null
|
||||||
var current_goal = Vector2.ZERO
|
|
||||||
var current_axis = Vector2.ZERO
|
var current_origin := Vector2.ZERO
|
||||||
var current_slide = Vector2.ZERO
|
var current_goal := Vector2.ZERO
|
||||||
var local_min_position = Vector2.ZERO
|
var current_axis := Vector2.ZERO
|
||||||
var local_max_position = Vector2.ZERO
|
var current_touch_slide := Vector2.ZERO
|
||||||
|
var local_min_position := Vector2.ZERO
|
||||||
|
var local_max_position := Vector2.ZERO
|
||||||
|
|
||||||
func position_for_index(index: Vector2, size: int) -> Vector2:
|
func position_for_index(index: Vector2, size: int) -> Vector2:
|
||||||
return padding + Vector2(index.x * (size + interpiece), index.y * (size + interpiece))
|
return padding + Vector2(index.x * (size + interpiece), index.y * (size + interpiece))
|
||||||
|
@ -74,8 +76,7 @@ func _ready() -> void:
|
||||||
|
|
||||||
if r == rows - 1 && c == columns - 1:
|
if r == rows - 1 && c == columns - 1:
|
||||||
piece.visible = false
|
piece.visible = false
|
||||||
missing_piece.x = c
|
missing_piece = piece
|
||||||
missing_piece.y = r
|
|
||||||
|
|
||||||
$Background.add_child(piece)
|
$Background.add_child(piece)
|
||||||
pieces_row.append(piece)
|
pieces_row.append(piece)
|
||||||
|
@ -84,12 +85,8 @@ func _ready() -> void:
|
||||||
|
|
||||||
shuffle(difficulty)
|
shuffle(difficulty)
|
||||||
|
|
||||||
func _input(event):
|
func _process(delta):
|
||||||
if $AnimationPlayer.is_playing():
|
var game_state = get_node_or_null("/root/Main/GameState") as GameState
|
||||||
# Disable input during animation
|
|
||||||
return
|
|
||||||
|
|
||||||
var game_state = get_node("/root/Main/GameState") as GameState
|
|
||||||
if game_state != null:
|
if game_state != null:
|
||||||
match game_state.current_state:
|
match game_state.current_state:
|
||||||
# If we are in the winning animation, fast-forward to game over screen
|
# If we are in the winning animation, fast-forward to game over screen
|
||||||
|
@ -99,58 +96,59 @@ func _input(event):
|
||||||
GameState.State.GAME_OVER:
|
GameState.State.GAME_OVER:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
func _input(event):
|
||||||
|
if $AnimationPlayer.is_playing():
|
||||||
|
# Disable input during animation
|
||||||
|
return
|
||||||
|
|
||||||
#
|
#
|
||||||
# Handle keyboard input
|
# Handle keyboard input
|
||||||
#
|
#
|
||||||
if event.is_action_pressed("ui_up"):
|
if event.is_action_pressed("ui_up"):
|
||||||
move_piece(Direction.DOWN)
|
|
||||||
if event.is_action_pressed("ui_down"):
|
|
||||||
move_piece(Direction.UP)
|
move_piece(Direction.UP)
|
||||||
|
if event.is_action_pressed("ui_down"):
|
||||||
|
move_piece(Direction.DOWN)
|
||||||
if event.is_action_pressed("ui_left"):
|
if event.is_action_pressed("ui_left"):
|
||||||
move_piece(Direction.RIGHT)
|
|
||||||
if event.is_action_pressed("ui_right"):
|
|
||||||
move_piece(Direction.LEFT)
|
move_piece(Direction.LEFT)
|
||||||
|
if event.is_action_pressed("ui_right"):
|
||||||
|
move_piece(Direction.RIGHT)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Handle touch input
|
# Handle touch input
|
||||||
#
|
#
|
||||||
if event is InputEventScreenDrag:
|
if event is InputEventScreenDrag:
|
||||||
# print("screen drag")
|
|
||||||
swipe = event.relative
|
swipe = event.relative
|
||||||
if not is_sliding:
|
if not is_sliding:
|
||||||
is_sliding = true
|
is_sliding = true
|
||||||
current_slide = Vector2(0, 0)
|
current_touch_slide = Vector2.ZERO
|
||||||
var angle = swipe.angle()
|
var angle = swipe.angle()
|
||||||
var direction = direction_for_angle(angle)
|
var direction = direction_for_angle(angle)
|
||||||
debug_print_direction(direction)
|
debug_print_direction(direction)
|
||||||
current_sliding_piece = sliding_piece_for_direction(direction)
|
current_sliding_piece = sliding_piece_for_direction(direction)
|
||||||
if current_sliding_piece != null:
|
if current_sliding_piece != null:
|
||||||
current_origin = current_sliding_piece.position
|
|
||||||
current_axis = axis_for_direction(direction)
|
current_axis = axis_for_direction(direction)
|
||||||
var local_end_position = current_axis * (current_sliding_piece.size + interpiece)
|
var local_end_position = current_axis * (current_sliding_piece.size + interpiece)
|
||||||
local_min_position = Vector2(min(0, local_end_position.x), min(0, local_end_position.y))
|
local_min_position = Vector2(min(0, local_end_position.x), min(0, local_end_position.y))
|
||||||
local_max_position = Vector2(max(0, local_end_position.x), max(0, local_end_position.y))
|
local_max_position = Vector2(max(0, local_end_position.x), max(0, local_end_position.y))
|
||||||
current_goal = current_sliding_piece.position + local_end_position
|
current_goal = current_sliding_piece.position + local_end_position
|
||||||
current_slide += swipe
|
current_touch_slide += swipe
|
||||||
if current_sliding_piece != null:
|
if current_sliding_piece != null:
|
||||||
var delta = current_slide.project(current_axis)
|
var delta = current_touch_slide.project(current_axis)
|
||||||
delta.x = clamp(delta.x, local_min_position.x, local_max_position.x)
|
delta.x = clamp(delta.x, local_min_position.x, local_max_position.x)
|
||||||
delta.y = clamp(delta.y, local_min_position.y, local_max_position.y)
|
delta.y = clamp(delta.y, local_min_position.y, local_max_position.y)
|
||||||
current_sliding_piece.position = current_origin + delta
|
current_sliding_piece.position = current_origin + delta
|
||||||
|
|
||||||
if event is InputEventScreenTouch:
|
if event is InputEventScreenTouch:
|
||||||
# print("screen touch")
|
|
||||||
if not event.pressed: # Touch released
|
if not event.pressed: # Touch released
|
||||||
is_sliding = false
|
is_sliding = false
|
||||||
if current_sliding_piece != null:
|
if current_sliding_piece != null:
|
||||||
var current_position = current_sliding_piece.position
|
var current_position = current_sliding_piece.position
|
||||||
if current_position.distance_to(current_origin) > current_position.distance_to(current_goal):
|
if current_position.distance_to(current_origin) > current_position.distance_to(current_goal):
|
||||||
current_sliding_piece.position = current_goal
|
current_sliding_piece.position = current_goal
|
||||||
var origin_taquin_position = current_sliding_piece.taquin_index
|
commit_slide()
|
||||||
swap(missing_piece, origin_taquin_position)
|
|
||||||
missing_piece = origin_taquin_position
|
|
||||||
else:
|
else:
|
||||||
current_sliding_piece.position = current_origin
|
reset_position(current_sliding_piece)
|
||||||
|
reset_slide()
|
||||||
|
|
||||||
func debug_print_direction(direction: int):
|
func debug_print_direction(direction: int):
|
||||||
match direction:
|
match direction:
|
||||||
|
@ -192,7 +190,7 @@ func direction_for_angle(angle: float) -> int:
|
||||||
return Direction.DOWN
|
return Direction.DOWN
|
||||||
|
|
||||||
func sliding_piece_for_direction(direction) -> Piece:
|
func sliding_piece_for_direction(direction) -> Piece:
|
||||||
var destination: Vector2 = missing_piece
|
var destination: Vector2 = missing_piece.taquin_index
|
||||||
match direction:
|
match direction:
|
||||||
Direction.UP:
|
Direction.UP:
|
||||||
destination.y += 1
|
destination.y += 1
|
||||||
|
@ -207,26 +205,18 @@ func sliding_piece_for_direction(direction) -> Piece:
|
||||||
|| destination.y < 0 || destination.y >= rows):
|
|| destination.y < 0 || destination.y >= rows):
|
||||||
print("\/!\\ Impossible move")
|
print("\/!\\ Impossible move")
|
||||||
return null
|
return null
|
||||||
return pieces[destination.x][destination.y]
|
|
||||||
|
|
||||||
func move_piece(direction) -> bool:
|
var piece = pieces[destination.x][destination.y]
|
||||||
var destination: Vector2 = missing_piece
|
current_origin = piece.position
|
||||||
match direction:
|
|
||||||
Direction.UP:
|
|
||||||
destination.y -= 1
|
|
||||||
Direction.DOWN:
|
|
||||||
destination.y += 1
|
|
||||||
Direction.LEFT:
|
|
||||||
destination.x -= 1
|
|
||||||
Direction.RIGHT:
|
|
||||||
destination.x += 1
|
|
||||||
|
|
||||||
if (destination.x < 0 || destination.x >= columns
|
return piece
|
||||||
|| destination.y < 0 || destination.y >= rows):
|
|
||||||
print("impossible move")
|
func move_piece(direction) -> void:
|
||||||
return false
|
current_sliding_piece = sliding_piece_for_direction(direction)
|
||||||
|
if current_sliding_piece == null:
|
||||||
|
reset_slide()
|
||||||
|
return
|
||||||
|
|
||||||
var moving_piece: Piece = pieces[destination.x][destination.y]
|
|
||||||
var moving_piece_animation: Animation = $AnimationPlayer.get_animation("MovingPiece")
|
var moving_piece_animation: Animation = $AnimationPlayer.get_animation("MovingPiece")
|
||||||
|
|
||||||
assert(moving_piece_animation != null)
|
assert(moving_piece_animation != null)
|
||||||
|
@ -236,33 +226,47 @@ func move_piece(direction) -> bool:
|
||||||
|
|
||||||
assert(moving_piece_track_index != -1)
|
assert(moving_piece_track_index != -1)
|
||||||
|
|
||||||
var new_animation_path: String = str($AnimationPlayer.get_parent().get_path_to(moving_piece), ":position")
|
var new_animation_path: String = str($AnimationPlayer.get_parent().get_path_to(current_sliding_piece), ":position")
|
||||||
moving_piece_animation.track_set_path(moving_piece_track_index, new_animation_path)
|
moving_piece_animation.track_set_path(moving_piece_track_index, new_animation_path)
|
||||||
current_animation_path = 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, 0, current_sliding_piece.position)
|
||||||
moving_piece_animation.track_set_key_value(moving_piece_track_index, 1, position_for_index(missing_piece, moving_piece.size))
|
moving_piece_animation.track_set_key_value(moving_piece_track_index, 1, missing_piece.position)
|
||||||
$AnimationPlayer.play("MovingPiece")
|
$AnimationPlayer.play("MovingPiece")
|
||||||
|
|
||||||
swap(missing_piece, destination)
|
commit_slide()
|
||||||
missing_piece = destination
|
|
||||||
|
|
||||||
update()
|
update()
|
||||||
if check_solved():
|
check_solved()
|
||||||
var game_state = get_node("/root/Main/GameState") as GameState
|
|
||||||
if game_state != null:
|
|
||||||
game_state.transition_to(GameState.State.WINNING)
|
|
||||||
|
|
||||||
return true
|
|
||||||
|
|
||||||
func swap(src: Vector2, dst: Vector2) -> void:
|
func commit_slide():
|
||||||
var tmp: Piece = pieces[src.x][src.y]
|
assert(current_sliding_piece != null)
|
||||||
pieces[src.x][src.y] = pieces[dst.x][dst.y]
|
assert(current_origin != Vector2.ZERO)
|
||||||
pieces[src.x][src.y].taquin_index = src
|
|
||||||
pieces[dst.x][dst.y] = tmp
|
var x_delta = missing_piece.taquin_index.x - current_sliding_piece.taquin_index.x
|
||||||
tmp.taquin_position = dst
|
var y_delta = missing_piece.taquin_index.y - current_sliding_piece.taquin_index.y
|
||||||
# pieces[src.x][src.y].position = position_for_index(src, tmp.size)
|
assert(abs(x_delta) + abs(y_delta) == 1)
|
||||||
# pieces[dst.x][dst.y].position = position_for_index(dst, tmp.size)
|
|
||||||
|
swap_pieces(missing_piece, current_sliding_piece)
|
||||||
|
reset_position(missing_piece)
|
||||||
|
|
||||||
|
ensure_validity()
|
||||||
|
reset_slide()
|
||||||
|
check_solved()
|
||||||
|
|
||||||
|
func reset_slide():
|
||||||
|
current_sliding_piece = null
|
||||||
|
current_origin = Vector2.ZERO
|
||||||
|
|
||||||
|
func reset_position(p: Piece):
|
||||||
|
p.position = position_for_index(p.taquin_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
|
||||||
|
pieces[a_index.x][a_index.y] = b
|
||||||
|
|
||||||
func shuffle(count: int) -> void:
|
func shuffle(count: int) -> void:
|
||||||
while count > 0:
|
while count > 0:
|
||||||
|
@ -273,10 +277,22 @@ func shuffle(count: int) -> void:
|
||||||
func check_solved() -> bool:
|
func check_solved() -> bool:
|
||||||
for c in range(columns):
|
for c in range(columns):
|
||||||
for r in range(rows):
|
for r in range(rows):
|
||||||
if pieces[c][r].number != 1 + c + r * columns:
|
if pieces[c][r].order != 1 + c + r * columns:
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
var game_state = get_node_or_null("/root/Main/GameState") as GameState
|
||||||
|
if game_state != null:
|
||||||
|
game_state.transition_to(GameState.State.WINNING)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
func _on_GameState_state_changed(previous, current):
|
func _on_GameState_state_changed(previous, current):
|
||||||
match current:
|
match current:
|
||||||
GameState.State.WINNING:
|
GameState.State.WINNING:
|
||||||
|
|
|
@ -49,8 +49,8 @@ script = ExtResource( 1 )
|
||||||
__meta__ = {
|
__meta__ = {
|
||||||
"_edit_use_anchors_": false
|
"_edit_use_anchors_": false
|
||||||
}
|
}
|
||||||
rows = 5
|
rows = 3
|
||||||
columns = 5
|
columns = 3
|
||||||
difficulty = 0
|
difficulty = 0
|
||||||
|
|
||||||
[node name="Background" type="ColorRect" parent="."]
|
[node name="Background" type="ColorRect" parent="."]
|
||||||
|
|
Loading…
Reference in a new issue