9.8 KiB
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
- Separation of Concerns: Game logic is separate from visual presentation
- Event-Driven: State changes emit signals for loose coupling
- Data-Driven: Card definitions loaded from JSON, not hardcoded
- 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) -> CardDataget_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, orderedHAND- Hidden from opponentFIELD_FORWARDS- PublicFIELD_BACKUPS- Public, max 5DAMAGE- Public, orderedBREAK- 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):
ACTIVE- Activate dull charactersDRAW- Draw cardsMAIN_1- Play cards/abilitiesATTACK- CombatMAIN_2- Play cards/abilitiesEND- 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) -> boolcan_afford(cost: Dictionary) -> boolclear()
Combat (scripts/game/Combat.gd)
Handles attack phase logic.
States:
IDLEDECLARING_ATTACKERWAITING_BLOCKERRESOLVING_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