Godot Version
4.2.1
Question
Hi, I’m fairly new to Godot and working on my first actual project, a 2d platformer. I have been working on a mechanic for a while that recursively swaps tiles on a tilemap between an active and reference layer when you interact with a switch. This has mostly been successful, however I am running into an issue with scenes that I have added to my tileset. The way I found to set the tile in the active layer to the cell in the reference layer is this:
tilemap.set_cell(main_layer, cell_pos, ref_source_id, ref_atlas_coords)
This method relies on the atlas coordinates of the tile in the reference layer, but scene tiles seem to be stored differently. I am to the point where the game can read if the next tile to be swapped is a scene tile, but it just swaps it for an empty tile because it isn’t reading where the tile is stored properly. My best guess from what I’ve researched so far is that I may need to access the scene directly through the scenetree, but I’m not sure how I could make it specific to the tile that needs to be replaced.
Here’s the full script for the switch scene if it helps. It’s kind of Frankensteined together from various tutorials and the small bit of knowledge I’ve picked up thus far.
extends Node2D
@export var is_wire := true
@onready var animation = $AnimatedSprite2D
@export var main_layer := 7 # Layer with interactive wires
@export var reference_layer := 8 # Layer with opposite states
var checked_cells :=
@onready var tilemap = get_node(“/root/Level/tilemap”)
var hitcell
var proxy_atlas = Vector2i(31, 2)
var processed =
var first_neighbor_processed = false
var is_scene = false
func _ready():
hitcell = tilemap.local_to_map(position)
tilemap.set_cell(main_layer, hitcell, 1, proxy_atlas)
animation.play(“default”)
pass # Replace with function body.
func _process(delta):
pass
func _on_area_2d_body_entered(body):
animation.play(“break”)
hitcell = tilemap.local_to_map(position)
tile_swap(hitcell)
pass # Replace with function body.
func _on_animated_sprite_2d_animation_finished():
queue_free()
pass # Replace with function body.
func tile_swap(cell_pos: Vector2i):
if cell_pos in processed:
return
processed.append(cell_pos)
var tile_data = tilemap.get_cell_tile_data(main_layer, cell_pos)
var ref_source_id = tilemap.get_cell_source_id(reference_layer, cell_pos)
var ref_atlas_coords = tilemap.get_cell_atlas_coords(reference_layer, cell_pos)
var can_swap = false
is_scene = false
if tile_data and tile_data.get_custom_data("is_wire"):
can_swap = true
elif tilemap.get_cell_source_id(main_layer, cell_pos) != -1:
can_swap = true
var source_id = tilemap.get_cell_source_id(reference_layer, cell_pos)
if source_id != -1 and not tile_data:
is_scene = true
var source = tilemap.tile_set.get_source(source_id)
if can_swap:
if is_scene == false:
tilemap.set_cell(main_layer, cell_pos, ref_source_id, ref_atlas_coords)
else:
if ref_source_id != -1:
print("Swapping scene tile at ", cell_pos, " source ID: ", ref_source_id)
tilemap.set_cell(main_layer, cell_pos, ref_source_id)
for dir in [Vector2i.UP, Vector2i.DOWN, Vector2i.LEFT, Vector2i.RIGHT]:
var neighbor = cell_pos + dir
if tilemap.get_cell_source_id(main_layer, neighbor) != -1:
if not first_neighbor_processed:
tile_swap(neighbor)
first_neighbor_processed = true
else:
call_deferred("tile_swap", neighbor)