feat: Implement initial main game scene with player board UI, powerup inventory script, and associated assets.

This commit is contained in:
Yogi Wiguna
2026-03-24 11:54:27 +08:00
parent 82fdbf91d1
commit da9ba9361d
5 changed files with 143 additions and 192 deletions
Binary file not shown.
@@ -0,0 +1,36 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://c2tryhyhlyb1u"
path="res://.godot/imported/Supercell-Magic Regular.ttf-470d998e73788b4db06bc80514578b9e.fontdata"
[deps]
source_file="res://assets/fonts/Supercell-Magic Regular.ttf"
dest_files=["res://.godot/imported/Supercell-Magic Regular.ttf-470d998e73788b4db06bc80514578b9e.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
modulate_color_glyphs=false
hinting=1
subpixel_positioning=4
keep_rounding_remainders=true
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}
@@ -1,8 +1,8 @@
[gd_resource type="Theme" load_steps=14 format=3 uid="uid://0dhxl4ohyxh8"]
[gd_resource type="Theme" format=3 uid="uid://0dhxl4ohyxh8"]
[ext_resource type="Texture2D" uid="uid://bc4h3o4wjjhc7" path="res://assets/graphics/game_setting/checkbox_on.png" id="1_36vy5"]
[ext_resource type="FontFile" uid="uid://c5t0o1yflhrg6" path="res://fonts/Supercell-Magic Regular.ttf" id="1_ofq5d"]
[ext_resource type="FontFile" uid="uid://bkg2jgfslxukn" path="res://fonts/TektonDash2.ttf" id="2_1r1ma"]
[ext_resource type="FontFile" uid="uid://c2tryhyhlyb1u" path="res://assets/fonts/Supercell-Magic Regular.ttf" id="1_ofq5d"]
[ext_resource type="FontFile" uid="uid://dsqg0x5lnosou" path="res://assets/fonts/TektonDash2.ttf" id="2_1r1ma"]
[ext_resource type="Texture2D" uid="uid://cwayis8vcdrne" path="res://assets/graphics/game_setting/arrow_down.png" id="2_ucrj8"]
[ext_resource type="Texture2D" uid="uid://djtnarduvxu5i" path="res://assets/graphics/game_setting/checkbox_off.png" id="2_w7n4t"]
[ext_resource type="Texture2D" uid="uid://dpcrm3nenf3vy" path="res://assets/graphics/game_setting/check_tex.png" id="3_w7n4t"]
@@ -99,6 +99,7 @@ HSlider/styles/grabber_area_highlight = SubResource("StyleBoxFlat_dvgdt")
HSlider/styles/slider = SubResource("StyleBoxFlat_w4ep3")
Label/colors/font_outline_color = Color(0.46666667, 0.32941177, 0.24313726, 1)
Label/constants/outline_size = 13
Label/fonts/font = ExtResource("1_ofq5d")
OptionButton/font_sizes/font_size = 24
OptionButton/fonts/font = ExtResource("1_ofq5d")
OptionButton/icons/arrow = ExtResource("2_ucrj8")
+16 -54
View File
@@ -14,13 +14,11 @@
[ext_resource type="Texture2D" uid="uid://68x88jj25yxg" path="res://assets/textures/Adjacent.png" id="9_6gcb6"]
[ext_resource type="Texture2D" uid="uid://dasaeaytvhll0" path="res://assets/models/pboard/AdjacentRect.tres" id="9_aspsw"]
[ext_resource type="FontFile" uid="uid://xnjx058n4tsw" path="res://assets/fonts/Nougat-ExtraBlack.ttf" id="13_j8jky"]
[ext_resource type="Theme" uid="uid://0dhxl4ohyxh8" path="res://assets/graphics/game_setting/setting_theme.tres" id="18_pm3ni"]
[ext_resource type="Texture2D" uid="uid://ba80xnybpixw2" path="res://assets/graphics/touch_control/take_tile.png" id="25_qkpxi"]
[ext_resource type="Texture2D" uid="uid://bsgqrjx2ity4c" path="res://assets/graphics/touch_control/speed.png" id="26_2f3dj"]
[ext_resource type="Texture2D" uid="uid://pwxo4lb87yi" path="res://assets/graphics/touch_control/put_tile.png" id="26_5q0nq"]
[ext_resource type="Texture2D" uid="uid://umw3e8nfe3vr" path="res://assets/graphics/touch_control/attack_mode.png" id="27_dgi5k"]
[ext_resource type="Texture2D" uid="uid://cupfmb5m15kmf" path="res://assets/graphics/touch_control/wall.png" id="27_yq6so"]
[ext_resource type="Texture2D" uid="uid://dcwdbeqla0ooi" path="res://assets/graphics/touch_control/freeze_area.png" id="28_fv21b"]
[ext_resource type="Texture2D" uid="uid://b2vhatfmufn3d" path="res://assets/graphics/touch_control/ghost.png" id="33_5q0nq"]
[ext_resource type="Texture2D" uid="uid://biun2yvglxgij" path="res://assets/graphics/touch_control/grab_tekton.png" id="36_pibwh"]
[ext_resource type="Script" uid="uid://86ikh0wuqk7v" path="res://scripts/ui/powerup_inventory_ui.gd" id="powerup_ui_script"]
[ext_resource type="Script" uid="uid://b54tfa0n6kogi" path="res://scripts/managers/touch_controls.gd" id="touch_manager"]
@@ -1175,29 +1173,20 @@ anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -94.0
offset_top = -432.0
offset_right = -94.0
offset_bottom = -432.0
offset_left = -1252.0
offset_top = -140.00006
offset_right = -1252.0
offset_bottom = -140.00006
grow_horizontal = 0
grow_vertical = 0
rotation = -0.10297442
theme = ExtResource("18_pm3ni")
script = ExtResource("powerup_ui_script")
[node name="Container" type="VBoxContainer" parent="PowerUpInventoryUI" unique_id=1100906843]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -31.999996
offset_right = 41.00098
offset_bottom = 350.0
grow_horizontal = 2
grow_vertical = 2
rotation = 0.10297442
theme_override_constants/separation = 10
[node name="SpeedBtn" type="Button" parent="PowerUpInventoryUI/Container" unique_id=1549270030]
layout_mode = 2
[node name="PowerUpBtn" type="Button" parent="PowerUpInventoryUI" unique_id=1549270030]
layout_mode = 0
offset_right = 74.28728
offset_bottom = 78.35126
size_flags_horizontal = 3
size_flags_vertical = 3
focus_mode = 0
@@ -1206,36 +1195,6 @@ flat = true
icon_alignment = 1
expand_icon = true
[node name="WallBtn" type="Button" parent="PowerUpInventoryUI/Container" unique_id=863365575]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
focus_mode = 0
icon = ExtResource("27_yq6so")
flat = true
icon_alignment = 1
expand_icon = true
[node name="FreezeAreaBtn" type="Button" parent="PowerUpInventoryUI/Container" unique_id=1087493560]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
focus_mode = 0
icon = ExtResource("28_fv21b")
flat = true
icon_alignment = 1
expand_icon = true
[node name="GhostBtn" type="Button" parent="PowerUpInventoryUI/Container" unique_id=2041811828]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
focus_mode = 0
icon = ExtResource("33_5q0nq")
flat = true
icon_alignment = 1
expand_icon = true
[node name="LeaderboardPanel" type="PanelContainer" parent="." unique_id=364209533]
anchors_preset = 1
anchor_left = 1.0
@@ -1419,6 +1378,7 @@ offset_top = 318.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
theme = ExtResource("18_pm3ni")
[node name="VirtualJoystick" type="Control" parent="TouchControls/TouchControls" unique_id=1983608919]
visible = false
@@ -1440,6 +1400,7 @@ offset_top = 98.014656
offset_right = 129.85825
offset_bottom = 265.01465
rotation = -0.10297442
theme_override_constants/separation = 10
[node name="AttackModeBtn" type="Button" parent="TouchControls/TouchControls/PowerBarBtn" unique_id=1380511463]
layout_mode = 2
@@ -1462,11 +1423,12 @@ expand_icon = true
[node name="InteractionBtn" type="VBoxContainer" parent="TouchControls/TouchControls" unique_id=1738242916]
layout_mode = 0
offset_left = 134.0
offset_left = 131.0
offset_top = 86.999985
offset_right = 216.0
offset_right = 213.0
offset_bottom = 254.0
rotation = -0.10297442
theme_override_constants/separation = 10
[node name="GrabBtn" type="Button" parent="TouchControls/TouchControls/InteractionBtn" unique_id=914810452]
layout_mode = 2
+87 -135
View File
@@ -5,10 +5,17 @@ extends Control
# PowerUpInventoryUI - Displays stored powerups and handles selection
# UI References
var icon_containers: Dictionary = {} # { EffectEnum: Button }
# UI References
var power_up_button: Button
var effect_textures: Dictionary = {
0: preload("res://assets/graphics/touch_control/speed.png"),
1: preload("res://assets/graphics/touch_control/freeze_area.png"),
2: preload("res://assets/graphics/touch_control/wall.png"),
3: preload("res://assets/graphics/touch_control/ghost.png")
}
# Local State
var selected_effect: int = -1
var current_effect: int = -1
var special_manager_ref: Node = null # Reference to SpecialTilesManager
@onready var SettingsManager = get_node_or_null("/root/SettingsManager")
@@ -20,78 +27,44 @@ func _ready():
# Connect to SettingsManager to update labels
if SettingsManager and not SettingsManager.control_remapped.is_connected(_on_control_remapped):
SettingsManager.control_remapped.connect(_on_control_remapped)
# Map Effect Enum to UI Nodes (Assumes specific names in main.tscn)
# We try to get them immediately. If they are children, they should be accessible.
var container = get_node_or_null("Container")
if not container:
print("[PowerUpUI] ERROR: Container not found in ", get_path())
return
# Center buttons in the container instead of spreading them out
container.alignment = BoxContainer.ALIGNMENT_CENTER
# Mapping based on User Request
# 11: FASTER_SPEED (0) -> SpeedBtn
# 12: AREA_FREEZE (1) -> FreezeAreaBtn
# 13: BLOCK_FLOOR (2) -> WallBtn
# 14: INVISIBLE_MODE (3) -> GhostBtn
# We use 0, 1, 2, 3 to match SpecialTilesManager.SpecialEffect enum
var speed_btn = container.get_node_or_null("SpeedBtn")
var freeze_btn = container.get_node_or_null("FreezeAreaBtn")
var wall_btn = container.get_node_or_null("WallBtn")
var ghost_btn = container.get_node_or_null("GhostBtn")
var mode = LobbyManager.get_game_mode()
var is_restricted = GameMode.is_restricted(mode)
_setup_btn(0, speed_btn)
_setup_btn(1, freeze_btn)
_setup_btn(2, wall_btn)
_setup_btn(3, ghost_btn)
# New Single Button UI
power_up_button = get_node_or_null("PowerUpBtn")
if not power_up_button:
# Fallback to Container/PowerUpBtn just in case
power_up_button = get_node_or_null("Container/PowerUpBtn")
if not power_up_button:
print("[PowerUpUI] ERROR: PowerUpBtn not found")
return
# Remove mode-based restrictions on visibility for now, as ownership controls visibility
if wall_btn: wall_btn.visible = false
if freeze_btn: freeze_btn.visible = false
if speed_btn: speed_btn.visible = false
if ghost_btn: ghost_btn.visible = false
# Helper to setup the single button
_setup_powerup_btn(power_up_button)
_update_shortcuts_for_mode(is_restricted)
# Start hidden until player has a powerup
power_up_button.visible = false
print("[PowerUpUI] UI Initialization Complete. Mapped %d buttons." % icon_containers.size())
print("[PowerUpUI] UI Initialization Complete (Single Button Mode).")
func _on_control_remapped(_action: String, _key: int):
# Refresh all labels
_update_shortcuts_for_mode(LobbyManager.is_game_mode(GameMode.Mode.STOP_N_GO))
func _setup_btn(effect_id: int, btn: Button):
if not btn:
print("[PowerUpUI] Warning: Button for effect %d is null" % effect_id)
return
icon_containers[effect_id] = btn
func _setup_powerup_btn(btn: Button):
# Start DISABLED
btn.disabled = true
btn.modulate = Color(0.5, 0.5, 0.5, 0.5) # Grayed out
btn.modulate = Color(0.5, 0.5, 0.5, 0.5)
btn.focus_mode = Control.FOCUS_NONE
# Fix "Floating" issue: don't expand button to fill whole container height
# This keeps the buttons grouped tightly together
btn.size_flags_vertical = Control.SIZE_SHRINK_CENTER
btn.custom_minimum_size.y = 80 # Consistent height
# Add Cooldown Overlay
if not btn.has_node("CooldownOverlay"):
var overlay = ColorRect.new()
overlay.name = "CooldownOverlay"
overlay.mouse_filter = Control.MOUSE_FILTER_IGNORE
overlay.color = Color(0, 0, 0, 0.6) # Semi-transparent black
overlay.color = Color(0, 0, 0, 0.6)
overlay.set_anchors_preset(Control.PRESET_FULL_RECT)
overlay.anchor_top = 1.0 # Start empty at bottom
overlay.anchor_top = 1.0
overlay.grow_vertical = Control.GROW_DIRECTION_BEGIN
btn.add_child(overlay)
@@ -100,29 +73,30 @@ func _setup_btn(effect_id: int, btn: Button):
var sc_lbl = Label.new()
sc_lbl.name = "ShortcutLabel"
sc_lbl.mouse_filter = Control.MOUSE_FILTER_IGNORE
sc_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_LEFT
sc_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
sc_lbl.vertical_alignment = VERTICAL_ALIGNMENT_TOP
sc_lbl.set_anchors_preset(Control.PRESET_FULL_RECT)
sc_lbl.offset_left = 5
sc_lbl.offset_top = -4 # Lowered slightly from -12
sc_lbl.set_anchors_preset(Control.PRESET_TOP_RIGHT)
sc_lbl.offset_left = -60 # Width of label roughly
sc_lbl.offset_right = 6
sc_lbl.offset_top = -4
sc_lbl.offset_bottom = 12
sc_lbl.add_theme_font_size_override("font_size", 16)
sc_lbl.add_theme_color_override("font_outline_color", Color.BLACK)
sc_lbl.add_theme_constant_override("outline_size", 4)
sc_lbl.add_theme_color_override("font_color", Color(0.9, 0.9, 0.9))
btn.add_child(sc_lbl)
_update_btn_shortcut(effect_id, btn)
_update_btn_shortcut(btn)
# Connect click
if not btn.pressed.is_connected(_on_btn_pressed):
btn.pressed.connect(_on_btn_pressed.bind(effect_id))
btn.pressed.connect(_on_btn_pressed)
func _update_shortcuts_for_mode(is_restricted: bool):
for effect_id in icon_containers:
var btn = icon_containers[effect_id]
_update_btn_shortcut(effect_id, btn)
func _update_shortcuts_for_mode(_is_restricted: bool):
if power_up_button:
_update_btn_shortcut(power_up_button)
func _update_btn_shortcut(_effect_id: int, btn: Button):
func _update_btn_shortcut(btn: Button):
var sc_lbl = btn.get_node_or_null("ShortcutLabel")
if not sc_lbl: return
@@ -130,15 +104,16 @@ func _update_btn_shortcut(_effect_id: int, btn: Button):
sc_lbl.text = ""
return
# Show only Shortcut 1 as per single-slot request
# Show universal powerup shortcut
sc_lbl.text = " %s " % SettingsManager.get_control_text("use_powerup")
func _on_btn_pressed(effect_id: int):
print("[PowerUpUI] Clicked Button %d" % effect_id)
func _on_btn_pressed(effect_id: int = -1):
var target_effect = effect_id if effect_id != -1 else current_effect
if target_effect == -1: return
print("[PowerUpUI] Activating effect: %d" % target_effect)
if special_manager_ref:
special_manager_ref.activate_effect(effect_id)
else:
print("[PowerUpUI] ERROR: special_manager_ref is null during click")
special_manager_ref.activate_effect(target_effect)
func setup(player_node):
print("[PowerUpUI] Setup called for player: ", player_node.name)
@@ -160,28 +135,25 @@ func _on_player_child_entered(node: Node, player_node: Node):
player_node.child_entered_tree.disconnect(_on_player_child_entered)
func _on_global_cooldown_updated(time_left: float, max_time: float):
for effect in icon_containers:
var btn = icon_containers[effect]
var overlay = btn.get_node_or_null("CooldownOverlay")
if overlay:
if time_left > 0:
overlay.visible = true
overlay.anchor_top = 1.0 - (time_left / max_time)
btn.disabled = true
else:
overlay.visible = false
overlay.anchor_top = 1.0
if special_manager_ref and special_manager_ref.inventory.get(effect, false):
btn.disabled = false
if not power_up_button: return
var overlay = power_up_button.get_node_or_null("CooldownOverlay")
if overlay:
if time_left > 0:
overlay.visible = true
overlay.anchor_top = 1.0 - (time_left / max_time)
power_up_button.disabled = true
else:
overlay.visible = false
overlay.anchor_top = 1.0
if current_effect != -1:
power_up_button.disabled = false
func _connect_special_manager(special_manager):
special_manager_ref = special_manager
print("[PowerUpUI] Connected to SpecialTilesManager")
# Connect signals if not already connected
if not special_manager.is_connected("powerup_unlocked", _on_powerup_unlocked):
special_manager.connect("powerup_unlocked", _on_powerup_unlocked)
if not special_manager.is_connected("inventory_updated", _on_inventory_updated):
special_manager.connect("inventory_updated", _on_inventory_updated)
@@ -189,56 +161,36 @@ func _connect_special_manager(special_manager):
special_manager.connect("global_cooldown_updated", _on_global_cooldown_updated)
# Initial State Sync
if icon_containers.is_empty():
print("[PowerUpUI] Warning: Icon containers empty during setup. Attempting _ready logic now...")
var container = get_node_or_null("Container")
if container:
_setup_btn(0, container.get_node_or_null("SpeedBtn"))
_setup_btn(1, container.get_node_or_null("FreezeAreaBtn"))
_setup_btn(2, container.get_node_or_null("WallBtn"))
_setup_btn(3, container.get_node_or_null("GhostBtn"))
if not power_up_button:
_ready()
# Sync Inventory
_on_inventory_updated(special_manager.inventory)
# Sync Levels for owned items
for effect in special_manager.inventory:
if special_manager.inventory[effect]:
var lvl = special_manager.powerup_levels.get(effect, 1)
_on_powerup_unlocked(effect, lvl)
func _on_powerup_unlocked(effect: int, level: int):
# Enable button and set level
if icon_containers.has(effect):
var btn = icon_containers[effect]
print("[PowerUpUI] Enabling button for Effect %d (Node: %s)" % [effect, btn.name])
btn.disabled = false
btn.modulate = Color.WHITE # Restore color
btn.visible = true # Ensure visible
# Enforce 1-slot rule by hiding others
if special_manager_ref:
_on_inventory_updated(special_manager_ref.inventory)
else:
print("[PowerUpUI] ERROR: Unlocked Effect %d but no UI button found! Keys: %s" % [effect, icon_containers.keys()])
func _on_inventory_updated(inventory: Dictionary):
# Update UI icons (Only show ONE active slot as per user request)
print("[PowerUpUI] Inventory Updated Signal Received! Data: ", inventory)
for effect in icon_containers:
var has_item = inventory.get(effect, false)
var btn = icon_containers[effect]
if not power_up_button: return
# Update UI icon (Single slot logic)
var active_effect: int = -1
for effect in inventory:
if inventory[effect] == true:
active_effect = effect
break
current_effect = active_effect
if active_effect != -1:
power_up_button.visible = true
power_up_button.icon = effect_textures.get(active_effect)
# Single slot logic: Only the owned one is visible
btn.visible = has_item
if has_item:
# Check global cooldown before enabling
var is_cooling = false
if special_manager_ref and special_manager_ref.global_cooldown_timer > 0:
is_cooling = true
btn.disabled = is_cooling
btn.modulate = Color.WHITE
_update_btn_shortcut(effect, btn)
# Check global cooldown
var is_cooling = false
if special_manager_ref and special_manager_ref.global_cooldown_timer > 0:
is_cooling = true
power_up_button.disabled = is_cooling
power_up_button.modulate = Color.WHITE
_update_btn_shortcut(power_up_button)
else:
power_up_button.visible = false
power_up_button.disabled = true