- Complete technical stack (bgfx, SDL2, YAML/JSON/TOML) - AI-friendly architecture (data-driven entities, UI, missions) - Rendering 2D implementation details (sprite batching, camera) - 16-week development plan (5 phases) - ECS architecture + component examples - LLM workflow capabilities (create/modify without C++ code) - Questions ouvertes + risk mitigation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
18 KiB
GroveEngine - Supplementary Design Document
Date créé : 24 novembre 2025 Auteur : Alexis (avec Claude Code) Status : Architecture Planning
CONTEXTE
GroveEngine est un moteur de jeu multi-projets conçu pour être :
- Data-driven : Config/text-based pour tout ce qui est modifiable
- AI-friendly : LLM peut créer/modifier assets sans toucher au code C++
- Multi-backend rendering : Support Vulkan/DX12/Metal/OpenGL via bgfx
- Solide & réutilisable : Foundation pour plusieurs projets
État actuel :
- ✅ Coeur engine done (mode debug)
- ❌ Pas de rendering
- ❌ Pas de framework 2D/UI
PROJETS BASÉS SUR GROVEENGINE
- Pokrovsk: Iron Line (survival management, train builder)
- AISSIA (concepts via SecondVoice/YT-DL)
- Troisième projet : À définir
Objectif : Un seul moteur, plusieurs jeux, maintenance centralisée.
STACK TECHNIQUE
Rendering
-
bgfx : Abstraction multi-backend (Vulkan/DX12/Metal/OpenGL)
- Multi-platform par design
- Performant pour 2D (batching, sprites)
- Mature (utilisé par Defold engine)
- Dev : Branimir Karadzic (ex-Frostbite EA)
-
SDL2 : Windowing + input
- Cross-platform
- Léger, bien supporté
-
stb_image : Texture loading
- Single-header, simple
Serialization/Config
-
yaml-cpp : YAML parsing
- Entities definitions
- Missions, events, dialogues
-
nlohmann/json : JSON parsing
- UI layouts
- Save files
- Asset manifests (alternative)
-
TOML++ : Config files
- Settings, constants
- Game balance values
UI
-
ImGui : Debug/tools UI (dev only)
- Immediate mode
- Parfait pour tools
-
Custom UI system (bgfx-based) : In-game UI
- JSON-driven layouts
- Rendering via bgfx
- Themeable
Scripting (optionnel)
- Lua : Si besoin de scripting pour game logic
- Alternative : Config-only (YAML events + state machines)
- Plus simple
- Assez pour beaucoup de cas
ARCHITECTURE AI-FRIENDLY
Principe : LLM peut créer/modifier game content sans toucher au code C++.
1. Entity System (Data-Driven)
Structure :
entities/
├── wagons/
│ ├── wagon_basic.yaml
│ ├── wagon_armored.yaml
│ └── wagon_workshop.yaml
├── drones/
│ ├── mavic_reco.yaml
│ └── fpv_strike.yaml
└── humans/
└── commandant_template.yaml
Exemple : entities/wagons/wagon_basic.yaml
entity: wagon_basic
components:
- type: visual
sprite: wagon_base.png
size: [20, 6] # Grille interne
- type: balance
weight: 5.0
center_of_mass: [10, 3]
dampeners: 0 # Upgrade level
- type: slots
grid: [20, 6]
layers: [high, low]
specialization: null # production, logistic, habitation, military
- type: health
hp_max: 100
armor: 10
LLM peut : Créer nouveaux wagons, tweaker stats, ajouter composants.
2. UI Layouts (Declarative JSON)
Structure :
ui/
├── screens/
│ ├── train_builder.json
│ ├── mission_briefing.json
│ └── campaign_map.json
└── widgets/
├── balance_gauge.json
└── resource_panel.json
Exemple : ui/screens/train_builder.json
{
"screen": "train_builder",
"elements": [
{
"type": "panel",
"id": "wagon_view",
"rect": [0, 0, 800, 600],
"background": "#2a2a2a",
"children": [
{
"type": "sprite",
"id": "wagon_display",
"anchor": "center"
}
]
},
{
"type": "gauge",
"id": "balance_lateral",
"rect": [820, 20, 160, 40],
"label": "Balance G/D",
"min": -10,
"max": 10,
"value_binding": "wagon.balance.lateral",
"color_good": "#00ff00",
"color_warning": "#ffaa00",
"color_bad": "#ff0000"
},
{
"type": "text",
"id": "wagon_name",
"rect": [820, 80, 160, 30],
"text_binding": "wagon.name",
"font": "main_ui",
"size": 18,
"color": "#ffffff"
}
]
}
LLM peut : Créer UI screens, repositionner éléments, modifier styles, créer layouts.
3. Game Logic (Config-Driven Events)
Structure :
content/
├── missions/
│ ├── 2022_early/
│ │ ├── scavenge_kyiv.yaml
│ │ └── rescue_civilians.yaml
│ └── 2025_late/
│ └── drone_intercept.yaml
├── events/
│ ├── random_events.yaml
│ └── story_events.yaml
└── dialogues/
└── commandants/
├── sergei.yaml
└── oksana.yaml
Exemple : missions/2022_early/scavenge_kyiv.yaml
mission:
id: scavenge_kyiv_outskirts
name: "Colonne russe détruite - Périphérie Kyiv"
year: 2022
period: early
difficulty: easy
briefing:
text: |
Colonne blindée russe détruite à 2km au nord.
Reconnaissance indique 8-10 véhicules abandonnés.
Opposition minimale attendue.
intel:
- "Matériel récent, peu endommagé"
- "Zone relativement sécurisée"
- "Temps limité avant arrivée autres scavengers"
rewards:
metal: [50, 100]
electronics: [20, 40]
components_military: [5, 15]
fame: 10
risks:
- type: ambush
probability: 0.1
- type: mines
probability: 0.15
events:
- trigger: mission_start
text: "Votre équipe approche la colonne détruite..."
choices:
- id: approach_cautious
text: "Approche prudente (sweep mines)"
time_cost: 2h
risk_modifier: -0.5
- id: rush
text: "Rush rapide (grab & go)"
time_cost: 30min
risk_modifier: +0.8
reward_modifier: 1.2
- trigger: loot_phase
condition: "approach_cautious"
text: "Temps de fouiller méthodiquement..."
outcomes:
- probability: 0.7
result: success
rewards_modifier: 1.0
- probability: 0.3
result: partial
rewards_modifier: 0.6
LLM peut : Créer missions, events, dialogues, choix, outcomes.
4. Asset Pipeline (Text Metadata)
Structure :
assets/
├── sprites/
│ ├── wagons.manifest
│ ├── drones.manifest
│ └── ui.manifest
├── textures/
│ └── (PNG files)
└── fonts/
└── fonts.manifest
Exemple : assets/sprites/wagons.manifest (TOML)
[wagon_base]
file = "textures/wagon_base.png"
size = [400, 120]
pivot = [200, 60]
tags = ["wagon", "basic"]
[wagon_armored]
file = "textures/wagon_armored.png"
size = [400, 120]
pivot = [200, 60]
weight_modifier = 1.5
tags = ["wagon", "armored", "heavy"]
[wagon_workshop]
file = "textures/wagon_workshop.png"
size = [400, 140] # Plus haut
pivot = [200, 70]
specialization = "production"
tags = ["wagon", "specialized"]
LLM peut : Définir assets, metadata, tags, modifiers.
ARCHITECTURE ENGINE
Core Systems
1. Entity Component System (ECS)
class Entity {
EntityID id;
std::vector<Component*> components;
};
class Component {
virtual void Update(float dt) = 0;
virtual void Serialize(YAML::Node& node) = 0;
virtual void Deserialize(const YAML::Node& node) = 0;
};
// Exemples components
class VisualComponent : public Component { ... }
class BalanceComponent : public Component { ... }
class SlotsComponent : public Component { ... }
2. Asset Manager
class AssetManager {
// Textures
std::map<std::string, bgfx::TextureHandle> textures;
// Manifests (metadata)
std::map<std::string, AssetMetadata> metadata;
// Fonts
std::map<std::string, FontHandle> fonts;
void LoadManifest(const std::string& path);
bgfx::TextureHandle GetTexture(const std::string& id);
};
3. Config System
class ConfigManager {
YAML::Node LoadYAML(const std::string& path);
nlohmann::json LoadJSON(const std::string& path);
Entity* CreateEntityFromYAML(const std::string& entity_id);
UIScreen* CreateUIFromJSON(const std::string& screen_id);
};
4. Rendering 2D (bgfx-based)
class Renderer2D {
bgfx::ProgramHandle sprite_shader;
// Sprite batching pour performance
struct SpriteBatch {
std::vector<SpriteVertex> vertices;
bgfx::TextureHandle texture;
};
void DrawSprite(const Sprite& sprite);
void DrawRect(const Rect& rect, Color color);
void DrawText(const std::string& text, Font font, Vec2 pos);
void Flush(); // Submit batched draws
};
5. UI System (JSON-driven)
class UIManager {
std::map<std::string, UIScreen*> screens;
UIScreen* LoadScreen(const std::string& screen_json);
void Update(float dt);
void Render(Renderer2D& renderer);
// Data binding
void BindValue(const std::string& path, float* value);
void BindText(const std::string& path, std::string* text);
};
class UIElement {
std::string id;
Rect rect;
virtual void Render(Renderer2D& renderer) = 0;
virtual void Update(float dt) = 0;
};
// Concrete elements
class UIPanel : public UIElement { ... }
class UIGauge : public UIElement { ... }
class UIText : public UIElement { ... }
class UISprite : public UIElement { ... }
RENDERING 2D AVEC BGFX
Concept de base
bgfx ne fait PAS de 2D directement → Tu construis la couche 2D par-dessus.
Primitive : Quad (pour sprites)
struct SpriteVertex {
float x, y, z; // Position
float u, v; // UV coords (texture)
uint32_t color; // Tint color (ABGR)
};
// Vertex layout bgfx
bgfx::VertexLayout sprite_layout;
sprite_layout.begin()
.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
.end();
Sprite Rendering
void Renderer2D::DrawSprite(const Sprite& sprite) {
// 1. Batch sprite (grouper par texture)
GetOrCreateBatch(sprite.texture).AddQuad(sprite);
}
void Renderer2D::Flush() {
// 2. Pour chaque batch, submit draw call
for (auto& batch : batches) {
bgfx::setTexture(0, sampler, batch.texture);
bgfx::setVertexBuffer(0, batch.vertex_buffer);
bgfx::setIndexBuffer(batch.index_buffer);
bgfx::setState(BGFX_STATE_DEFAULT);
bgfx::submit(view_id, sprite_shader);
}
batches.clear();
}
Camera 2D (Orthographic)
class Camera2D {
Vec2 position;
float zoom;
Mat4 GetViewMatrix() const {
return Mat4::Translation(-position.x, -position.y, 0);
}
Mat4 GetProjectionMatrix(int width, int height) const {
float halfW = (width / zoom) * 0.5f;
float halfH = (height / zoom) * 0.5f;
return Mat4::Ortho(-halfW, halfW, -halfH, halfH, -1, 1);
}
};
// Usage
bgfx::setViewTransform(view_id,
camera.GetViewMatrix().data,
camera.GetProjectionMatrix(screenW, screenH).data
);
PLAN DE DÉVELOPPEMENT
Phase 1 : Core Engine (3-4 semaines)
Semaine 1-2 : Setup bgfx + SDL2
- Intégrer bgfx, bx, bimg dans projet (git submodules)
- Build bgfx pour platform cible
- Window SDL2 + init bgfx
- Clear screen avec couleur
- Input basique (keyboard, mouse)
Semaine 3 : Rendering 2D basique
- Vertex layout sprites
- Shader simple (texture + color tint)
- Afficher 1 sprite (quad texturé)
- Camera 2D orthographique
Semaine 4 : Asset Pipeline
- Texture loading (stb_image)
- AssetManager basique
- Manifest TOML (assets metadata)
- Load sprite from manifest
Phase 2 : Framework 2D (2-3 semaines)
Semaine 5 : Sprite System
- Sprite batching (group by texture)
- DrawSprite API
- DrawRect (colored quads)
- Transform system (position, rotation, scale)
Semaine 6 : UI Primitives
- Text rendering (stb_truetype ou FreeType)
- Font loading via manifest
- DrawText API
- UI elements basiques (Panel, Text, Sprite)
Semaine 7 : Input & Interaction
- Mouse picking (screen → world coords)
- Drag & drop basique
- Button clicks
- Input manager
Phase 3 : Entity System (2-3 semaines)
Semaine 8 : ECS Core
- Entity class
- Component base class
- Entity manager (create, destroy, query)
- YAML serialization/deserialization
Semaine 9 : Components Library
- VisualComponent (sprite rendering)
- TransformComponent (position, rotation)
- BalanceComponent (pour Pokrovsk wagons)
- SlotsComponent (grille placement)
Semaine 10 : Config Integration
- Load entity from YAML
- Entity templates system
- Component factory (deserialize components)
Phase 4 : UI System (2-3 semaines)
Semaine 11 : UI Framework
- UIElement base class
- UIManager (screen stack)
- Layout system (anchors, rects)
- JSON UI loading
Semaine 12 : UI Widgets
- UIPanel
- UIText (with data binding)
- UIGauge (progress bar, balance gauge)
- UIButton
Semaine 13 : Advanced UI
- Data binding system (link UI ↔ game data)
- Events (onClick, onHover)
- Theming (colors, fonts from config)
Phase 5 : Validation Pokrovsk (2-3 semaines)
Semaine 14 : Wagon Entity
- Wagon YAML definition
- Instantiate wagon from config
- Render wagon sprite (double slice)
- Display balance gauges (UI)
Semaine 15 : Train Builder UI
- Train builder screen (JSON)
- Grid overlay (slots)
- Drag & drop elements (atelier, stockage, dortoir)
- Real-time balance calculation
Semaine 16 : Polish & Validation
- Balance visualization (wagon tilts if unbalanced)
- Element placement constraints
- Save/load train configuration
- Prototype jouable = validation complète
TOTAL : ~10-16 semaines pour moteur complet + prototype Pokrovsk
AVANTAGES POUR LLM
Ce que LLM peut créer/modifier sans code C++ :
Entities
- ✅ Wagons (YAML) : stats, composants, visuel
- ✅ Drones (YAML) : types, capacités
- ✅ Commandants (YAML) : skills, personnalité
- ✅ Missions (YAML) : events, choix, rewards
UI
- ✅ Screens (JSON) : layouts, elements
- ✅ Widgets (JSON) : gauges, panels, text
- ✅ Themes (JSON) : colors, fonts, styles
Content
- ✅ Dialogues (YAML)
- ✅ Events (YAML)
- ✅ Story beats (YAML)
- ✅ Balance values (TOML)
Assets
- ✅ Manifests (TOML) : sprites metadata
- ✅ Tags, categories, filters
- ✅ Asset relationships
Workflow LLM
Exemple : "Créer un nouveau wagon blindé lourd"
- LLM crée
entities/wagons/wagon_heavy_armored.yaml - LLM met à jour
assets/sprites/wagons.manifest(nouveau sprite) - LLM peut tester en modifiant une mission pour donner ce wagon
- Aucun code C++ touché
QUESTIONS OUVERTES
Architecture
-
Scripting Lua ou config-only ?
- Lua = plus flexible pour game logic
- Config = plus simple, assez pour events/missions
- Décision : À trancher selon complexité game logic
-
Save system format ?
- JSON (human-readable, LLM-friendly)
- Binaire (compact, rapide)
- Recommandation : JSON pour dev, option binaire pour release
-
Networking futur ?
- Pokrovsk = solo only
- Autres projets ?
- Impact : Architecture ECS doit supporter network sync ou pas
Performance
-
Sprite batching strategy ?
- Batch par texture (standard)
- Batch par layer (z-order)
- Décision : Tester performance avec prototype
-
Entity pooling ?
- Object pooling pour éviter alloc/dealloc
- Critical pour drones (100+ entities)
- Recommandation : Oui, implement dès Phase 3
Tooling
-
Level editor ?
- ImGui-based editor in-engine
- Externe (web-based ?)
- Recommandation : ImGui in-engine = plus rapide
-
Asset hot-reload ?
- Reload YAML/JSON/textures sans restart
- Crucial pour iteration rapide
- Recommandation : Oui, implement Phase 2-3
DÉPENDANCES EXTERNES
Obligatoires
- bgfx : Rendering (https://github.com/bkaradzic/bgfx)
- bx : Base library pour bgfx (https://github.com/bkaradzic/bx)
- bimg : Image loading pour bgfx (https://github.com/bkaradzic/bimg)
- SDL2 : Windowing + input (https://www.libsdl.org/)
- yaml-cpp : YAML parsing (https://github.com/jbeder/yaml-cpp)
- nlohmann/json : JSON parsing (https://github.com/nlohmann/json)
- stb_image : Image loading (https://github.com/nothings/stb)
Optionnelles
- TOML++ : TOML parsing (https://github.com/marzer/tomlplusplus)
- ImGui : Debug UI (https://github.com/ocornut/imgui)
- Lua : Scripting (https://www.lua.org/)
- stb_truetype : Font rendering (https://github.com/nothings/stb)
- FreeType : Alternative font rendering (https://freetype.org/)
RISQUES & MITIGATION
| Risque | Impact | Probabilité | Mitigation |
|---|---|---|---|
| bgfx trop complexe | HAUT | MOYEN | Exemples officiels, communauté active |
| Scope creep framework | HAUT | HAUT | Lock features après Phase 4, focus prototype |
| Performance 2D insuffisante | MOYEN | FAIBLE | Batching + profiling dès Phase 2 |
| Config system trop rigide | MOYEN | MOYEN | Itérer avec prototype Pokrovsk |
| LLM-generated content bugs | MOYEN | MOYEN | Validation schema (JSON schema, YAML schema) |
| Timeline trop optimiste | HAUT | MOYEN | Buffers 20% par phase |
RÉFÉRENCES
bgfx
- Repo officiel : https://github.com/bkaradzic/bgfx
- Documentation : https://bkaradzic.github.io/bgfx/
- Exemples : https://github.com/bkaradzic/bgfx/tree/master/examples
Architecture ECS
- "Overwatch Gameplay Architecture" (GDC Talk)
- "Data-Oriented Design" (Richard Fabian)
2D Rendering bgfx
- bgfx example-26 (vectordisplay)
- NanoVG-bgfx (https://github.com/memononen/nanovg)
NEXT STEPS
- Setup projet : Créer repo GroveEngine, structure folders
- Intégrer bgfx : Submodules + build
- Hello Triangle : Première fenêtre + rendering
- Suivre plan Phase 1 : 4 semaines pour core engine
Document Version : 1.0
Status : Architecture Design
Owner : Alexis
Related : Projects/CONCEPT/pokrovsk_iron_line_v2.md