use proper logging everywhere add gamepad and keyboard control on match3 gameplay
192 lines
7.7 KiB
GDScript
192 lines
7.7 KiB
GDScript
extends Node2D
|
|
|
|
signal tile_selected(tile: Node2D)
|
|
|
|
@export var tile_type: int = 0 : set = _set_tile_type
|
|
var grid_position: Vector2i
|
|
var is_selected: bool = false : set = _set_selected
|
|
var is_highlighted: bool = false : set = _set_highlighted
|
|
var original_scale: Vector2 = Vector2.ONE # Store the original scale for the board
|
|
|
|
@onready var sprite: Sprite2D = $Sprite2D
|
|
|
|
# Target size for each tile to fit in the 54x54 grid cells
|
|
const TILE_SIZE = 48 # Slightly smaller than 54 to leave some padding
|
|
|
|
# All available gem textures
|
|
var all_gem_textures = [
|
|
preload("res://assets/sprites/gems/bg_19.png"), # 0 - Blue gem
|
|
preload("res://assets/sprites/gems/dg_19.png"), # 1 - Dark gem
|
|
preload("res://assets/sprites/gems/gg_19.png"), # 2 - Green gem
|
|
preload("res://assets/sprites/gems/mg_19.png"), # 3 - Magenta gem
|
|
preload("res://assets/sprites/gems/rg_19.png"), # 4 - Red gem
|
|
preload("res://assets/sprites/gems/yg_19.png"), # 5 - Yellow gem
|
|
preload("res://assets/sprites/gems/pg_19.png"), # 6 - Purple gem
|
|
preload("res://assets/sprites/gems/sg_19.png"), # 7 - Silver gem
|
|
]
|
|
|
|
# Static variable to store the current gem pool for all tiles
|
|
static var current_gem_pool = [0, 1, 2, 3, 4] # Start with first 5 gems
|
|
|
|
# Currently active gem types (indices into all_gem_textures)
|
|
var active_gem_types = [] # Will be set from current_gem_pool
|
|
|
|
func _set_tile_type(value: int) -> void:
|
|
tile_type = value
|
|
# Fixed: Add sprite null check to prevent crashes during initialization
|
|
if not sprite:
|
|
return
|
|
if value >= 0 and value < active_gem_types.size():
|
|
var texture_index = active_gem_types[value]
|
|
sprite.texture = all_gem_textures[texture_index]
|
|
# print("Debug: Set texture_index ", texture_index, " for tile_type ", value)
|
|
_scale_sprite_to_fit()
|
|
else:
|
|
DebugManager.log_error("Invalid tile type: " + str(value) + ". Available types: 0-" + str(active_gem_types.size() - 1), "Match3")
|
|
|
|
func _scale_sprite_to_fit() -> void:
|
|
# Fixed: Add additional null checks
|
|
if sprite and sprite.texture:
|
|
var texture_size = sprite.texture.get_size()
|
|
var max_dimension = max(texture_size.x, texture_size.y)
|
|
var scale_factor = TILE_SIZE / max_dimension
|
|
original_scale = Vector2(scale_factor, scale_factor)
|
|
sprite.scale = original_scale
|
|
DebugManager.log_debug("Set original scale to %s for tile (%d,%d)" % [original_scale, grid_position.x, grid_position.y], "Match3")
|
|
|
|
# Gem pool management functions
|
|
static func set_active_gem_pool(gem_indices: Array) -> void:
|
|
# Update static gem pool for new tiles
|
|
current_gem_pool = gem_indices.duplicate()
|
|
|
|
# Update all existing tile instances to use new gem pool
|
|
var scene_tree = Engine.get_main_loop() as SceneTree
|
|
if scene_tree:
|
|
var tiles = scene_tree.get_nodes_in_group("tiles")
|
|
for tile in tiles:
|
|
if tile.has_method("_update_active_gems"):
|
|
tile._update_active_gems(gem_indices)
|
|
|
|
func _update_active_gems(gem_indices: Array) -> void:
|
|
active_gem_types = gem_indices.duplicate()
|
|
# Re-validate current tile type
|
|
if tile_type >= active_gem_types.size():
|
|
# Generate a new random tile type within valid range
|
|
tile_type = randi() % active_gem_types.size()
|
|
_set_tile_type(tile_type)
|
|
|
|
static func get_active_gem_count() -> int:
|
|
# Get from any tile instance or default
|
|
var scene_tree = Engine.get_main_loop() as SceneTree
|
|
if scene_tree:
|
|
var tiles = scene_tree.get_nodes_in_group("tiles")
|
|
if tiles.size() > 0:
|
|
return tiles[0].active_gem_types.size()
|
|
return 5 # Default
|
|
|
|
static func add_gem_to_pool(gem_index: int) -> void:
|
|
var scene_tree = Engine.get_main_loop() as SceneTree
|
|
if scene_tree:
|
|
var tiles = scene_tree.get_nodes_in_group("tiles")
|
|
for tile in tiles:
|
|
if tile.has_method("_add_gem_type"):
|
|
tile._add_gem_type(gem_index)
|
|
|
|
func _add_gem_type(gem_index: int) -> void:
|
|
if gem_index >= 0 and gem_index < all_gem_textures.size():
|
|
if not active_gem_types.has(gem_index):
|
|
active_gem_types.append(gem_index)
|
|
|
|
static func remove_gem_from_pool(gem_index: int) -> void:
|
|
var scene_tree = Engine.get_main_loop() as SceneTree
|
|
if scene_tree:
|
|
var tiles = scene_tree.get_nodes_in_group("tiles")
|
|
for tile in tiles:
|
|
if tile.has_method("_remove_gem_type"):
|
|
tile._remove_gem_type(gem_index)
|
|
|
|
func _remove_gem_type(gem_index: int) -> void:
|
|
var type_index = active_gem_types.find(gem_index)
|
|
if type_index != -1 and active_gem_types.size() > 2: # Keep at least 2 gem types
|
|
active_gem_types.erase(gem_index)
|
|
# Update tiles that were using removed type
|
|
if tile_type >= active_gem_types.size():
|
|
tile_type = 0
|
|
_set_tile_type(tile_type)
|
|
|
|
func _set_selected(value: bool) -> void:
|
|
var old_value = is_selected
|
|
is_selected = value
|
|
DebugManager.log_debug("Tile (%d,%d) selection changed: %s -> %s" % [grid_position.x, grid_position.y, old_value, value], "Match3")
|
|
_update_visual_feedback()
|
|
|
|
func _set_highlighted(value: bool) -> void:
|
|
var old_value = is_highlighted
|
|
is_highlighted = value
|
|
DebugManager.log_debug("Tile (%d,%d) highlight changed: %s -> %s" % [grid_position.x, grid_position.y, old_value, value], "Match3")
|
|
_update_visual_feedback()
|
|
|
|
func _update_visual_feedback() -> void:
|
|
if not sprite:
|
|
return
|
|
|
|
# Determine target values based on priority: selected > highlighted > normal
|
|
var target_modulate: Color
|
|
var target_scale: Vector2
|
|
var scale_multiplier: float
|
|
|
|
if is_selected:
|
|
# Selected: bright and 20% larger than original board size
|
|
target_modulate = Color(1.2, 1.2, 1.2, 1.0)
|
|
scale_multiplier = 1.2
|
|
DebugManager.log_debug("SELECTING tile (%d,%d): target scale %.2fx, current scale %s" % [grid_position.x, grid_position.y, scale_multiplier, sprite.scale], "Match3")
|
|
elif is_highlighted:
|
|
# Highlighted: subtle glow and 10% larger than original board size
|
|
target_modulate = Color(1.1, 1.1, 1.1, 1.0)
|
|
scale_multiplier = 1.1
|
|
DebugManager.log_debug("HIGHLIGHTING tile (%d,%d): target scale %.2fx, current scale %s" % [grid_position.x, grid_position.y, scale_multiplier, sprite.scale], "Match3")
|
|
else:
|
|
# Normal state: white and original board size
|
|
target_modulate = Color.WHITE
|
|
scale_multiplier = 1.0
|
|
DebugManager.log_debug("NORMALIZING tile (%d,%d): target scale %.2fx, current scale %s" % [grid_position.x, grid_position.y, scale_multiplier, sprite.scale], "Match3")
|
|
|
|
# Calculate target scale relative to original board scale
|
|
target_scale = original_scale * scale_multiplier
|
|
|
|
# Apply modulate immediately
|
|
sprite.modulate = target_modulate
|
|
|
|
# Only animate scale if it's actually changing
|
|
if sprite.scale != target_scale:
|
|
DebugManager.log_debug("Animating scale from %s to %s for tile (%d,%d)" % [sprite.scale, target_scale, grid_position.x, grid_position.y], "Match3")
|
|
|
|
var tween = create_tween()
|
|
tween.tween_property(sprite, "scale", target_scale, 0.15)
|
|
|
|
# Add completion callback for debugging
|
|
tween.tween_callback(_on_scale_animation_completed.bind(target_scale))
|
|
else:
|
|
DebugManager.log_debug("No scale change needed for tile (%d,%d)" % [grid_position.x, grid_position.y], "Match3")
|
|
|
|
func _on_scale_animation_completed(expected_scale: Vector2) -> void:
|
|
DebugManager.log_debug("Scale animation completed for tile (%d,%d): expected %s, actual %s" % [grid_position.x, grid_position.y, expected_scale, sprite.scale], "Match3")
|
|
|
|
func force_reset_visual_state() -> void:
|
|
# Force reset all visual states - debug function
|
|
is_selected = false
|
|
is_highlighted = false
|
|
if sprite:
|
|
sprite.modulate = Color.WHITE
|
|
sprite.scale = original_scale # Reset to original board scale, not 1.0
|
|
DebugManager.log_debug("Forced visual reset on tile (%d,%d) to original scale %s" % [grid_position.x, grid_position.y, original_scale], "Match3")
|
|
|
|
# Called when the node enters the scene tree for the first time.
|
|
func _ready() -> void:
|
|
add_to_group("tiles") # Add to group for gem pool management
|
|
# Initialize with current static gem pool
|
|
active_gem_types = current_gem_pool.duplicate()
|
|
_set_tile_type(tile_type)
|
|
|
|
|