class_name WinnerPopup extends BasePopup ## Shows who won, with their character, where the other players placed, and how the game ## went: a graph of everyone's score after each song and a few facts about it. ## Size of the coloured square in front of each name in the legend. const LEGEND_SQUARE_SIZE: Vector2 = Vector2(14, 14) @onready var winner_panel: Panel = %WinnerPanel @onready var winner_picture: TextureRect = %WinnerPicture @onready var winner_label: Label = %WinnerLabel @onready var players_list: VBoxContainer = %PlayersList @onready var legend: HBoxContainer = %Legend @onready var score_graph: ScoreGraph = %ScoreGraph @onready var streak_label: Label = %StreakLabel @onready var standstill_label: Label = %StandstillLabel @onready var shared_label: Label = %SharedLabel func _ready() -> void: visible = false func show_winner(winner: PlayerObject) -> void: var winners: Array[PlayerObject] = [winner] show_winners(winners) ## Shows [param winners], who share the top score, with everyone else's placing below. ## Tied players get the same placing. With no players, it says the quiz is over. func show_winners(winners: Array[PlayerObject]) -> void: visible = true winner_label.text = winners_text(winners) _show_pictures(winners) for child: Node in players_list.get_children(): child.queue_free() var sorted_players: Array[PlayerObject] = Settings.player_array.duplicate() sorted_players.sort_custom( func(a: PlayerObject, b: PlayerObject) -> bool: return a.player_score > b.player_score ) for player: PlayerObject in sorted_players: if player in winners: continue var label: Label = Label.new() label.text = "%d. %s - %s" % [placing(player), player.player_name, points_text(player.player_score)] players_list.add_child(label) show_history(ScoreHistory.from_playlist(Settings.player_array)) ## The headline for [param winners], e.g. "Crono won with 5 points!!" or "Crono and ## Marle won with 5 points!!". static func winners_text(winners: Array[PlayerObject]) -> String: if winners.is_empty(): return "The quiz is over!" var names: PackedStringArray = [] for winner: PlayerObject in winners: names.append(winner.player_name) var joined: String = names[-1] if names.size() > 1: joined = ", ".join(names.slice(0, -1)) + " and " + names[-1] return "%s won with %s!!" % [joined, points_text(winners[0].player_score)] ## [param points] in words, e.g. "1 point" or "5 points". static func points_text(points: int) -> String: return "%d point%s" % [points, "" if points == 1 else "s"] ## Where [param player] placed: 1 plus how many players have more points, so tied ## players share a placing. static func placing(player: PlayerObject) -> int: var place: int = 1 for other: PlayerObject in Settings.player_array: if other.player_score > player.player_score: place += 1 return place # One picture per winner, next to each other func _show_pictures(winners: Array[PlayerObject]) -> void: var header: Node = winner_picture.get_parent() for extra: Node in header.get_children(): if extra != winner_picture && extra is TextureRect: header.remove_child(extra) extra.queue_free() winner_picture.visible = !winners.is_empty() for index: int in winners.size(): var picture: TextureRect = winner_picture if index > 0: picture = winner_picture.duplicate() header.add_child(picture) header.move_child(picture, winner_picture.get_index() + index) _show_character(picture, winners[index]) func _show_character(picture: TextureRect, player: PlayerObject) -> void: picture.texture = player.character # The "no character" placeholder is pixel art, which blurs when scaled up smoothly if player.character.resource_path == PlayerObject.NO_CHARACTER_PATH: picture.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST else: picture.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR ## Shows how the game went: the score graph, its legend and the summary boxes. func show_history(history: ScoreHistory) -> void: # A prepared quiz has no winning score to draw var winning_score: int = 0 if Settings.is_prepared_quiz() else Settings.winning_score score_graph.show_history(history, winning_score) streak_label.text = history.longest_streak_text() standstill_label.text = history.longest_standstill_text() shared_label.text = history.most_shared_text() for child: Node in legend.get_children(): legend.remove_child(child) child.queue_free() for index: int in history.players.size(): var player: PlayerObject = history.players[index] var entry: HBoxContainer = HBoxContainer.new() var square: ColorRect = ColorRect.new() square.custom_minimum_size = LEGEND_SQUARE_SIZE square.size_flags_vertical = Control.SIZE_SHRINK_CENTER square.color = score_graph.player_color(index) entry.add_child(square) var name_label: Label = Label.new() name_label.text = "%s %d" % [player.player_name, history.final_score(player.id)] entry.add_child(name_label) legend.add_child(entry)