diff --git a/project.godot b/project.godot index b85da74..9143630 100644 --- a/project.godot +++ b/project.godot @@ -25,6 +25,7 @@ SettingsManager="*res://src/autoloads/SettingsManager.gd" AudioManager="*res://src/autoloads/AudioManager.gd" GameManager="*res://src/autoloads/GameManager.gd" LocalizationManager="*res://src/autoloads/LocalizationManager.gd" +DebugManager="*res://src/autoloads/DebugManager.gd" [input] diff --git a/scenes/game/game.gd b/scenes/game/game.gd index a873cff..65a91d6 100644 --- a/scenes/game/game.gd +++ b/scenes/game/game.gd @@ -1,27 +1,17 @@ extends Node @onready var back_button: Button = $BackButtonContainer/BackButton -const MATCH3_SCENE_PATH := "res://scenes/match3/match3.tscn" -var match3_instance: Node +# Fixed: Use static Match3 instance from scene instead of dynamic loading +@onready var match3_instance: Node = $Match3 func _ready() -> void: if not back_button.pressed.is_connected(_on_back_button_pressed): back_button.pressed.connect(_on_back_button_pressed) - _load_match3_scene() + # Fixed: No need to load match3 scene - it's already in the scene tree func _on_back_button_pressed() -> void: AudioManager.play_ui_click() GameManager.save_game() - if match3_instance and is_instance_valid(match3_instance): - match3_instance.queue_free() + # Fixed: Don't free the static instance, just exit GameManager.exit_to_main_menu() - -func _load_match3_scene() -> void: - var match3_scene := load(MATCH3_SCENE_PATH) - if not match3_scene or not match3_scene is PackedScene: - push_error("Failed to load Match3 scene at: %s" % MATCH3_SCENE_PATH) - return - - match3_instance = match3_scene.instantiate() - add_child(match3_instance) diff --git a/scenes/game/game.tscn b/scenes/game/game.tscn index e302b0c..8640338 100644 --- a/scenes/game/game.tscn +++ b/scenes/game/game.tscn @@ -1,7 +1,9 @@ -[gd_scene load_steps=3 format=3 uid="uid://dmwkyeq2l7u04"] +[gd_scene load_steps=5 format=3 uid="uid://dmwkyeq2l7u04"] [ext_resource type="Script" uid="uid://b16jnk7w22mb" path="res://scenes/game/game.gd" id="1_uwrxv"] [ext_resource type="PackedScene" uid="uid://b4kv7g7kllwgb" path="res://scenes/match3/match3.tscn" id="2_yqjtg"] +[ext_resource type="PackedScene" path="res://scenes/ui/DebugToggle.tscn" id="3_debug"] +[ext_resource type="PackedScene" uid="uid://fax5m4ywp1r3" path="res://scenes/ui/DebugMenu.tscn" id="4_debug_menu"] [node name="Game" type="Node"] script = ExtResource("1_uwrxv") @@ -19,3 +21,7 @@ offset_bottom = 31.0 text = "back" [node name="Match3" parent="." instance=ExtResource("2_yqjtg")] + +[node name="DebugToggle" parent="." instance=ExtResource("3_debug")] + +[node name="DebugMenu" parent="." instance=ExtResource("4_debug_menu")] diff --git a/scenes/main/main.tscn b/scenes/main/main.tscn index f59170a..a8967f1 100644 --- a/scenes/main/main.tscn +++ b/scenes/main/main.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=4 format=3 uid="uid://ci2gk11211n0d"] +[gd_scene load_steps=5 format=3 uid="uid://ci2gk11211n0d"] [ext_resource type="Script" uid="uid://b0uwk2jlm6g08" path="res://scenes/main/Main.gd" id="1_0wfyh"] [ext_resource type="PackedScene" uid="uid://gbe1jarrwqsi" path="res://scenes/main/PressAnyKeyScreen.tscn" id="1_o5qli"] [ext_resource type="Texture2D" uid="uid://c8y6tlvcgh2gn" path="res://assets/textures/backgrounds/beanstalk-dark.webp" id="2_sugp2"] +[ext_resource type="PackedScene" path="res://scenes/ui/DebugToggle.tscn" id="4_v7g8d"] [node name="main" type="Control"] layout_mode = 3 @@ -25,3 +26,6 @@ stretch_mode = 1 [node name="PressAnyKeyScreen" parent="." instance=ExtResource("1_o5qli")] layout_mode = 1 + +[node name="DebugToggle" parent="." instance=ExtResource("4_v7g8d")] +layout_mode = 1 diff --git a/scenes/match3/match3.gd b/scenes/match3/match3.gd index 0640181..ef2317e 100644 --- a/scenes/match3/match3.gd +++ b/scenes/match3/match3.gd @@ -1,26 +1,71 @@ extends Node2D -const GRID_SIZE := Vector2i(8, 8) -const TILE_TYPES := 5 +var GRID_SIZE := Vector2i(8, 8) +var TILE_TYPES := 5 const TILE_SCENE := preload("res://scenes/match3/tile.tscn") var grid := [] +var tile_size: float = 48.0 +var grid_offset: Vector2 func _ready(): + # Set up initial gem pool + var gem_indices = [] + for i in range(TILE_TYPES): + gem_indices.append(i) + + const TileScript = preload("res://scenes/match3/tile.gd") + TileScript.set_active_gem_pool(gem_indices) + + _calculate_grid_layout() _initialize_grid() +func _calculate_grid_layout(): + var viewport_size = get_viewport().get_visible_rect().size + var available_width = viewport_size.x * 0.8 # Use 80% of screen width + var available_height = viewport_size.y * 0.7 # Use 70% of screen height + + # Calculate tile size based on available space + var max_tile_width = available_width / GRID_SIZE.x + var max_tile_height = available_height / GRID_SIZE.y + tile_size = min(max_tile_width, max_tile_height) + + # Align grid to left side with some margin + var total_grid_height = tile_size * GRID_SIZE.y + grid_offset = Vector2( + 50, # Left margin + (viewport_size.y - total_grid_height) / 2 + 50 # Vertically centered with top margin + ) + func _initialize_grid(): + # Update gem pool BEFORE creating any tiles + var gem_indices = [] + for i in range(TILE_TYPES): + gem_indices.append(i) + + const TileScript = preload("res://scenes/match3/tile.gd") + TileScript.set_active_gem_pool(gem_indices) + for y in range(GRID_SIZE.y): grid.append([]) for x in range(GRID_SIZE.x): var tile = TILE_SCENE.instantiate() - tile.position = Vector2(x, y) * 64 # Adjust to your tile size + tile.position = grid_offset + Vector2(x, y) * tile_size tile.grid_position = Vector2i(x, y) - tile.tile_type = randi() % TILE_TYPES add_child(tile) + # Set tile type after adding to scene tree so sprite reference is available + var new_type = randi() % TILE_TYPES + tile.tile_type = new_type + print("Debug: Created tile at (", x, ",", y, ") with type ", new_type) grid[y].append(tile) func _has_match_at(pos: Vector2i) -> bool: + # Fixed: Add bounds and null checks + if pos.x < 0 or pos.y < 0 or pos.x >= GRID_SIZE.x or pos.y >= GRID_SIZE.y: + return false + if not grid[pos.y][pos.x]: + return false + var matches_horizontal = _get_match_line(pos, Vector2i(1, 0)) if matches_horizontal.size() >= 3: return true @@ -28,15 +73,25 @@ func _has_match_at(pos: Vector2i) -> bool: var matches_vertical = _get_match_line(pos, Vector2i(0, 1)) return matches_vertical.size() >= 3 +# Fixed: Add missing function to check for any matches on the board +func _check_for_matches() -> bool: + for y in range(GRID_SIZE.y): + for x in range(GRID_SIZE.x): + if _has_match_at(Vector2i(x, y)): + return true + return false + func _get_match_line(start: Vector2i, dir: Vector2i) -> Array: var line = [grid[start.y][start.x]] var type = grid[start.y][start.x].tile_type + # Fixed: Check in both directions separately to avoid infinite loops for offset in [1, -1]: var current = start + dir * offset while current.x >= 0 and current.y >= 0 and current.x < GRID_SIZE.x and current.y < GRID_SIZE.y: var neighbor = grid[current.y][current.x] - if neighbor.tile_type != type: + # Fixed: Add null check to prevent crashes + if not neighbor or neighbor.tile_type != type: break line.append(neighbor) current += dir * offset @@ -48,6 +103,9 @@ func _clear_matches(): for y in range(GRID_SIZE.y): for x in range(GRID_SIZE.x): + # Fixed: Add null check before processing + if not grid[y][x]: + continue var pos = Vector2i(x, y) var horiz = _get_match_line(pos, Vector2i(1, 0)) if horiz.size() >= 3: @@ -62,6 +120,10 @@ func _clear_matches(): unique_dict[tile] = true to_clear = unique_dict.keys() + # Fixed: Only proceed if there are matches to clear + if to_clear.size() == 0: + return + for tile in to_clear: grid[tile.grid_position.y][tile.grid_position.x] = null tile.queue_free() @@ -75,15 +137,17 @@ func _drop_tiles(): while moved: moved = false for x in range(GRID_SIZE.x): - for y in range(GRID_SIZE.y - 2, -1, -1): + # Fixed: Start from GRID_SIZE.y - 1 to avoid out of bounds + for y in range(GRID_SIZE.y - 1, -1, -1): var tile = grid[y][x] - if tile and not grid[y + 1][x]: + # Fixed: Check bounds before accessing y + 1 + if tile and y + 1 < GRID_SIZE.y and not grid[y + 1][x]: grid[y + 1][x] = tile grid[y][x] = null tile.grid_position = Vector2i(x, y + 1) # You can animate position here using Tween for smooth drop: - # tween.interpolate_property(tile, "position", tile.position, Vector2(x, y + 1) * 64, 0.2) - tile.position = Vector2(x, y + 1) * 64 + # tween.interpolate_property(tile, "position", tile.position, grid_offset + Vector2(x, y + 1) * tile_size, 0.2) + tile.position = grid_offset + Vector2(x, y + 1) * tile_size moved = true func _fill_empty_cells(): @@ -93,10 +157,63 @@ func _fill_empty_cells(): var tile = TILE_SCENE.instantiate() tile.grid_position = Vector2i(x, y) tile.tile_type = randi() % TILE_TYPES - tile.position = Vector2(x, y) * 64 + tile.position = grid_offset + Vector2(x, y) * tile_size grid[y][x] = tile add_child(tile) - # Recheck matches + # Fixed: Add recursion protection to prevent stack overflow await get_tree().create_timer(0.1).timeout - _clear_matches() + var max_iterations = 10 + var iteration = 0 + while _check_for_matches() and iteration < max_iterations: + _clear_matches() + await get_tree().create_timer(0.1).timeout + iteration += 1 + +func regenerate_grid(): + # Use time-based seed to ensure different patterns each time + var new_seed = Time.get_ticks_msec() + seed(new_seed) + print("Debug: Regenerating grid with seed: ", new_seed) + + # Fixed: Clear ALL tile children, not just ones in grid array + # This handles any orphaned tiles that might not be tracked in the grid + var children_to_remove = [] + for child in get_children(): + if child.has_method("get_script") and child.get_script(): + var script_path = child.get_script().resource_path + if script_path == "res://scenes/match3/tile.gd": + children_to_remove.append(child) + + # Remove all found tile children + for child in children_to_remove: + child.free() + + # Also clear grid array references + for y in range(grid.size()): + if grid[y] and grid[y] is Array: + for x in range(grid[y].size()): + # Set to null since we already freed the nodes above + grid[y][x] = null + + # Clear the grid array + grid.clear() + + # No need to wait for nodes to be freed since we used free() + + # Fixed: Recalculate grid layout before regenerating tiles + _calculate_grid_layout() + + # Regenerate the grid (gem pool is updated in _initialize_grid) + _initialize_grid() + +func set_tile_types(new_count: int): + TILE_TYPES = new_count + # Regenerate grid with new tile types (gem pool is updated in regenerate_grid) + await regenerate_grid() + +func set_grid_size(new_size: Vector2i): + print("Debug: Changing grid size from ", GRID_SIZE, " to ", new_size) + GRID_SIZE = new_size + # Regenerate grid with new size + await regenerate_grid() diff --git a/scenes/match3/tile.gd b/scenes/match3/tile.gd index 21f2452..1536971 100644 --- a/scenes/match3/tile.gd +++ b/scenes/match3/tile.gd @@ -1,6 +1,6 @@ extends Node2D -@export var tile_type: int = 0 +@export var tile_type: int = 0 : set = _set_tile_type var grid_position: Vector2i @onready var sprite: Sprite2D = $Sprite2D @@ -20,20 +20,29 @@ var all_gem_textures = [ 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 = [0, 1, 2, 3, 4] # Start with first 5 gems +var active_gem_types = [] # Will be set from current_gem_pool func _set_tile_type(value: int) -> void: tile_type = value + print("Debug: _set_tile_type called with value ", value, ", active_gem_types.size() = ", active_gem_types.size()) + # 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: push_error("Invalid tile type: " + str(value) + ". Available types: 0-" + str(active_gem_types.size() - 1)) func _scale_sprite_to_fit() -> void: - if sprite.texture: + # 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 @@ -41,31 +50,41 @@ func _scale_sprite_to_fit() -> void: # Gem pool management functions static func set_active_gem_pool(gem_indices: Array) -> void: - # Update all tile instances to use new gem pool - var tiles = get_tree().get_nodes_in_group("tiles") - for tile in tiles: - if tile.has_method("_update_active_gems"): - tile._update_active_gems(gem_indices) + # 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(): - tile_type = 0 # Reset to first available type + # 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 tiles = get_tree().get_nodes_in_group("tiles") - if tiles.size() > 0: - return tiles[0].active_gem_types.size() + 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 tiles = get_tree().get_nodes_in_group("tiles") - for tile in tiles: - if tile.has_method("_add_gem_type"): - tile._add_gem_type(gem_index) + 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(): @@ -73,10 +92,12 @@ func _add_gem_type(gem_index: int) -> void: active_gem_types.append(gem_index) static func remove_gem_from_pool(gem_index: int) -> void: - var tiles = get_tree().get_nodes_in_group("tiles") - for tile in tiles: - if tile.has_method("_remove_gem_type"): - tile._remove_gem_type(gem_index) + 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) @@ -90,4 +111,6 @@ func _remove_gem_type(gem_index: int) -> void: # 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) diff --git a/scenes/ui/DebugButton.tscn b/scenes/ui/DebugButton.tscn new file mode 100644 index 0000000..b35b5df --- /dev/null +++ b/scenes/ui/DebugButton.tscn @@ -0,0 +1,25 @@ +[gd_scene load_steps=2 format=3 uid="uid://dmjfgs6r4yfwl"] + +[ext_resource type="Script" uid="uid://bt6a8gpw1e31c" path="res://scenes/ui/DebugButton.gd" id="1_debug_script"] + +[node name="DebugButton" type="Control"] +layout_mode = 3 +anchors_preset = 3 +anchor_left = 1.0 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -80.0 +offset_top = -40.0 +grow_horizontal = 0 +grow_vertical = 0 +script = ExtResource("1_debug_script") + +[node name="Button" type="Button" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +text = "DEBUG" diff --git a/scenes/ui/DebugMenu.gd b/scenes/ui/DebugMenu.gd new file mode 100644 index 0000000..e1ef3de --- /dev/null +++ b/scenes/ui/DebugMenu.gd @@ -0,0 +1,203 @@ +extends Control + +@onready var regenerate_button: Button = $VBoxContainer/RegenerateButton +@onready var gem_types_spinbox: SpinBox = $VBoxContainer/GemTypesContainer/GemTypesSpinBox +@onready var gem_types_label: Label = $VBoxContainer/GemTypesContainer/GemTypesLabel +@onready var grid_width_spinbox: SpinBox = $VBoxContainer/GridSizeContainer/GridWidthContainer/GridWidthSpinBox +@onready var grid_height_spinbox: SpinBox = $VBoxContainer/GridSizeContainer/GridHeightContainer/GridHeightSpinBox +@onready var grid_width_label: Label = $VBoxContainer/GridSizeContainer/GridWidthContainer/GridWidthLabel +@onready var grid_height_label: Label = $VBoxContainer/GridSizeContainer/GridHeightContainer/GridHeightLabel + +var match3_scene: Node2D +var search_timer: Timer + +# Fixed: Add cleanup function +func _exit_tree(): + if search_timer: + search_timer.queue_free() + +func _ready(): + visible = false + DebugManager.debug_toggled.connect(_on_debug_toggled) + regenerate_button.pressed.connect(_on_regenerate_pressed) + gem_types_spinbox.value_changed.connect(_on_gem_types_changed) + grid_width_spinbox.value_changed.connect(_on_grid_width_changed) + grid_height_spinbox.value_changed.connect(_on_grid_height_changed) + + # Initialize gem types spinbox + gem_types_spinbox.min_value = 3 + gem_types_spinbox.max_value = 8 + gem_types_spinbox.step = 1 + gem_types_spinbox.value = 5 # Default value + + # Initialize grid size spinboxes + grid_width_spinbox.min_value = 4 + grid_width_spinbox.max_value = 12 + grid_width_spinbox.step = 1 + grid_width_spinbox.value = 8 # Default value + + grid_height_spinbox.min_value = 4 + grid_height_spinbox.max_value = 12 + grid_height_spinbox.step = 1 + grid_height_spinbox.value = 8 # Default value + + # Fixed: Create timer for periodic match3 scene search + search_timer = Timer.new() + search_timer.wait_time = 0.1 + search_timer.timeout.connect(_find_match3_scene) + add_child(search_timer) + + # Start searching immediately and continue until found + _find_match3_scene() + +func _find_match3_scene(): + # Fixed: Search more thoroughly for match3 scene + if match3_scene: + # Already found, stop searching + if search_timer and search_timer.timeout.is_connected(_find_match3_scene): + search_timer.stop() + return + + # Search in current scene tree + var current_scene = get_tree().current_scene + if current_scene: + # Try to find match3 by class name first + match3_scene = _find_node_by_script(current_scene, "res://scenes/match3/match3.gd") + + # Fallback: search by common node names + if not match3_scene: + for possible_name in ["Match3", "match3", "Match3Game"]: + match3_scene = current_scene.find_child(possible_name, true, false) + if match3_scene: + break + + if match3_scene: + print("Debug: Found match3 scene: ", match3_scene.name) + # Update UI with current values + if match3_scene.has_method("get") and "TILE_TYPES" in match3_scene: + gem_types_spinbox.value = match3_scene.TILE_TYPES + gem_types_label.text = "Gem Types: " + str(match3_scene.TILE_TYPES) + + # Update grid size values + if "GRID_SIZE" in match3_scene: + var grid_size = match3_scene.GRID_SIZE + grid_width_spinbox.value = grid_size.x + grid_height_spinbox.value = grid_size.y + grid_width_label.text = "Width: " + str(grid_size.x) + grid_height_label.text = "Height: " + str(grid_size.y) + + # Stop the search timer + if search_timer and search_timer.timeout.is_connected(_find_match3_scene): + search_timer.stop() + else: + # Continue searching if not found + if search_timer and not search_timer.timeout.is_connected(_find_match3_scene): + search_timer.timeout.connect(_find_match3_scene) + search_timer.start() + +func _find_node_by_script(node: Node, script_path: String) -> Node: + # Helper function to find node by its script path + if node.get_script(): + var node_script = node.get_script() + if node_script.resource_path == script_path: + return node + + for child in node.get_children(): + var result = _find_node_by_script(child, script_path) + if result: + return result + + return null + +func _on_debug_toggled(enabled: bool): + visible = enabled + if enabled: + # Always refresh match3 scene reference when debug menu opens + if not match3_scene: + _find_match3_scene() + # Update display values + if match3_scene and match3_scene.has_method("get") and "TILE_TYPES" in match3_scene: + gem_types_spinbox.value = match3_scene.TILE_TYPES + gem_types_label.text = "Gem Types: " + str(match3_scene.TILE_TYPES) + + # Update grid size display values + if match3_scene and "GRID_SIZE" in match3_scene: + var grid_size = match3_scene.GRID_SIZE + grid_width_spinbox.value = grid_size.x + grid_height_spinbox.value = grid_size.y + grid_width_label.text = "Width: " + str(grid_size.x) + grid_height_label.text = "Height: " + str(grid_size.y) + +func _on_regenerate_pressed(): + if not match3_scene: + _find_match3_scene() + + if not match3_scene: + print("Error: Could not find match3 scene for regeneration") + return + + if match3_scene.has_method("regenerate_grid"): + print("Debug: Calling regenerate_grid()") + await match3_scene.regenerate_grid() + else: + print("Error: match3_scene does not have regenerate_grid method") + +func _on_gem_types_changed(value: float): + if not match3_scene: + _find_match3_scene() + + if not match3_scene: + print("Error: Could not find match3 scene for gem types change") + return + + var new_value = int(value) + if match3_scene.has_method("set_tile_types"): + print("Debug: Setting tile types to ", new_value) + await match3_scene.set_tile_types(new_value) + gem_types_label.text = "Gem Types: " + str(new_value) + else: + print("Error: match3_scene does not have set_tile_types method") + # Fallback: try to set TILE_TYPES directly + if "TILE_TYPES" in match3_scene: + match3_scene.TILE_TYPES = new_value + gem_types_label.text = "Gem Types: " + str(new_value) + +func _on_grid_width_changed(value: float): + if not match3_scene: + _find_match3_scene() + + if not match3_scene: + print("Error: Could not find match3 scene for grid width change") + return + + var new_width = int(value) + grid_width_label.text = "Width: " + str(new_width) + + # Get current height + var current_height = int(grid_height_spinbox.value) + + if match3_scene.has_method("set_grid_size"): + print("Debug: Setting grid size to ", new_width, "x", current_height) + await match3_scene.set_grid_size(Vector2i(new_width, current_height)) + else: + print("Error: match3_scene does not have set_grid_size method") + +func _on_grid_height_changed(value: float): + if not match3_scene: + _find_match3_scene() + + if not match3_scene: + print("Error: Could not find match3 scene for grid height change") + return + + var new_height = int(value) + grid_height_label.text = "Height: " + str(new_height) + + # Get current width + var current_width = int(grid_width_spinbox.value) + + if match3_scene.has_method("set_grid_size"): + print("Debug: Setting grid size to ", current_width, "x", new_height) + await match3_scene.set_grid_size(Vector2i(current_width, new_height)) + else: + print("Error: match3_scene does not have set_grid_size method") diff --git a/scenes/ui/DebugMenu.tscn b/scenes/ui/DebugMenu.tscn new file mode 100644 index 0000000..3ce79da --- /dev/null +++ b/scenes/ui/DebugMenu.tscn @@ -0,0 +1,83 @@ +[gd_scene load_steps=2 format=3 uid="uid://fax5m4ywp1r3"] + +[ext_resource type="Script" uid="uid://b4ppfg1tb0al0" path="res://scenes/ui/DebugMenu.gd" id="1_debug_menu"] + +[node name="DebugMenu" type="Control"] +layout_mode = 3 +anchors_preset = 1 +anchor_left = 1.0 +anchor_right = 1.0 +offset_left = -201.0 +offset_top = 59.0 +offset_right = -11.0 +offset_bottom = 169.0 +grow_horizontal = 0 +script = ExtResource("1_debug_menu") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 10.0 +offset_top = 10.0 +offset_right = -10.0 +offset_bottom = -10.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="TitleLabel" type="Label" parent="VBoxContainer"] +layout_mode = 2 +text = "Debug Menu" +horizontal_alignment = 1 + +[node name="RegenerateButton" type="Button" parent="VBoxContainer"] +layout_mode = 2 +text = "Generate New Grid" + +[node name="GemTypesContainer" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="GemTypesLabel" type="Label" parent="VBoxContainer/GemTypesContainer"] +layout_mode = 2 +text = "Gem Types: 5" + +[node name="GemTypesSpinBox" type="SpinBox" parent="VBoxContainer/GemTypesContainer"] +layout_mode = 2 +min_value = 3.0 +max_value = 8.0 +value = 5.0 + +[node name="GridSizeContainer" type="VBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="GridSizeLabel" type="Label" parent="VBoxContainer/GridSizeContainer"] +layout_mode = 2 +text = "Grid Size" +horizontal_alignment = 1 + +[node name="GridWidthContainer" type="HBoxContainer" parent="VBoxContainer/GridSizeContainer"] +layout_mode = 2 + +[node name="GridWidthLabel" type="Label" parent="VBoxContainer/GridSizeContainer/GridWidthContainer"] +layout_mode = 2 +text = "Width: 8" + +[node name="GridWidthSpinBox" type="SpinBox" parent="VBoxContainer/GridSizeContainer/GridWidthContainer"] +layout_mode = 2 +min_value = 4.0 +max_value = 12.0 +value = 8.0 + +[node name="GridHeightContainer" type="HBoxContainer" parent="VBoxContainer/GridSizeContainer"] +layout_mode = 2 + +[node name="GridHeightLabel" type="Label" parent="VBoxContainer/GridSizeContainer/GridHeightContainer"] +layout_mode = 2 +text = "Height: 8" + +[node name="GridHeightSpinBox" type="SpinBox" parent="VBoxContainer/GridSizeContainer/GridHeightContainer"] +layout_mode = 2 +min_value = 4.0 +max_value = 12.0 +value = 8.0 diff --git a/scenes/ui/DebugToggle.gd b/scenes/ui/DebugToggle.gd new file mode 100644 index 0000000..24733f7 --- /dev/null +++ b/scenes/ui/DebugToggle.gd @@ -0,0 +1,12 @@ +extends Button + +func _ready(): + text = "Debug: OFF" + pressed.connect(_on_pressed) + DebugManager.debug_toggled.connect(_on_debug_toggled) + +func _on_pressed(): + DebugManager.toggle_debug() + +func _on_debug_toggled(enabled: bool): + text = "Debug: " + ("ON" if enabled else "OFF") \ No newline at end of file diff --git a/scenes/ui/DebugToggle.tscn b/scenes/ui/DebugToggle.tscn new file mode 100644 index 0000000..8aa5059 --- /dev/null +++ b/scenes/ui/DebugToggle.tscn @@ -0,0 +1,18 @@ +[gd_scene load_steps=2 format=3 uid="uid://df2b4wn8j6cxl"] + +[ext_resource type="Script" path="res://scenes/ui/DebugToggle.gd" id="1_gn2ol"] + +[node name="DebugToggle" type="Button"] +anchors_preset = 3 +anchor_left = 1.0 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -110.0 +offset_top = -40.0 +offset_right = -10.0 +offset_bottom = -10.0 +grow_horizontal = 0 +grow_vertical = 0 +text = "Debug: OFF" +script = ExtResource("1_gn2ol") \ No newline at end of file diff --git a/src/autoloads/DebugManager.gd b/src/autoloads/DebugManager.gd new file mode 100644 index 0000000..8669935 --- /dev/null +++ b/src/autoloads/DebugManager.gd @@ -0,0 +1,35 @@ +extends Node + +signal debug_toggled(enabled: bool) + +var debug_enabled: bool = false +var debug_overlay_visible: bool = false + +func _ready(): + print("DebugManager loaded") + +func toggle_debug(): + debug_enabled = !debug_enabled + debug_toggled.emit(debug_enabled) + print("Debug mode: ", "ON" if debug_enabled else "OFF") + +func set_debug_enabled(enabled: bool): + if debug_enabled != enabled: + debug_enabled = enabled + debug_toggled.emit(debug_enabled) + +func is_debug_enabled() -> bool: + return debug_enabled + +func toggle_overlay(): + debug_overlay_visible = !debug_overlay_visible + +func set_overlay_visible(visible: bool): + debug_overlay_visible = visible + +func is_overlay_visible() -> bool: + return debug_overlay_visible + +func log_debug(message: String, category: String = "DEBUG"): + if debug_enabled: + print("[", category, "] ", message)