|
|
|
 |
Reply From: |
clemens.tolboom |
The code below does not use Atlas tiles but just expect correct numberdimensions
of tiles. It works for me.
I have reduced the variables needed and typed them so autocomplete functions 
extends Node2D
# define touch action for left mouse down
# This assumes a tilemap with same dimensions and tiles set in order
export var puzzle_dimensions:Vector2 = Vector2(3,4)
onready var puzzle:TileMap = $Background/Grid
var touch_y_limit:int = 5
var swipe_limit:float = 10.0
var swiping:bool = false
var first_cell:Vector2
var sec_cell:Vector2
func get_tile_index(x:int, y:int) -> int:
return x + y * int(puzzle_dimensions.x)
func _ready():
solved_puzzle()
func solved_puzzle():
for i in range(puzzle_dimensions.x):
for j in range(puzzle_dimensions.y):
var index = get_tile_index(i,j)
puzzle.set_cell(i, j, index)
func _process(delta):
touch_input()
func touch_input():
var touch_location:Vector2
if Input.is_action_just_pressed("touch"):
if get_global_mouse_position().y > touch_y_limit:
touch_location = get_global_mouse_position()
first_cell = puzzle.world_to_map(touch_location)
swiping = true
if Input.is_action_just_released("touch") and swiping:
touch_location = get_global_mouse_position()
sec_cell = puzzle.world_to_map(touch_location)
var first_tile:int = puzzle.get_cellv(first_cell)
var sec_tile:int = puzzle.get_cellv(sec_cell)
puzzle.set_cellv(first_cell, sec_tile)
puzzle.set_cellv(sec_cell, first_tile)
swiping = false
Thanks a lot.
I have some questions though.
the :
export var puzzle_dimensions:Vector2 = Vector2(3,4)
is the grid’s number of cells(4 columns, 5 rows)? So in my case will be Vector2(3,5), because the image is divided to 24 pieces(4 columns and 6 rows), if the count starts from 0.
And also the tilemap’s position doesn’t start at position 0,0 but is a bit right and down.
I already tried to calculate it(I have updated my first post) like this:
first_touch = get_global_mouse_position()
var first_with_offset = first_touch - $Background/Grid.position
first_cell = $Background/Grid.world_to_map(first_with_offset)
and:
final_touch = get_global_mouse_position()
var final_with_offset = first_touch - $Background/Grid.position
first_cell = $Background/Grid.world_to_map(final_with_offset)
EDIT:
I started to implement your suggestions, but seems that doesn’t work for me.
With the function I had in “_ready”, I had the picture drawn on screen, but with the “solved_puzzle” function I just get the first tile of every image I had in tileset. At this time I have 2 images on the tileset. I set them like this:
- Drag and drop the first image in tileset editor
- Select it and press the +New Atlas button
- Set the cell to 130x158
- In region tap I select all image to get the divided 24 cells for the image
Same procedure for the 2nd image.
-Save the tileset.
EDIT2:
I din’t find a way to draw all image’s tiles, I returned to my function to display the solved image, and I managed to make it work.
I created 2 more variables to store the autotile’s coordinations and with this I can swap the tiles. I put all those in 2 new fucntions which I use in “touch” and “release” input if statements:
func swap_tile_start():
var first_with_offset = first_touch - puzzle.position
print(first_with_offset)
print(first_touch)
first_cell = puzzle.world_to_map(first_with_offset)
print(first_cell)
if is_in_grid(first_cell.x, first_cell.y):
print(first_cell.x, first_cell.y)
grid_controling = true
cell_one = puzzle.get_cell(first_cell.x, first_cell.y)
autotile_one = puzzle.get_cell_autotile_coord(first_cell.x, first_cell.y)
#print("cell1 " + str(autotile_one))
func swap_tile_end():
var final_with_offset = final_touch - puzzle.position
sec_cell = puzzle.world_to_map(final_with_offset)
print(sec_cell)
if is_in_grid(sec_cell.x,sec_cell.y) and grid_controling:
cell_two = puzzle.get_cell(sec_cell.x, sec_cell.y)
autotile_two = puzzle.get_cell_autotile_coord(sec_cell.x, sec_cell.y)
#print("cell2 " + str(puzzle.get_cell_autotile_coord(sec_cell.x,sec_cell.y)))
puzzle.set_cell(sec_cell.x, sec_cell.y , cell_one, false, false, false, Vector2(autotile_one))
puzzle.set_cell(first_cell.x, first_cell.y, cell_two, false, false, false, Vector2(autotile_two))
Like this works, but there are 2 more problems now:
- Limit the draw and swap tile actions in the area of those 24 cells
- Limit swipe to only the next tile up/down/left/right from the first.
dancaer69 | 2021-03-25 09:49
Are we talking about tiles or real pictures/images 
My puzzle is one image.
My 2D scene has root Node2D
with child Node2D
named ** Background** with Child
TileMap` named Grid
I dragged a (32x3) x (32x4) image on the TileMap/TileSet then clicked New Single Tile 3x4 times and select each cell in order.
Then attached my script and it did it’s job.
Hope this helps.
clemens.tolboom | 2021-03-25 17:39
var dim:Vector2 = Vector2(3,4)
used in
for i in range(dim.x):
for j in range(dim.y):
makes i iterate over [0,1,2] and j over [0,1,2,3].
Restricting the swaps you can use
if sec_cell.distance_to(first_cell) == 1:
clemens.tolboom | 2021-03-25 17:46
No, I’m talking about real images, I have 2(for now, but I added more) 525x948 pixels size. I used new atlas to divide each in 24 pieces, so every piece is a part(a region) of the image.
Thanks for the tip about restricting swaps, works fine.
The main problem now is the bounds of the tilemap. I tried to control so to swap only for a range of cells
func is_in_grid(col, row):
if col >= 0 and col < 4:
if row >= 0 and row < 6:
grid_controling = true
else:
grid_controling = false
return grid_controling
I call this function and I can see that called with print messages, but the swap action still applies on cells (-1,0), (-1,1)…, (0,6), (1,6)… which cause wired draws and messes up the image.
dancaer69 | 2021-03-25 18:04
I guess you must check both first and second cells. From my head something like:
rect:Rect = Rect.new(dimensions)
rect.contains(cellFirst) and rect.contains(cellSeconds)
clemens.tolboom | 2021-03-25 20:21
Thanks,
the above code didn’t work because there’s no rect, but I think I get the idea.
Probably you meant the Rect2 in which I get error about new() constant and contains method.
But after some trial and error I did it like this:
var rect = Rect2(Vector2.ZERO, puzzle_dimensions)
if rect.has_point(first_cell) and rect.has_point(sec_cell) and sec_cell.distance_to(first_cell) == 1:
and generally works. I have some problems though because on some cells(mostly on the sides) the swap action doesn’t trigger in all cell’ s area. For example on top 3 cells must to start the action by click(or touch) in the upper side of the cell.
dancaer69 | 2021-03-26 07:15
I have some problems though because on some cells(mostly on the sides) the swap action doesn’t trigger in all cell’ s area.
You can always log the cell position on mouse move events to figure out what is wrong. My guess is the TileMap is not positioned on screen on Vector2.ZERO
?
var mousePosition:Vector2 = get_global_mouse_position()
var local_position:Vector2 = puzzle.to_local(mousePosition)
var map_position:Vector2 = puzzle.world_to_map(local_position)
print(map_position)
If my answer is satisfying please mark it as such 
clemens.tolboom | 2021-03-26 13:56
Thanks again.
Yes, probalbly isn’ t because I have a background picture with a frame. So I had move the tilemap position to right and down about 40pixels. But in some point I added another colorRect and put the tilemap inside it.
I also had commented out the variable below:
var first_with_offset = first_touch - puzzle.position
Now I enable it and use it again and seems that is fine now.
dancaer69 | 2021-03-26 15:15