How do I get a list of objects in a row after an input?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Wulzzy

I have a game I am working on where there are tiles in rows and columns. Players can swap the tiles by dragging them around with the mouse and I want to check what order they are in after each move.

I’ve tried a couple of iterations of what I thought would work by using an Area2D node that moves to each tile position and adds the tiles to lists after releasing the mouse button. Instead, the Area2D moves, but only adds the first tile it was on to the list (or in the case of using a signal, doesn’t even add anything after the first input).

I’ve tried using body_entered and get_overlapping_bodies. I’ve also tried switching between _input and _process. Here is the relevant code trying to get just the top row:

func _process(_delta):
if Input.is_action_just_released("mouse_left"):

func checkTiles():
for column in columns:
	$PosChecker.position.x = firstColumnX + columnSpacingX*column
	$PosChecker/CollisionShape2D.position.x = firstColumnX + columnSpacingX*column
	rowList += $PosChecker.get_overlapping_bodies()
	for name in rowList:
$PosChecker.position.x = firstColumnX
$PosChecker.position.y = firstRowY

I’m assuming this has something to do with sequencing and/or collisions all processing at once (as in the case of get_overlapping_bodies). But I’ve spent way too much time banging my head against the walling trying to figure this out and I obviously have no idea what I am doing.

Am I missing something or going about it wrong? Is there an elegant solution to this or should I maybe place Area2Ds at each tile position?

:bust_in_silhouette: Reply From: Inces

Are You using TIleMap ?

If Yes, than You can iterate through tiles with Tilemap methods. Get-used-rect() for whole cells area, or manually like :

for x in yourtotalcellshorizontally:
     for y in your totalcellvertically:
            get-cell(x,y) or getcellv(x,y) 

If You want to only check column and row where cursor is, than just transofrm mouse position into world-to-map() and check it in similar way

I am not, but I think there might be some confusion given that I was calling the nodes players drag around “tiles” in my post. They are KinematicBody2Ds.

Wakatta below was able to solve my issue, but I’m wondering now if using a TileMap is actually possible for my situation. Are you able to do a sort of drag and drop system such as an inventory system with TileMap?

Wulzzy | 2021-03-24 05:47

For project like inventory even TileMap seems to overkill :). There are control nodes like Itemlist or gridcontainer useful for that. However they may lack some graphical shenanigans. All in all it is possible to easily make functional inventory with TileMap, as long as items are all one size :).

Inces | 2021-03-24 07:36

:bust_in_silhouette: Reply From: Wakatta

You’ve managed to complicate a simple problem
Add all related nodes to an array then use a custom sorting function
even easier if they’re part of a group

func compare_positions(a, b):
	return a.rect_position < b.rect_position

func checkTiles():
    var tiles = get_tree().get_nodes_in_group("Tiles")
    tiles.sort_custom(self, "compare_positions")

func _process(_delta):
    if Input.is_action_just_released("mouse_left"):

Can’t really remember how xy sorting works but you can always use use two comparisons in that case to get the desired results

For rows

func compare_rows(a, b):
	return a.rect_position.x < b.rect_position.x

for columbs

func compare_columbs(a, b):
	return a.rect_position.y < b.rect_position.y

Thanks! It works perfectly! I really was overdoing it.

Wulzzy | 2021-03-24 05:38