Skip to main content
The ScoreManager is an autoload singleton that handles all persistent game data including high scores, coins, inventory, and equipped items. It uses Godot’s ConfigFile system to save and load player progress.

File Location

nyuron/scripts/ScoreManager.gd.gd

Save Path

All data is stored in:
const SAVE_PATH = "user://high_scores.cfg"
The user:// protocol points to:
  • Windows: %APPDATA%/Godot/app_userdata/[project_name]/
  • Linux: ~/.local/share/godot/app_userdata/[project_name]/
  • macOS: ~/Library/Application Support/Godot/app_userdata/[project_name]/
  • Android/iOS: App-specific sandboxed storage

High Score Management

save_high_score()

Saves a new high score if it exceeds the current record.
game_name
String
required
The minigame identifier. Valid values:
  • "memorice"
  • "turtle_runner"
  • "worm_catch"
  • "food_catch"
  • "counting_animals"
  • "nyuron_color"
new_score
int
required
The score to save
returns
bool
Returns true if a new record was set, false otherwise
Example from worm_catch minigame:
worm_bucket/scripts/main.gd
func _on_game_over() -> void:
    var score_manager = get_node("/root/ScoreManager")
    if score_manager:
        score_manager.save_high_score("worm_catch", score)
        var coins_earned = int(score * 2.5)
        if coins_earned > 0:
            score_manager.add_coins(coins_earned)

get_high_score()

Retrieves the high score for a specific game.
game_name
String
required
The minigame identifier
returns
int
The high score, or 0 if the game is not registered
var best_score = ScoreManager.get_high_score("turtle_runner")
print("Your best: ", best_score)

get_all_scores()

Returns a dictionary containing all high scores.
var all_scores = ScoreManager.get_all_scores()
print(all_scores)
# Output: {"memorice": 450, "turtle_runner": 2100, ...}

Coin Management

add_coins()

Adds or removes coins from the player’s balance.
amount
int
required
Amount to add (positive) or subtract (negative)
Usage in minigames:
food_catch/main.gd
# Award coins based on score
var coins_earned = int(score * 0.1)
if coins_earned > 0:
    score_manager.add_coins(coins_earned)
    print("Ganaste:", coins_earned, "monedas")
tienda/Script/store_menu.gd
# Deduct coins when purchasing
if ScoreManager.get_coins() >= item.price:
    ScoreManager.add_to_inventory(item.name)
    ScoreManager.add_coins(-item.price)  # Negative to subtract

get_coins()

Returns the current coin balance.
var coins = ScoreManager.get_coins()
coins_label.text = "Monedas: %s" % coins

Inventory System

add_to_inventory()

Adds an item to the player’s inventory (if not already owned).
item_name
String
required
The unique name of the item (e.g., "Corona", "Caparazón Azul")
ScoreManager.add_to_inventory("Gafas")

get_inventory()

Returns an array of owned item names.
var owned_items = ScoreManager.get_inventory()
if owned_items.has("Corona"):
    print("Player owns the crown!")

Equipped Items

equip_item()

Equips an item from the inventory.
category
String
required
Item category: "caparazon" or "accesorio"
item_name
String
required
Name of the item to equip. Special values:
  • "default" - Default shell
  • "none" - No accessory
Example from shop:
tienda/Script/store_menu.gd
func _on_equip_item(item: Dictionary):
    ScoreManager.equip_item(item.category, item.name)
    print("Equipado:", item.name)
This emits the skin_updated signal to notify listeners.

get_equipped_item()

Returns the name of the currently equipped item in a category.
category
String
required
"caparazon" or "accesorio"
Usage in main menu:
scripts/main_menu.gd
func update_menu_skin():
    var id_cuerpo = ScoreManager.get_equipped_item("caparazon")
    var id_accesorio = ScoreManager.get_equipped_item("accesorio")
    # ... load corresponding texture

is_equipped()

Checks if a specific item is currently equipped.
if ScoreManager.is_equipped("Caparazón Azul"):
    print("Blue shell is active")

Signals

skin_updated

Emitted when an item is equipped. Used to refresh character visuals.
ScoreManager.skin_updated.connect(_on_skin_changed)

func _on_skin_changed():
    update_character_appearance()

Data Persistence

File Structure

The save file uses INI-like sections:
[high_scores]
memorize=450
turtle_runner=2100
worm_catch=85
food_catch=1800
counting_animals=320
nyuron_color=14

[player_data]
coins=1250
equipped_items={"caparazon":"Caparazón Azul","accesorio":"Corona"}

[inventory]
items=["Caparazón Azul","Caparazón Verde","Corona","Gafas"]

save_to_file()

Automatically called by other methods to persist changes. Uses ConfigFile to write all data:
func save_to_file():
    var config = ConfigFile.new()
    config.load(SAVE_PATH)
    
    # Save high scores
    for game in high_scores.keys():
        config.set_value("high_scores", game, high_scores[game])
    
    # Save coins and equipped items
    config.set_value("player_data", "coins", coins)
    config.set_value("player_data", "equipped_items", equipped_items)
    
    # Save inventory
    config.set_value("inventory", "items", inventory)
    
    var error = config.save(SAVE_PATH)

load_high_scores()

Called automatically in _ready(). Loads all saved data or creates a new file if none exists.
func load_high_scores():
    var config = ConfigFile.new()
    var error = config.load(SAVE_PATH)
    
    if error != OK:
        print("Creando archivo de progreso...")
        save_to_file()
        return
    
    # Load all sections
    for game in high_scores.keys():
        high_scores[game] = config.get_value("high_scores", game, 0)
    
    coins = config.get_value("player_data", "coins", 0)
    inventory = config.get_value("inventory", "items", [])
    equipped_items = config.get_value("player_data", "equipped_items", equipped_items)

Default Values

var high_scores = {
    "memorice": 0,
    "turtle_runner": 0,
    "worm_catch": 0,
    "food_catch": 0,
    "counting_animals": 0,
    "nyuron_color": 0
}

var coins := 0
var inventory: Array = []

var equipped_items = {
    "caparazon": "default", 
    "accesorio": "none"
}

Common Patterns

End-of-Game Reward Flow

func _on_game_over():
    var final_score = int(score)
    var score_manager = get_node("/root/ScoreManager")
    
    if score_manager and final_score > 0:
        # Save high score
        score_manager.save_high_score("turtle_runner", final_score)
        
        # Award coins
        var coins_earned = int(final_score * 0.1)
        if coins_earned > 0:
            score_manager.add_coins(coins_earned)
            print("Ganaste:", coins_earned, "monedas")

Shop Purchase Flow

func _on_buy_item(item: Dictionary):
    if ScoreManager.get_coins() >= item.price:
        ScoreManager.add_to_inventory(item.name)
        ScoreManager.add_coins(-item.price)
        update_coins()
        print("Comprado:", item.name)
    else:
        print("No tienes monedas suficientes")

Build docs developers (and LLMs) love