I started making puzzles in Godot 3.5.2 from a video tutorial. I entered these codes for a tile.
extends TextureButton
var number
signal tile_pressed
signal slide_completed
func set_text(new_number):
number = new_number
$Number/Label.text = str(number)
func set_sprite(new_frame, size, tile_size):
var sprite = $Sprite
update_size(size, tile_size)
sprite.set_hframes(size)
sprite.set_vframes(size)
sprite.set_frame(new_frame)
func update_size(size, tile_size):
var new_size = Vector2(tile_size, tile_size)
set_size(new_size)
$Number.set_size(new_size)
$Number/ColorRect.set_size(new_size)
$Number/Label.set_size(new_size)
$Panel.set_size(new_size)
var to_scale = size * (new_size / $Sprite.texture.get_size())
$Sprite.set_scale(to_scale)
func set_sprite_texture(texture):
$Sprite.set_texture(texture)
func slide_to(new_position, duration):
var tween = $Tween
tween.interpolate_property(self, "rect_position", null, new_position, duration,Tween.TRANS_QUART, Tween.EASE_OUT)
tween.start()
func set_number_visible(state):
$Number.visible = state
func _on_Tile_pressed():
emit_signal("tile_pressed", number)
func _on_Tween_tween_completed(_object, _key):
emit_signal("slide_completed", number)
I entered these codes for the board puzzle.
extends Control
export var size = 4
export var tile_size = 80
export var tile_scene: PackedScene
export var slide_duration = 0.15
var board = []
var tiles = []
var empty = Vector2()
var is_animating = false
var tiles_animating = 0
var move_count = 0
var number_visible = true
var background_texture = null
enum GAME_STATES {
NOT_STARTED,
STARTED,
WON
}
var game_state = GAME_STATES.NOT_STARTED
signal game_started
signal game_won
signal moves_updated
func gen_board():
var value = 1
board = []
for r in range(size):
board.append([])
for c in range(size):
if (value == size*size):
board[r].append(0)
empty = Vector2(c, r)
else:
board[r].append(value)
var tile = tile_scene.instance()
tile.set_position(Vector2(c * tile_size, r * tile_size))
tile.set_text(value)
if background_texture:
tile.set_sprite_texture(background_texture)
tile.set_sprite(value-1, size, tile_size)
tile.set_number_visible(number_visible)
tile.connect("tile_pressed", self, "on_Tile_pressed")
tile.connect("slide_completed", self, "_on_Tile_slide_completed")
add_child(tile)
tiles.append(tile)
value += 1
func is_board_solved():
var count = 1
for r in range(size):
for c in range(size):
if (board[r][c] != count):
if r == c and c == size - 1 and board[r][c] == 0:
return true
else:
return false
count +=1
return true
func print_board():
print('------board------')
for r in range(size):
var row = ''
for c in range(size):
row += str(board[r][c]).pad_zeros(2) + ' '
print(row)
func value_to_grid(value):
for r in range(size):
for c in range(size):
if (board[r][c] == value):
return Vector2(c, r)
return null
func get_tile_by_value(value):
for tile in tiles:
if str(tile.number) == str(value):
return tile
return null
func _ready():
tile_size = floor(get_size().x / size)
set_size(Vector2(tile_size*size, tile_size*size))
gen_board()
func _on_Tile_pressed(number):
if is_animating:
return
if game_state == GAME_STATES.NOT_STARTED:
scramble_board()
game_state = GAME_STATES.STARTED
emit_signal('game_started')
return
if game_state == GAME_STATES.WON:
game_state = GAME_STATES.STARTED
reset_move_count()
scramble_board()
emit_signal('game_started')
return
var tile = value_to_grid(number)
empty = value_to_grid(0)
if (tile.x != empty.x and tile.y != empty.y):
return
var dir = Vector2("sign(tile.x - empty.x)", "sign(tile.y, - empty.y)")
var start = Vector2("min(tile.x, empty.x)", "min(tile.y, empty.y)")
var end = Vector2("max(tile.x, empty.x)", "max(tile.y, empty.y)")
for r in range(end.y, start.y - 1, -1):
for c in range(end.x, start.x - 1, -1):
if board[r][c] == 0:
continue
var object: TextureButton = get_tile_by_value(board[r][c])
object.slide_to((Vector2(c, r)-dir) * tile_size, slide_duration)
is_animating = true
tiles_animating += 1
var old_board = board.duplicate(true)
if tile.y == empty.y:
if dir.x == -1:
board[tile.y] = slide_row(board[tile.y], 1, start.x)
else:
board[tile.y] = slide_row(board[tile.y], -1, end.x)
if tile.x == empty.x:
var column = []
for r in range(size):
column.append(board[r][tile.x])
if dir.y == -1:
column = slide_column(column, 1, start.y)
else:
column = slide_column(column, -1, end.y)
for r in range(size):
board[r][tile.x] = column[r]
var moves_made = 0
for r in range(size):
for c in range(size):
if old_board[r][c] != board[r][c]:
moves_made += 1
move_count += moves_made - 1
emit_signal("moves_updated", move_count)
var is_solved = is_board_solved()
if is_solved:
game_state = GAME_STATES.WON
emit_signal("game_won")
func is_board_solvable(flat):
var parity = 0
var grid_width = size
var row = 0
var blank_row = 0
for i in range(size*size):
if i % grid_width == 0:
row += 1
if flat[i] == 0:
blank_row = row
continue
for j in range(i+1, size*size):
if flat[i] > flat[j] and flat[j] != 0:
parity += 1
if grid_width % 2 == 0:
if blank_row % 2 == 0:
return parity % 2 == 0
else:
return parity % 2 != 0
else:
return parity % 2 == 0
func scramble_board():
reset_board()
var temp_flat_board = []
for i in range(size*size - 1, -1, -1):
temp_flat_board.append(i)
randomize()
temp_flat_board.shuffle()
var is_solvable = is_board_solvable(temp_flat_board)
while not is_solvable:
randomize()
temp_flat_board.shuffle()
is_solvable = is_board_solvable(temp_flat_board)
for r in range(size):
for c in range(size):
board[r][c] = temp_flat_board[r*size + c]
if board[r][c] != 0:
set_tile_position(r, c, board[r][c])
empty = value_to_grid(0)
func reset_board():
reset_move_count()
board = []
for r in range(size):
board.append(([]))
for c in range(size):
board[r].append(r*size + c + 1)
if r*size + c + 1 == size * size:
board[r][c] = 0
else:
set_tile_position(r, c, board[r][c])
empty = value_to_grid(0)
func set_tile_position(r: int, c: int, val: int):
var object: TextureButton = get_tile_by_value(val)
object.set_position(Vector2(c, r) * tile_size)
func _process(_delta):
var is_pressed = true
var dir = Vector2.ZERO
if (Input.is_action_just_pressed("move_left")):
dir.x = -1
elif (Input.is_action_just_pressed("move_right")):
dir.x = 1
elif (Input.is_action_just_pressed("move_up")):
dir.y = -1
elif (Input.is_action_just_pressed("move_down")):
dir.y = 1
else:
is_pressed = false
if is_pressed:
empty = value_to_grid(0)
var nr = empty.y + dir.y
var nc = empty.x + dir.x
if (nr == -1 or nc == -1 or nr >= size or nc >= size):
return
var tile_pressed = board[nr][nc]
print(tile_pressed)
_on_Tile_pressed(tile_pressed)
func slide_row(row, dir, limiter):
var empty_index = row.find(0)
if dir == 1:
var start = row.slice(0, limiter)
start.pop_back()
var pre = row.slice(limiter, empty_index)
pre.pop_back()
var post = row.slice(empty_index, row.size())
post.pop_front()
return start + [0] + pre + post
else:
var pre = row.slice(0, empty_index)
pre.pop_back()
var post = row.slice(empty_index, limiter)
post.pop_front()
var end = row.slice(limiter, row.size() - 1)
end.pop_front()
return pre + post + [0] + end
func slide_column(column, dir, limiter):
var empty_index = column.find(0)
if dir == 1:
var start = column.slice(0, limiter)
start.pop_back()
var pre = column.slice(limiter, empty_index)
pre.pop_back()
var post = column.slice(empty_index, column.size())
post.pop_front()
return start + [0] + pre + post
else:
var pre = column.slice(0, empty_index)
pre.pop_back()
var post = column.slice(empty_index, limiter)
post.pop_front()
var end = column.slice(limiter, column.size() - 1)
end.pop_front()
return pre + post + [0] + end
func _on_Tile_slide_completed(_number):
tiles_animating -= 1
if tiles_animating == 0:
is_animating = false
func reset_move_count():
move_count = 0
emit_signal("moves_updated", move_count)
func set_tile_numbers(state):
number_visible = state
for tile in tiles:
tile.set_number_visiblw(state)
func update_size(new_size):
size = int(new_size)
print('updating board size ', size)
tile_size = floor(get_size().x / size)
for tile in tiles:
tile.queue_free()
tiles = []
gen_board()
game_state = GAME_STATES.NOT_STARTED
reset_move_count()
func update_background_texture(texture):
background_texture = texture
for tile in tiles:
tile.set_sprite_texture(texture)
tile.update_size(size, tile_size)
When I click ctr+shift+f5, the messy puzzle is also displayed, but by pressing the buttons that I defined in the input map, none of the puzzle pieces move. Bugs are not displayed in the debug section. I did not understand what is the existing bug.