feat: update leaderboard GUI, and HUD for gauge
This commit is contained in:
+212
-21
@@ -238,38 +238,37 @@ func setup_powerup_bar_ui(main_node):
|
||||
powerup_segments.clear()
|
||||
var hbox = powerup_bar.get_node_or_null("HBox")
|
||||
if hbox:
|
||||
for i in range(4):
|
||||
for i in range(3):
|
||||
var segment = hbox.get_node_or_null("Segment" + str(i))
|
||||
if segment:
|
||||
# Apply initial empty style
|
||||
var style = StyleBoxFlat.new()
|
||||
style.bg_color = Color(0.15, 0.15, 0.15, 1.0)
|
||||
style.border_color = Color(0.3, 0.7, 0.3, 1.0)
|
||||
style.set_border_width_all(2)
|
||||
style.corner_radius_top_left = 4 if i == 0 else 0
|
||||
style.corner_radius_bottom_left = 4 if i == 0 else 0
|
||||
style.corner_radius_top_right = 4 if i == 3 else 0
|
||||
style.corner_radius_bottom_right = 4 if i == 3 else 0
|
||||
var style = StyleBoxTexture.new()
|
||||
var tex_path = "res://assets/graphics/gui/gauge/Segment%d_empty.png" % i
|
||||
if ResourceLoader.exists(tex_path):
|
||||
style.texture = load(tex_path)
|
||||
segment.add_theme_stylebox_override("panel", style)
|
||||
powerup_segments.append(segment)
|
||||
|
||||
func update_powerup_bar(current_points: int, _max_points: int):
|
||||
"""Update battery segments based on current power-up points."""
|
||||
# 4 Segments total. Max Boost is 100. So each segment represents 25 points.
|
||||
# Was previously dividing by 4, causing it to fill at 16 points!
|
||||
var points_per_segment = _max_points / 4.0
|
||||
# 3 Segments total. Max Boost is 100. So each segment represents 33.33 points.
|
||||
var points_per_segment = _max_points / 3.0
|
||||
var bars_filled = int(current_points / points_per_segment)
|
||||
|
||||
for i in range(powerup_segments.size()):
|
||||
var segment = powerup_segments[i]
|
||||
var style = segment.get_theme_stylebox("panel").duplicate()
|
||||
var style = StyleBoxTexture.new()
|
||||
var tex_path = ""
|
||||
|
||||
if i < bars_filled:
|
||||
# Filled segment - bright green
|
||||
style.bg_color = Color(0.3, 0.9, 0.3, 1.0)
|
||||
# Filled segment
|
||||
tex_path = "res://assets/graphics/gui/gauge/Segment%d_filled.png" % i
|
||||
else:
|
||||
# Empty segment - dark
|
||||
style.bg_color = Color(0.2, 0.2, 0.2, 0.8)
|
||||
# Empty segment
|
||||
tex_path = "res://assets/graphics/gui/gauge/Segment%d_empty.png" % i
|
||||
|
||||
if ResourceLoader.exists(tex_path):
|
||||
style.texture = load(tex_path)
|
||||
|
||||
segment.add_theme_stylebox_override("panel", style)
|
||||
|
||||
@@ -277,8 +276,8 @@ var _previous_bars: int = 0
|
||||
|
||||
func _on_powerup_points_changed(current: int, max_points: int):
|
||||
if current % 10 == 0: print("[UIManager] Points changed: ", current)
|
||||
# Calculate based on max points (100) / 4 segments = 25 points per segment
|
||||
var new_bars = int(current / 25.0)
|
||||
# Calculate based on max points (100) / 3 segments = 33.33 points per segment
|
||||
var new_bars = int(current / (max_points / 3.0))
|
||||
|
||||
# Detect if a new bar was filled
|
||||
if new_bars > _previous_bars and powerup_bar:
|
||||
@@ -407,14 +406,21 @@ func initialize_leaderboard_with_players(players: Array):
|
||||
return
|
||||
|
||||
for i in range(4):
|
||||
var entry = vbox.get_node_or_null("Entry" + str(i + 1))
|
||||
if not entry:
|
||||
var entry_root = vbox.get_node_or_null("Entry" + str(i + 1))
|
||||
if not entry_root:
|
||||
continue
|
||||
|
||||
var entry = entry_root.get_node_or_null("HBox")
|
||||
if not entry:
|
||||
entry = entry_root
|
||||
|
||||
if i < players.size():
|
||||
var player = players[i]
|
||||
var name_label = entry.get_node_or_null("NameLabel")
|
||||
var score_label = entry.get_node_or_null("ScoreLabel")
|
||||
var portrait_rect = entry.get_node_or_null("PortraitRect")
|
||||
var ghost_icon = entry.get_node_or_null("GhostIcon")
|
||||
var mini_powerup_bar = entry.get_node_or_null("MiniPowerUpBar")
|
||||
|
||||
if name_label:
|
||||
# Use display_name if available, otherwise fallback to node name
|
||||
@@ -422,9 +428,194 @@ func initialize_leaderboard_with_players(players: Array):
|
||||
if player_display_name.is_empty():
|
||||
player_display_name = str(player.name) if player else "Player " + str(i + 1)
|
||||
name_label.text = player_display_name
|
||||
|
||||
if score_label:
|
||||
score_label.text = str(player.score) if player and player.get("score") else "0"
|
||||
|
||||
if portrait_rect:
|
||||
var character_name = "Pip" # Default fallback
|
||||
var peer_id = player.name.to_int() if player else 0
|
||||
|
||||
var lobby_manager = get_node_or_null("/root/LobbyManager")
|
||||
if lobby_manager:
|
||||
var lobby_players = lobby_manager.get_players()
|
||||
for p in lobby_players:
|
||||
if p.get("id") == peer_id:
|
||||
character_name = p.get("character", "Pip")
|
||||
break
|
||||
|
||||
var avatar_url = "res://assets/graphics/character_selection/sc_characters/sc_%s.png" % character_name.to_lower()
|
||||
if ResourceLoader.exists(avatar_url):
|
||||
portrait_rect.texture = load(avatar_url)
|
||||
|
||||
if ghost_icon:
|
||||
# Hidden by default. The live update loop will populate the correct texture.
|
||||
ghost_icon.modulate = Color(1, 1, 1, 0)
|
||||
|
||||
if mini_powerup_bar:
|
||||
# Initialize to empty segments
|
||||
for j in range(3):
|
||||
var seg = mini_powerup_bar.get_node_or_null("Segment" + str(j))
|
||||
if seg:
|
||||
var style = StyleBoxFlat.new()
|
||||
style.bg_color = Color(0.2, 0.2, 0.2, 0.8)
|
||||
style.border_color = Color(0.3, 0.7, 0.3, 1.0)
|
||||
style.set_border_width_all(2)
|
||||
seg.add_theme_stylebox_override("panel", style)
|
||||
|
||||
entry.visible = true
|
||||
else:
|
||||
entry.visible = false
|
||||
|
||||
func update_live_leaderboard(players: Array):
|
||||
"""Update the leaderboard during gameplay (scores, ghosts, powerups)."""
|
||||
if not leaderboard_panel: return
|
||||
var vbox = leaderboard_panel.get_node_or_null("MarginContainer/VBox")
|
||||
if not vbox: vbox = leaderboard_panel.get_node_or_null("VBox")
|
||||
if not vbox: return
|
||||
|
||||
var sorted_players = players.duplicate()
|
||||
sorted_players.sort_custom(func(a, b):
|
||||
var score_a = a.score if "score" in a else 0
|
||||
var score_b = b.score if "score" in b else 0
|
||||
return score_a > score_b
|
||||
)
|
||||
|
||||
var my_id = -1
|
||||
if leaderboard_panel.is_inside_tree() and leaderboard_panel.get_tree().get_multiplayer():
|
||||
my_id = leaderboard_panel.get_tree().get_multiplayer().get_unique_id()
|
||||
|
||||
var my_index = -1
|
||||
for i in range(sorted_players.size()):
|
||||
if sorted_players[i] and sorted_players[i].name == str(my_id):
|
||||
my_index = i
|
||||
break
|
||||
|
||||
var items_to_display = []
|
||||
for i in range(min(3, sorted_players.size())):
|
||||
items_to_display.append({"player": sorted_players[i], "rank": i + 1})
|
||||
|
||||
if sorted_players.size() >= 4:
|
||||
if my_index > 3:
|
||||
items_to_display.append({"player": sorted_players[my_index], "rank": my_index + 1})
|
||||
else:
|
||||
items_to_display.append({"player": sorted_players[3], "rank": 4})
|
||||
|
||||
for i in range(4):
|
||||
var entry_root = vbox.get_node_or_null("Entry" + str(i + 1))
|
||||
if not entry_root or i >= items_to_display.size():
|
||||
if entry_root: entry_root.visible = false
|
||||
continue
|
||||
|
||||
entry_root.visible = true
|
||||
var entry = entry_root.get_node_or_null("HBox")
|
||||
if not entry: entry = entry_root
|
||||
|
||||
var item = items_to_display[i]
|
||||
var player = item.player
|
||||
var rank = item.rank
|
||||
|
||||
var rank_label = entry.get_node_or_null("RankLabel")
|
||||
if rank_label:
|
||||
match rank:
|
||||
1: rank_label.text = "1st"
|
||||
2: rank_label.text = "2nd"
|
||||
3: rank_label.text = "3rd"
|
||||
_: rank_label.text = str(rank) + "th"
|
||||
|
||||
if player and player.name == str(my_id):
|
||||
entry_root.modulate = Color(1.0, 1.0, 0.0) # Yellow
|
||||
else:
|
||||
entry_root.modulate = Color.WHITE
|
||||
|
||||
var score_label = entry.get_node_or_null("ScoreLabel")
|
||||
var ghost_icon = entry.get_node_or_null("GhostIcon")
|
||||
var mini_powerup_bar = entry.get_node_or_null("MiniPowerUpBar")
|
||||
var portrait_rect = entry.get_node_or_null("PortraitRect")
|
||||
var name_label = entry.get_node_or_null("NameLabel")
|
||||
|
||||
if name_label:
|
||||
var default_name = player.name if player else "Unknown"
|
||||
name_label.text = player.get("display_name") if (player and player.get("display_name")) else default_name
|
||||
|
||||
if portrait_rect:
|
||||
var character_name = "Pip" # Default fallback
|
||||
if player and player.get("selected_character"):
|
||||
var sc = player.selected_character
|
||||
match sc:
|
||||
"Bob": character_name = "Pip"
|
||||
"Masbro": character_name = "Dabro"
|
||||
"Gatot": character_name = "Gatot"
|
||||
"Oldpop": character_name = "Copper"
|
||||
_: character_name = sc
|
||||
|
||||
var avatar_url = "res://assets/graphics/character_selection/sc_characters/sc_%s.png" % character_name.to_lower()
|
||||
if ResourceLoader.exists(avatar_url):
|
||||
portrait_rect.texture = load(avatar_url)
|
||||
|
||||
if score_label:
|
||||
score_label.text = str(player.score) if player and player.get("score") else "0"
|
||||
|
||||
if ghost_icon:
|
||||
var active_skill_id = -1
|
||||
var is_blinking = false
|
||||
|
||||
if player.get("special_tiles_manager"):
|
||||
var stm = player.special_tiles_manager
|
||||
# Check if any skill is CURRENTLY active (User requesting blinking state)
|
||||
if stm.get("active_buffs") and stm.active_buffs.has(0): # FASTER_SPEED
|
||||
active_skill_id = 0
|
||||
is_blinking = true
|
||||
elif stm.get("active_freeze_zones") and stm.active_freeze_zones.size() > 0:
|
||||
active_skill_id = 1 # AREA_FREEZE
|
||||
is_blinking = true
|
||||
elif stm.get("blocked_tiles") != null and stm.get("blocked_tiles").size() > 0:
|
||||
active_skill_id = 2 # BLOCK_FLOOR
|
||||
is_blinking = true
|
||||
elif typeof(stm.get("invisible_timer")) in [TYPE_FLOAT, TYPE_INT] and float(stm.get("invisible_timer")) > 0.0:
|
||||
active_skill_id = 3 # INVISIBLE_MODE
|
||||
is_blinking = true
|
||||
else:
|
||||
var inv = stm.get("inventory")
|
||||
if inv:
|
||||
for effect_idx in inv:
|
||||
if inv[effect_idx]:
|
||||
active_skill_id = effect_idx
|
||||
break
|
||||
|
||||
if active_skill_id != -1:
|
||||
var tex_path = "res://assets/textures/player_board_and_blue_print/tile_null.tres"
|
||||
match int(active_skill_id):
|
||||
0: tex_path = "res://assets/graphics/touch_control/speed.png"
|
||||
1: tex_path = "res://assets/graphics/touch_control/freeze_area.png"
|
||||
2: tex_path = "res://assets/graphics/touch_control/wall.png"
|
||||
3: tex_path = "res://assets/graphics/touch_control/ghost.png"
|
||||
|
||||
if ResourceLoader.exists(tex_path):
|
||||
ghost_icon.texture = load(tex_path)
|
||||
|
||||
if is_blinking:
|
||||
var alpha = 1.0 if (Time.get_ticks_msec() % 500) > 250 else 0.3
|
||||
ghost_icon.modulate = Color(1, 1, 1, alpha)
|
||||
else:
|
||||
ghost_icon.modulate = Color(1, 1, 1, 1)
|
||||
else:
|
||||
ghost_icon.modulate = Color(1, 1, 1, 0)
|
||||
|
||||
if mini_powerup_bar and player.get("powerup_manager"):
|
||||
var p_mgr = player.powerup_manager
|
||||
if p_mgr:
|
||||
var max_pts = p_mgr.get_max_points()
|
||||
var current_pts = p_mgr.get_points()
|
||||
var points_per_segment = max_pts / 3.0
|
||||
var bars_filled = int(current_pts / points_per_segment)
|
||||
|
||||
for j in range(3):
|
||||
var seg = mini_powerup_bar.get_node_or_null("Segment" + str(j))
|
||||
if seg:
|
||||
var style = seg.get_theme_stylebox("panel").duplicate()
|
||||
if j < bars_filled:
|
||||
style.bg_color = Color(0.3, 0.9, 0.3, 1.0)
|
||||
else:
|
||||
style.bg_color = Color(0.2, 0.2, 0.2, 0.8)
|
||||
seg.add_theme_stylebox_override("panel", style)
|
||||
|
||||
Reference in New Issue
Block a user