match-3 grid generation

make game scene modular
global debug mode
This commit is contained in:
2025-09-24 10:45:14 +04:00
committed by nett00n
parent e11e864b26
commit 7182c45351
21 changed files with 506 additions and 94 deletions

View File

@@ -1,17 +1,63 @@
extends Node
extends Control
const GAMEPLAY_SCENES = {
"match3": "res://scenes/game/gameplays/match3_gameplay.tscn",
"clickomania": "res://scenes/game/gameplays/clickomania_gameplay.tscn"
}
@onready var back_button: Button = $BackButtonContainer/BackButton
# Fixed: Use static Match3 instance from scene instead of dynamic loading
@onready var match3_instance: Node = $Match3
@onready var gameplay_container: Control = $GameplayContainer
@onready var score_display: Label = $UI/ScoreDisplay
var current_gameplay_mode: String
var global_score: int = 0 : set = set_global_score
func _ready() -> void:
if not back_button.pressed.is_connected(_on_back_button_pressed):
back_button.pressed.connect(_on_back_button_pressed)
# Fixed: No need to load match3 scene - it's already in the scene tree
# Default to match3 for now
set_gameplay_mode("match3")
func set_gameplay_mode(mode: String) -> void:
current_gameplay_mode = mode
load_gameplay(mode)
func load_gameplay(mode: String) -> void:
# Clear existing gameplay
for child in gameplay_container.get_children():
child.queue_free()
# Load new gameplay
if GAMEPLAY_SCENES.has(mode):
var gameplay_scene = load(GAMEPLAY_SCENES[mode])
var gameplay_instance = gameplay_scene.instantiate()
gameplay_container.add_child(gameplay_instance)
# Connect gameplay signals to shared systems
if gameplay_instance.has_signal("score_changed"):
gameplay_instance.score_changed.connect(_on_score_changed)
func set_global_score(value: int) -> void:
global_score = value
if score_display:
score_display.text = "Score: " + str(global_score)
func _on_score_changed(points: int) -> void:
self.global_score += points
func _on_back_button_pressed() -> void:
print("Back button pressed in game scene")
AudioManager.play_ui_click()
GameManager.save_game()
# Fixed: Don't free the static instance, just exit
GameManager.exit_to_main_menu()
func _input(event: InputEvent) -> void:
if event.is_action_pressed("ui_accept") and Input.is_action_pressed("ui_select"):
# Debug: Switch to clickomania when Space+Enter pressed together
if current_gameplay_mode == "match3":
set_gameplay_mode("clickomania")
print("Switched to clickomania gameplay")
else:
set_gameplay_mode("match3")
print("Switched to match3 gameplay")

View File

@@ -1,27 +1,74 @@
[gd_scene load_steps=5 format=3 uid="uid://dmwkyeq2l7u04"]
[gd_scene load_steps=4 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"]
[ext_resource type="Texture2D" uid="uid://c8y6tlvcgh2gn" path="res://assets/textures/backgrounds/beanstalk-dark.webp" id="5_background"]
[node name="Game" type="Node"]
[node name="Game" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_uwrxv")
[node name="Background" type="TextureRect" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
texture = ExtResource("5_background")
stretch_mode = 1
[node name="UI" type="Control" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="ScoreDisplay" type="Label" parent="UI"]
layout_mode = 1
anchors_preset = 2
anchor_top = 1.0
anchor_bottom = 1.0
offset_left = 10.0
offset_top = -31.0
offset_right = 110.0
offset_bottom = -10.0
grow_vertical = 0
text = "Score: 0"
[node name="GameplayContainer" type="Control" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="BackButtonContainer" type="Control" parent="."]
layout_mode = 3
layout_mode = 1
anchors_preset = 0
offset_right = 40.0
offset_bottom = 40.0
offset_left = 10.0
offset_top = 10.0
offset_right = 55.0
offset_bottom = 41.0
[node name="BackButton" type="Button" parent="BackButtonContainer"]
layout_mode = 0
offset_right = 45.0
offset_bottom = 31.0
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
text = "back"
[node name="Match3" parent="." instance=ExtResource("2_yqjtg")]
[node name="DebugToggle" parent="." instance=ExtResource("3_debug")]
layout_mode = 1
[node name="DebugMenu" parent="." instance=ExtResource("4_debug_menu")]
[connection signal="pressed" from="BackButtonContainer/BackButton" to="." method="_on_back_button_pressed"]

View File

@@ -0,0 +1,129 @@
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
func _ready():
print("Match3DebugMenu: _ready() called")
DebugManager.debug_toggled.connect(_on_debug_toggled)
# Initialize with current debug state
var current_debug_state = DebugManager.is_debug_enabled()
print("Match3DebugMenu: Current debug state is ", current_debug_state)
visible = current_debug_state
print("Match3DebugMenu: Initial visibility set to ", visible)
if current_debug_state:
_on_debug_toggled(true)
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)
func _find_match3_scene():
# Debug menu is now: Match3 -> UILayer -> Match3DebugMenu
# So we need to go up two levels: get_parent() = UILayer, get_parent().get_parent() = Match3
var ui_layer = get_parent()
if ui_layer and ui_layer is CanvasLayer:
match3_scene = ui_layer.get_parent()
if match3_scene and match3_scene.get_script():
var script_path = match3_scene.get_script().resource_path
if script_path == "res://scenes/game/gameplays/match3_gameplay.gd":
print("Debug: Found match3 scene: ", match3_scene.name, " at path: ", match3_scene.get_path())
return
# If we couldn't find it, clear the reference
match3_scene = null
print("Debug: Could not find match3_gameplay scene")
func _on_debug_toggled(enabled: bool):
print("Match3DebugMenu: Debug toggled to ", enabled)
visible = enabled
print("Match3DebugMenu: Visibility set to ", visible)
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")
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))
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))

View File

@@ -0,0 +1,83 @@
[gd_scene load_steps=2 format=3 uid="uid://b76oiwlifikl3"]
[ext_resource type="Script" path="res://scenes/game/gameplays/Match3DebugMenu.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 = "Match-3 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

View File

@@ -1,6 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://bnk1gqom3oi6q"]
[ext_resource type="Script" uid="uid://3bu5wgfarlgp" path="res://scenes/match3/tile.gd" id="1_tile_script"]
[ext_resource type="Script" path="res://scenes/game/gameplays/tile.gd" id="1_tile_script"]
[node name="Tile" type="Node2D"]
script = ExtResource("1_tile_script")

View File

@@ -0,0 +1,10 @@
extends Node2D
signal score_changed(points: int)
func _ready():
print("Clickomania gameplay loaded")
# Example: Add some score after a few seconds to test the system
await get_tree().create_timer(2.0).timeout
score_changed.emit(100)
print("Clickomania awarded 100 points")

View File

@@ -0,0 +1,21 @@
[gd_scene load_steps=2 format=3 uid="uid://cl7g8v0eh3mam"]
[ext_resource type="Script" path="res://scenes/game/gameplays/clickomania_gameplay.gd" id="1_script"]
[node name="Clickomania" type="Node2D"]
script = ExtResource("1_script")
[node name="Label" type="Label" parent="."]
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -100.0
offset_top = -12.0
offset_right = 100.0
offset_bottom = 12.0
grow_horizontal = 2
grow_vertical = 2
text = "Clickomania Gameplay (Demo)"
horizontal_alignment = 1

View File

@@ -1,8 +1,10 @@
extends Node2D
signal score_changed(points: int)
var GRID_SIZE := Vector2i(8, 8)
var TILE_TYPES := 5
const TILE_SCENE := preload("res://scenes/match3/tile.tscn")
const TILE_SCENE := preload("res://scenes/game/gameplays/tile.tscn")
var grid := []
var tile_size: float = 48.0
@@ -14,7 +16,7 @@ func _ready():
for i in range(TILE_TYPES):
gem_indices.append(i)
const TileScript = preload("res://scenes/match3/tile.gd")
const TileScript = preload("res://scenes/game/gameplays/tile.gd")
TileScript.set_active_gem_pool(gem_indices)
_calculate_grid_layout()
@@ -43,7 +45,7 @@ func _initialize_grid():
for i in range(TILE_TYPES):
gem_indices.append(i)
const TileScript = preload("res://scenes/match3/tile.gd")
const TileScript = preload("res://scenes/game/gameplays/tile.gd")
TileScript.set_active_gem_pool(gem_indices)
for y in range(GRID_SIZE.y):
@@ -56,7 +58,7 @@ func _initialize_grid():
# 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)
# print("Debug: Created tile at (", x, ",", y, ") with type ", new_type)
grid[y].append(tile)
func _has_match_at(pos: Vector2i) -> bool:
@@ -182,7 +184,7 @@ func regenerate_grid():
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":
if script_path == "res://scenes/game/gameplays/tile.gd":
children_to_remove.append(child)
# Remove all found tile children

View File

@@ -0,0 +1,13 @@
[gd_scene load_steps=3 format=3 uid="uid://b4kv7g7kllwgb"]
[ext_resource type="Script" path="res://scenes/game/gameplays/match3_gameplay.gd" id="1_mvfdp"]
[ext_resource type="PackedScene" path="res://scenes/game/gameplays/Match3DebugMenu.tscn" id="2_debug_menu"]
[node name="Match3" type="Node2D"]
script = ExtResource("1_mvfdp")
[node name="GridContainer" type="Node2D" parent="."]
[node name="UILayer" type="CanvasLayer" parent="."]
[node name="Match3DebugMenu" parent="UILayer" instance=ExtResource("2_debug_menu")]

View File

@@ -35,7 +35,7 @@ func _set_tile_type(value: int) -> void:
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)
# 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))

View File

@@ -1,7 +1,8 @@
[gd_scene load_steps=15 format=3 uid="uid://gbe1jarrwqsi"]
[gd_scene load_steps=16 format=3 uid="uid://gbe1jarrwqsi"]
[ext_resource type="Script" uid="uid://cxw2fjj5onja3" path="res://scenes/main/PressAnyKeyScreen.gd" id="1_0a4p2"]
[ext_resource type="Texture2D" uid="uid://bcr4bokw87m5n" path="res://assets/sprites/characters/skeleton/Skeleton Idle.png" id="2_rjjcb"]
[ext_resource type="PackedScene" path="res://scenes/ui/DebugToggle.tscn" id="3_debug"]
[sub_resource type="AtlasTexture" id="AtlasTexture_l6pue"]
atlas = ExtResource("2_rjjcb")
@@ -132,3 +133,6 @@ horizontal_alignment = 1
[node name="PressKeyLabel" type="Label" parent="PressKeyContainer"]
layout_mode = 2
text = "`press_ok_continue`"
[node name="DebugToggle" parent="." instance=ExtResource("3_debug")]
layout_mode = 1

View File

@@ -1,8 +0,0 @@
[gd_scene load_steps=2 format=3 uid="uid://b4kv7g7kllwgb"]
[ext_resource type="Script" uid="uid://bvyiwvpepqfdu" path="res://scenes/match3/match3.gd" id="1_mvfdp"]
[node name="Match3" type="Node2D"]
script = ExtResource("1_mvfdp")
[node name="GridContainer" type="Node2D" parent="."]

View File

@@ -17,8 +17,11 @@ func _exit_tree():
search_timer.queue_free()
func _ready():
visible = false
DebugManager.debug_toggled.connect(_on_debug_toggled)
# Initialize with current debug state
var current_debug_state = DebugManager.is_debug_enabled()
visible = current_debug_state
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)
@@ -62,7 +65,7 @@ func _find_match3_scene():
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")
match3_scene = _find_node_by_script(current_scene, "res://scenes/game/gameplays/match3_gameplay.gd")
# Fallback: search by common node names
if not match3_scene:

View File

@@ -1,10 +1,13 @@
extends Button
func _ready():
text = "Debug: OFF"
pressed.connect(_on_pressed)
DebugManager.debug_toggled.connect(_on_debug_toggled)
# Initialize with current debug state
var current_state = DebugManager.is_debug_enabled()
text = "Debug: " + ("ON" if current_state else "OFF")
func _on_pressed():
DebugManager.toggle_debug()

View File

@@ -1,6 +1,7 @@
[gd_scene load_steps=2 format=3 uid="uid://m8lf3eh3al5j"]
[gd_scene load_steps=3 format=3 uid="uid://m8lf3eh3al5j"]
[ext_resource type="Script" uid="uid://b2c35v0f6rymd" path="res://scenes/ui/MainMenu.gd" id="1_b00nv"]
[ext_resource type="PackedScene" path="res://scenes/ui/DebugToggle.tscn" id="2_debug"]
[node name="MainMenu" type="Control"]
layout_mode = 3
@@ -37,6 +38,9 @@ text = "Settings"
layout_mode = 2
text = "Exit"
[node name="DebugToggle" parent="." instance=ExtResource("2_debug")]
layout_mode = 1
[connection signal="pressed" from="MenuContainer/NewGameButton" to="." method="_on_new_game_button_pressed"]
[connection signal="pressed" from="MenuContainer/SettingsButton" to="." method="_on_settings_button_pressed"]
[connection signal="pressed" from="MenuContainer/ExitButton" to="." method="_on_exit_button_pressed"]

View File

@@ -1,6 +1,7 @@
[gd_scene load_steps=2 format=3 uid="uid://57obmcwyos2g"]
[gd_scene load_steps=3 format=3 uid="uid://57obmcwyos2g"]
[ext_resource type="Script" uid="uid://bv56qwni68qo" path="res://scenes/ui/SettingsMenu.gd" id="1_oqkcn"]
[ext_resource type="PackedScene" path="res://scenes/ui/DebugToggle.tscn" id="2_debug"]
[node name="SettingsMenu" type="Control" groups=["localizable"]]
layout_mode = 3
@@ -103,13 +104,18 @@ popup/item_4/id = 2
[node name="BackButtonContainer" type="Control" parent="."]
layout_mode = 1
anchors_preset = 0
offset_right = 40.0
offset_bottom = 40.0
offset_left = 10.0
offset_top = 10.0
offset_right = 55.0
offset_bottom = 41.0
[node name="BackButton" type="Button" parent="BackButtonContainer"]
layout_mode = 0
offset_right = 8.0
offset_bottom = 8.0
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
text = "back"
[node name="ResetSettingsContainer" type="Control" parent="."]
@@ -136,6 +142,9 @@ offset_bottom = 31.0
grow_horizontal = 2
text = "Reset settings to default"
[node name="DebugToggle" parent="." instance=ExtResource("2_debug")]
layout_mode = 1
[connection signal="value_changed" from="SettingsContainer/MasterVolumeContainer/MasterVolumeSlider" to="." method="_on_master_volume_changed"]
[connection signal="value_changed" from="SettingsContainer/MusicVolumeContainer/MusicVolumeSlider" to="." method="_on_music_volume_changed"]
[connection signal="value_changed" from="SettingsContainer/SFXVolumeContainer/SFXVolumeSlider" to="." method="_on_sfx_volume_changed"]