Browse/Meta & Systems/Money Earned / Spent
Meta & Systems

Money Earned / Spent

Structured approach to money earned / spent that balances depth with accessibility, creating satisfying player experiences.

High complexity
2 examples
3 patterns

Overview

Money Earned / Spent represents a design pattern that defines how players interact with this aspect of the game world. Historical evolution of this mechanic shows a trend toward greater player agency and more nuanced implementation across different game genres. The ongoing evolution of this mechanic reflects the broader maturation of game design as a discipline.

Game Examples

Action RPGs

Action RPGs use this mechanic where players allocate limited resources to collect all available items. Multiple valid strategies exist for different playstyles, resulting in creative expression.

Real-Time Strategy Games

Real-Time Strategy Games use this mechanic where players track multiple variables to unlock new abilities and options. Each decision has cascading consequences, resulting in satisfying progression.

Pros & Cons

Advantages

  • Enables strategic player expression
  • Creates meaningful mechanical decisions for players
  • Scales well from beginner to advanced play
  • Integrates naturally with economy systems

Disadvantages

  • May conflict with movement systems in the game
  • Increases CPU requirements significantly
  • Can create frustrating when RNG is unfavorable
  • Requires significant development time to implement well
  • Requires significant balance data to implement well

Implementation Patterns

Settings Controller

A modular approach to money earned / spent that separates concerns and enables easy testing.

class MoneyEarnedSpentHandler {
  gameState: Map<string, any> = new Map();

  save(slot: number) {
    const data = {
      timestamp: Date.now(),
      version: "2.1.0",
      state: Object.fromEntries(this.gameState)
    };
    localStorage.setItem(`save_${slot}`, JSON.stringify(data));
  }

  load(slot: number) {
    const raw = localStorage.getItem(`save_${slot}`);
    if (!raw) return false;
    const data = JSON.parse(raw);
    if (data.version !== "2.1.0") {
      return this.migrate(data);
    }
    this.gameState = new Map(Object.entries(data.state));
    return true;
  }
}

Difficulty Adjuster

A modular approach to money earned / spent that separates concerns and enables easy testing.

class MoneyEarnedSpentManager {
  saveData: Map<string, any> = new Map();

  save(slot: number) {
    const data = {
      timestamp: Date.now(),
      version: "2.1.0",
      state: Object.fromEntries(this.saveData)
    };
    localStorage.setItem(`save_${slot}`, JSON.stringify(data));
  }

  load(slot: number) {
    const raw = localStorage.getItem(`save_${slot}`);
    if (!raw) return false;
    const data = JSON.parse(raw);
    if (data.version !== "2.1.0") {
      return this.migrate(data);
    }
    this.saveData = new Map(Object.entries(data.state));
    return true;
  }
}

Config Parser

Data-driven implementation that loads money earned / spent configuration from external definitions.

class MoneyEarnedSpentController {
  saveData: Map<string, any> = new Map();

  save(slot: number) {
    const data = {
      timestamp: Date.now(),
      version: "1.5.3",
      state: Object.fromEntries(this.saveData)
    };
    localStorage.setItem(`save_${slot}`, JSON.stringify(data));
  }

  load(slot: number) {
    const raw = localStorage.getItem(`save_${slot}`);
    if (!raw) return false;
    const data = JSON.parse(raw);
    if (data.version !== "1.5.3") {
      return this.migrate(data);
    }
    this.saveData = new Map(Object.entries(data.state));
    return true;
  }
}