Godot Version
4.3
Question
Hello, I’m trying to set up clickable tiles in a TileMapLayer, but I’m having trouble getting them to respond to clicks. The TileMapLayer is a child of another scene, which is being instantiated in the main scene. The scenes seem to load fine, but nothing happens when I click the tiles.
Here’s what I’ve done so far:
- I’ve implemented _input_event in the TileMapLayer to detect mouse clicks.
- I’ve connected the tile_clicked signal to the parent scene to handle clicks.
- I’ve added a physics layer to the TileMapLayer and painted tiles with the physics layer.
But when I click the tiles, I get no output, and nothing happens. Am I missing something here?
Thanks for any help!
Main Scene
Matrix Scene
TileMapLayer
extends TileMapLayer
# 4x4 tile state array
var tile_states: Array = []
# Signal to notify parent when a tile is clicked
signal tile_clicked(coords: Vector2i, power: int)
func _ready():
# Initialize the tile states array to null
tile_states = []
for y in range(4):
var row = []
for x in range(4):
row.append(null)
tile_states.append(row)
# Debugging to confirm readiness
print("TileMapLayer is ready.")
# Called when an input event occurs on this node (TileMapLayer)
func _input_event(viewport, event, shape_idx):
print("DEBUG: _input_event triggered!") # Debugging line
if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
var local_mouse_pos = to_local(event.position)
var clicked_coords = local_to_map(local_mouse_pos)
print("Mouse clicked at local position:", local_mouse_pos)
print("Tile coordinates:", clicked_coords)
# Emit signal when tile is clicked
emit_signal("tile_clicked", clicked_coords, 1) # Example power value: 1
# Return the tile states for external access
func get_tile_states() -> Array:
return tile_states
Node2D (Parent node for Matrix scene)
extends Node2D
@export var tilemap_layer: TileMapLayer
var tile_states: Array = []
func _ready():
# Ensure tilemap_layer is assigned
if not tilemap_layer:
tilemap_layer = $TileMapLayer # Adjust this if the child node name is different
if tilemap_layer:
print("TileMapLayer found, connecting signal.")
# Connect tilemap_layer's signal to the parent grid manager
tilemap_layer.connect("tile_clicked", Callable(self, "_on_tile_clicked"))
else:
print("Error: TileMapLayer not found.")
# Called when a tile is clicked in the TileMapLayer
func _on_tile_map_layer_tile_clicked(coords: Vector2i, power: int):
print("Tile clicked at:", coords, "with power:", power)
# You can add more logic here if needed
GridManager (Main Scene)
extends Node2D
@export var matrix4x4_scene: PackedScene # Reference to the Matrix4x4 scene
var grid_nodes: Array = [] # Array to hold the instantiated Matrix4x4 nodes
# This will hold the combined grid data
var grid_state: Array = []
# Screen resolution and tile sizes
const SCREEN_WIDTH = 1920
const SCREEN_HEIGHT = 1080
const TILE_SIZE = 16 # Adjust to match your tile size
const MATRIX_SCALE = 4 # Scale of the matrix
func _ready():
# Initialize grid_state as a 2D array for the 8x8 grid
grid_state = []
for y in range(8):
var row = []
for x in range(8):
row.append(null)
grid_state.append(row)
# Calculate the total size of the 2x2 grid
var matrix_size = TILE_SIZE * 4 * MATRIX_SCALE # Each matrix is 4x4 tiles
var total_grid_width = 2 * matrix_size # 2 matrices wide
var total_grid_height = 2 * matrix_size # 2 matrices high
# Calculate offsets to center the grid
var offset_x = (SCREEN_WIDTH - total_grid_width) / 2
var offset_y = (SCREEN_HEIGHT - total_grid_height) / 2
# Instantiate 4 matrix4x4 nodes and organize them in a 2x2 grid
for i in range(4):
var matrix = matrix4x4_scene.instantiate() # Instantiate a new Matrix4x4 node
add_child(matrix)
# Determine the position for each matrix in the 2x2 layout
var row = int(i / 2) # 0 or 1 (top or bottom row)
var col = i % 2 # 0 or 1 (left or right column)
var grid_x = col * matrix_size
var grid_y = row * matrix_size
matrix.position = Vector2(offset_x + grid_x, offset_y + grid_y)
# Scale up the matrix
matrix.scale = Vector2(MATRIX_SCALE, MATRIX_SCALE)
# Store the node and update its grid index
grid_nodes.append(matrix)
# Connect signals from matrix4x4 to parent grid manager
var tilemap_layer = matrix.get_node("TileMapLayer") # TileMapLayer is a child of Matrix4x4
if tilemap_layer:
print("TileMapLayer found in Matrix4x4, connecting signal.")
tilemap_layer.connect("tile_clicked", Callable(self, "_on_tile_clicked"))
else:
print("Error: TileMapLayer not found in Matrix4x4!")
# Update grid_state with the initial tile states
update_grid_state(i, tilemap_layer.get_tile_states()) # Now using tilemap_layer.get_tile_states()
func update_grid_state(grid_index: int, tile_states: Array):
# Map the 4x4 grid to the correct position in the 8x8 grid
var start_x = (grid_index % 2) * 4 # Left-to-right
var start_y = int(grid_index / 2) * 4 # Top-to-bottom
for local_y in range(4):
for local_x in range(4):
grid_state[start_y + local_y][start_x + local_x] = tile_states[local_y][local_x]
func _on_tile_clicked(coords: Vector2i, power: int):
print("Tile clicked at:", coords, "with power:", power)
# You can add further logic for handling the tile click here
func clear_full_rows_and_columns():
var rows_to_clear = []
var columns_to_clear = []
# Check rows
for y in range(8):
var full_row = true
for x in range(8):
if grid_state[y][x] == null:
full_row = false
break
if full_row:
rows_to_clear.append(y)
# Check columns
for x in range(8):
var full_column = true
for y in range(8):
if grid_state[y][x] == null:
full_column = false
break
if full_column:
columns_to_clear.append(x)
# Clear rows and columns
for y in rows_to_clear:
for x in range(8):
clear_tile(x, y)
for x in columns_to_clear:
for y in range(8):
clear_tile(x, y)
# Notify the grids to refill
for grid in grid_nodes:
grid.refill_tiles()
func clear_tile(x: int, y: int):
# Find which 4x4 grid the tile belongs to
var grid_index = int(y / 4) * 2 + int(x / 4)
var local_x = x % 4
var local_y = y % 4
var grid = grid_nodes[grid_index]
grid.clear_tile(local_x, local_y)
# Update the grid state
grid_state[y][x] = null
Output
TileMapLayer is ready.
TileMapLayer found, connecting signal.
TileMapLayer found in Matrix4x4, connecting signal.
TileMapLayer is ready.
TileMapLayer found, connecting signal.
TileMapLayer found in Matrix4x4, connecting signal.
TileMapLayer is ready.
TileMapLayer found, connecting signal.
TileMapLayer found in Matrix4x4, connecting signal.
TileMapLayer is ready.
TileMapLayer found, connecting signal.
TileMapLayer found in Matrix4x4, connecting signal.