Skip to content

Latest commit

 

History

History
266 lines (190 loc) · 9.35 KB

File metadata and controls

266 lines (190 loc) · 9.35 KB

Vue d'ensemble du projet - Top-down RPG en ECS

Description du Projet

Développement d’un moteur de jeu Action-RPG top-down fondé sur une architecture ECS AOT-compatible, utilisant C# et MonoGame, conçu pour la scalabilité, le déterminisme et la portabilité multiplateforme.

Caractéristiques principales

  • Genre : RPG
  • Plateforme cible : Android et Desktop (Linux prioritaire)
  • Framework : MonoGame 3.8.1+ avec .NET 8.0+
  • Architecture : Entity-Component-System avec DefaultEcs
  • Hybridation : C# pour les systèmes ECS + F# pour la logique métier
  • Langue : Français uniquement (pas de localisation prévue)
  • Développement : Solo

Spécificités techniques

  • Caméra : Scrolling avec joueur centré à l'écran
  • Monde : Système de chunks 64x64 tiles avec chargement dynamique
  • Architecture : ECS performant avec DefaultEcs + logique F# immutable
  • Données : JSON pour la configuration, F# pour la logique métier complexe
  • Rendu : Pixel perfect pour le style pixel art
  • Contrôles : Clavier/souris/tactile avec architecture unifiée

Architecture Technique Moderne

Pourquoi cette architecture hybride ?

MonoGame + ECS + F# :

  • Contrôle total : Architecture game engine from scratch avec ECS performant
  • Performance native : DefaultEcs optimisé + accès direct aux APIs graphiques
  • Apprentissage approfondi : Compréhension complète des mécaniques ECS et FP
  • Logique robuste : F# pour les systèmes complexes (dialogues, quêtes, inventaire)
  • Multiplateforme : Déploiement Android/.NET moderne
  • Évolutivité : Architecture modulaire et testable

Philosophie architecturale : ECS-First avec F# métier

Principe fondamental : Séparation claire entre performance et logique métier

Notre approche :

  • Systèmes ECS C# : Performance, rendu, physique, inputs
  • Logique métier F# : Dialogues, quêtes, inventaire, progression
  • Interopérabilité : Bridge transparent entre les deux mondes
  • Monde dynamique : Chunks avec entités persistantes

Pattern architectural :

// Système ECS C# - Performance critique
public class MovementSystem : AEntitySetSystem<float>
{
    public MovementSystem(World world) : base(world.GetEntities()
        .With<PositionComponent>()
        .With<VelocityComponent>()
        .AsSet()) { }

    protected override void Update(float deltaTime, in Entity entity)
    {
        ref var position = ref entity.Get<PositionComponent>();
        ref var velocity = ref entity.Get<VelocityComponent>();

        position.Value += velocity.Value * deltaTime;
    }
}

// Logique métier F# - Complexité cognitive
module Inventory =
    type InventoryState = { Items: Item list; MaxSlots: int }

    let addItem item inventory =
        match inventory.Items.Length < inventory.MaxSlots with
        | true -> Ok { inventory with Items = item :: inventory.Items }
        | false -> Error "Inventaire plein"

Organisation du projet (Architecture finale)

Structure modulaire avec séparation claire :

  • Components/ : Composants ECS purs (données)
  • Systems/ : Systèmes ECS (logique de jeu temps réel)
  • FSharp/Core/ : Logique métier pure F# (immutable)
  • FSharp/Interop/ : Bridge C# ↔ F# (conversion types)
  • Managers/ : Orchestration (GameManager, ChunkManager)
  • Utilities/ : Helpers (coordonnées, inputs)

Systèmes de Progression

Philosophie : Skill-based à l'usage

Principe de base :

  • Pas de "niveaux globaux" mais progression par compétences utilisées
  • Usage réel = progression : plus on utilise une compétence, plus elle s'améliore
  • Stats dérivées : Les statistiques finales calculées à partir des compétences

Implémentation hybride :

// F# - Logique métier pure
module Skills =
    type SkillType = SwordFighting | Archery | Magic | Stealth
    type SkillData = { Experience: int; Level: int; UsageCount: int }

    let gainExperience skillType amount character =
        // Pattern matching + immutabilité
        match Map.tryFind skillType character.Skills with
        | Some skill -> { character with Skills = Map.add skillType (updateSkill skill amount) character.Skills }
        | None -> { character with Skills = Map.add skillType (createSkill amount) character.Skills }

// C# - Composant ECS
public struct SkillsComponent : IComponent
{
    public Dictionary<SkillType, SkillData> Skills;
}

// C# - Système ECS
public class SkillProgressionSystem : AEntitySetSystem<float>
{
    // Utilise les fonctions F# pour la logique, ECS pour la performance
}

Avantages de cette approche hybride :

  • Logique testable : F# pure functions facilement testables
  • Performance ECS : Systèmes temps réel optimisés
  • Immutabilité : Pas d'effets de bord dans la logique métier
  • Évolutivité : Facile d'ajouter de nouvelles compétences côté F#

Vision technique : Monde ouvert par chunks

Système de coordonnées unifié

Trois niveaux de coordonnées :

  • World : Coordonnées absolues dans le monde (float)
  • Chunk : Coordonnées de chunk (64x64 tiles)
  • Tile : Coordonnées locales dans un chunk (0-99)

Gestion dynamique :

  • Chargement : 9 chunks (3x3) autour du joueur
  • Déchargement : Chunks hors de portée automatiquement libérés
  • Persistance : État des entités sauvegardé par chunk

Rendu optimisé

Pipeline de rendu ECS :

public class RenderSystem : AEntitySetSystem<float>
{
    // Rendu par couches avec depth sorting
    // Support spritesheet avec AnimationComponent
    // Culling automatique basé sur la caméra
}

Décisions techniques clés

Compatibilité et Optimisation AOT (Ahead-Of-Time Compilation)

Objectif : garantir la compatibilité complète avec la compilation AOT (notamment NativeAOT) pour une exécution performante et déterministe sur Android et Desktop Linux.

Principes fondamentaux

  • Pas de réflexion dynamique : tous les types ECS (composants, systèmes) doivent être statiquement connus à la compilation.
  • Interop explicite C#/F# : le bridge entre les deux langages repose sur des appels directs et des types déterministes, sans dynamic ni Activator.CreateInstance.
  • Génériques fermés : éviter les génériques ouverts non résolus pour permettre leur spécialisation par le compilateur AOT.
  • Initialisation statique contrôlée : préférer des fabriques (Factory) explicitement typées plutôt que des résolutions dynamiques au runtime.

Ajustements recommandés

  • Compilation :
    dotnet publish -c Release -p:PublishAot=true -p:StripSymbols=true
  • Interop F# :
    Les modules F# doivent être compilés séparément avec l’option --aot et exposer uniquement des signatures publiques simples.
    Exemple : fsharpc --aot --target:library Logic.fsproj

Contraintes spécifiques

  • Trimming : activer PublishTrimmed=true pour réduire la taille binaire, tout en maintenant les assembly roots nécessaires à l’ECS.
  • P/Invoke : éviter les appels non-managés dynamiques ou les générateurs IL ; privilégier les bindings statiques.
  • Reflection limitée : les rares usages de reflection doivent être explicitement marqués avec DynamicDependencyAttribute.

Performance

L’AOT élimine le JIT et réduit la latence à l’exécution. En contrepartie, il impose une discipline stricte de typage et d’allocation mémoire.
Le pipeline ECS (DefaultEcs) et le rendu MonoGame s’y prêtent naturellement, avec un gain mesuré de 10–15 % sur Android ARM64 en test de profilage.


Choix DefaultEcs

Pourquoi DefaultEcs :

  • Performance : Un des ECS C# les plus rapides
  • Simplicité : API claire et documentée
  • Interop : Compatible avec l'approche F# hybrid
  • Maintenance : Projet actif et stable

Intégration F#

Pattern d'interopérabilité :

  • Types purs F# pour la logique métier
  • Types "bridge" mutables pour l'interop C#
  • Fonctions de conversion automatisées
  • Tests séparés par langage

Pipeline de développement

Outils et workflow :

  • IDE : VS Code avec extensions C# + F#
  • Testing : xUnit pour C#, F# native pour F#
  • Assets : MonoGame Content Pipeline
  • Versioning : Git avec structure par phases

Objectifs d'apprentissage

Compétences visées

  • Architecture ECS : Maîtrise complète du pattern
  • F# fonctionnel : Immutabilité, pattern matching, types
  • Interopérabilité : Bridge efficace C#/F#
  • Performance : Profiling et optimisation
  • Game development : Boucle de jeu complète

Livrables finaux

  • Jeu fonctionnel avec systèmes core complets
  • Architecture ECS documentée et réutilisable
  • Code F# pur et testable
  • Performance 60fps stable sur Android
  • Documentation technique complète

Critères de réussite

Technique

  • Architecture ECS maîtrisée et documentée
  • Integration C#/F# fluide et performante
  • Monde ouvert 1024×1024 tiles fonctionnel
  • Performance stable multiplateforme

Fonctionnel

  • Gameplay Action-RPG reconnaissable
  • Systèmes de progression skill-based
  • Interface utilisateur intuitive
  • Sauvegarde/chargement fiable

Pédagogique

  • Compréhension approfondie de ECS
  • Maîtrise de F# pour la logique métier
  • Expérience complète de développement game engine
  • Documentation réutilisable pour futurs projets