Files
FFCardGame/docs/DESIGN.md
2026-01-24 16:29:11 -05:00

9.8 KiB

FF-TCG Digital - Architecture Design Document

Overview

This document describes the software architecture of the FF-TCG Digital implementation.

Technology Stack

  • Game Engine: Godot 4.2+
  • Language: GDScript
  • Target Platform: Linux Desktop
  • Rendering: Forward+ renderer with 3D isometric view

Architecture Principles

  1. Separation of Concerns: Game logic is separate from visual presentation
  2. Event-Driven: State changes emit signals for loose coupling
  3. Data-Driven: Card definitions loaded from JSON, not hardcoded
  4. Testable: Core game logic can be tested independently of visuals

System Architecture

┌─────────────────────────────────────────────────────────────────┐
│                        Main Scene                                │
├─────────────────────────────────────────────────────────────────┤
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐          │
│  │  Table Scene │  │   UI Layer   │  │ Input Handler│          │
│  │   (3D View)  │  │  (2D Canvas) │  │              │          │
│  └──────────────┘  └──────────────┘  └──────────────┘          │
├─────────────────────────────────────────────────────────────────┤
│                     Autoload Singletons                          │
│  ┌──────────────┐  ┌──────────────┐                             │
│  │ GameManager  │  │ CardDatabase │                             │
│  └──────────────┘  └──────────────┘                             │
├─────────────────────────────────────────────────────────────────┤
│                      Game State Engine                           │
│  ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌──────────────┐ │
│  │ GameState  │ │  Player    │ │   Zone     │ │ TurnManager  │ │
│  └────────────┘ └────────────┘ └────────────┘ └──────────────┘ │
│  ┌────────────┐ ┌────────────┐ ┌────────────┐                  │
│  │  CPPool    │ │  Combat    │ │   Stack    │                  │
│  └────────────┘ └────────────┘ └────────────┘                  │
└─────────────────────────────────────────────────────────────────┘

Core Components

Autoload Singletons

GameManager (scripts/autoload/GameManager.gd)

Central coordinator for game flow. Responsibilities:

  • Initialize new games
  • Coordinate between game state and visuals
  • Handle high-level game events
  • Manage scene transitions

Signals:

  • game_started()
  • game_ended(winner: int)
  • turn_changed(player_index: int)
  • phase_changed(phase: TurnPhase)

CardDatabase (scripts/autoload/CardDatabase.gd)

Manages card definitions loaded from JSON. Responsibilities:

  • Load and parse data/cards.json
  • Provide card lookup by ID
  • Validate card data on load
  • Cache card textures

Methods:

  • get_card(id: String) -> CardData
  • get_cards_by_element(element: Element) -> Array[CardData]
  • get_cards_by_type(type: CardType) -> Array[CardData]

Game State Classes

GameState (scripts/game/GameState.gd)

Master game state container. Holds:

  • Two Player instances
  • Shared Stack for ability resolution
  • Current turn/phase information
  • Game rules enforcement

Player (scripts/game/Player.gd)

Individual player state. Contains:

  • Hand (Zone)
  • Deck (Zone)
  • Field - Forwards area (Zone)
  • Field - Backups area (Zone)
  • Damage Zone (Zone)
  • Break Zone (Zone)
  • Current CP pool

Zone (scripts/game/Zone.gd)

Base class for card containers. Types:

  • DECK - Hidden, ordered
  • HAND - Hidden from opponent
  • FIELD_FORWARDS - Public
  • FIELD_BACKUPS - Public, max 5
  • DAMAGE - Public, ordered
  • BREAK - Public discard

Methods:

  • add_card(card: CardInstance)
  • remove_card(card: CardInstance)
  • get_cards() -> Array[CardInstance]
  • shuffle()

TurnManager (scripts/game/TurnManager.gd)

Handles turn structure and phase progression.

Phases (enum TurnPhase):

  1. ACTIVE - Activate dull characters
  2. DRAW - Draw cards
  3. MAIN_1 - Play cards/abilities
  4. ATTACK - Combat
  5. MAIN_2 - Play cards/abilities
  6. END - Cleanup

CPPool (scripts/game/CPPool.gd)

Tracks generated Crystal Points by element.

Properties:

  • cp: Dictionary - Element -> count mapping

Methods:

  • add_cp(element: Element, amount: int)
  • spend_cp(cost: Dictionary) -> bool
  • can_afford(cost: Dictionary) -> bool
  • clear()

Combat (scripts/game/Combat.gd)

Handles attack phase logic.

States:

  • IDLE
  • DECLARING_ATTACKER
  • WAITING_BLOCKER
  • RESOLVING_DAMAGE

Visual Components

TableCamera (scripts/visual/TableCamera.gd)

Isometric camera setup:

  • 45° rotation on Y axis
  • ~35° tilt down on X axis
  • Orthographic or perspective projection
  • Fixed position showing full board

CardVisual (scripts/visual/CardVisual.gd)

3D card representation:

  • MeshInstance3D with PlaneMesh
  • Dynamic texture from card image
  • States: normal, highlighted, selected, dull
  • Animation support for movement

ZoneVisual (scripts/visual/ZoneVisual.gd)

Visual representation of card zones:

  • Manages card positioning
  • Handles card enter/exit animations
  • Supports stacking and spreading

Data Flow

Playing a Card

1. Player clicks card in hand
   │
2. InputHandler detects selection
   │
3. GameManager.request_play_card(card)
   │
4. GameState.validate_play(card)
   ├── Check phase (must be Main Phase)
   ├── Check CP requirements
   └── Check field limits
   │
5. If valid: GameState.execute_play(card)
   ├── CPPool.spend_cp(card.cost)
   ├── Hand.remove_card(card)
   └── Field.add_card(card)
   │
6. GameState emits card_played signal
   │
7. Visual layer animates card movement

Combat Flow

1. Attack Phase begins
   │
2. Active player selects attacker
   ├── Must be active Forward
   └── Must be able to attack
   │
3. Attacker is dulled
   │
4. Defending player may select blocker
   ├── Must be active Forward
   └── Optional
   │
5. Damage resolution
   ├── If blocked: Exchange damage equal to Power
   └── If unblocked: Deal 1 damage to player
   │
6. Check for broken Forwards
   │
7. Return to step 2 or end Attack Phase

File Organization

scripts/
├── autoload/
│   ├── GameManager.gd      # Game flow coordinator
│   └── CardDatabase.gd     # Card data management
├── game/
│   ├── GameState.gd        # Master game state
│   ├── Player.gd           # Player state
│   ├── Zone.gd             # Zone base class
│   ├── CardInstance.gd     # Runtime card instance
│   ├── TurnManager.gd      # Turn/phase handling
│   ├── CPPool.gd           # CP tracking
│   ├── Combat.gd           # Combat resolution
│   └── Enums.gd            # Shared enumerations
├── visual/
│   ├── TableCamera.gd      # Isometric camera
│   ├── CardVisual.gd       # 3D card rendering
│   ├── ZoneVisual.gd       # Zone rendering
│   └── TableSetup.gd       # Table scene setup
└── ui/
    ├── GameUI.gd           # Main UI controller
    ├── CardDetailPanel.gd  # Card info popup
    ├── CPDisplay.gd        # CP pool display
    └── TurnIndicator.gd    # Turn/phase display

Signals Reference

GameManager Signals

Signal Parameters Description
game_started none New game initialized
game_ended winner: int Game over
turn_changed player: int Active player changed
phase_changed phase: TurnPhase Phase advanced

GameState Signals

Signal Parameters Description
card_played card, player Card deployed to field
card_moved card, from, to Card changed zones
damage_dealt player, amount Player took damage
forward_broken card Forward destroyed

Player Signals

Signal Parameters Description
hand_changed none Hand contents updated
cp_changed pool CP pool updated
field_changed none Field contents updated

Testing Strategy

Unit Tests

  • Card data validation
  • CP calculation
  • Combat damage resolution
  • Zone operations

Integration Tests

  • Full turn cycle
  • Complete game to win condition
  • Edge cases (deck empty, backup limit)

Manual Testing

  • Visual correctness
  • Input responsiveness
  • Animation smoothness