IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Conception de classe RPG


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Par défaut Conception de classe RPG
    Bonjour,

    Sans plus attendre, voici mon bout de code (et oui, je suis un mec comme ça moi) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    #include <iostream>
    #include <vector>
     
    enum
    {
        CRUSHING,
        SLASHING
    };
     
    int dice(int sides)
    {
        return (rand() % sides + 1);
    }
     
    struct Weapon
    {
        int damageType;
     
        virtual int damage() = 0;
    };
     
    struct HAMM01 : Weapon
    {
        HAMM01()
        {
            damageType = CRUSHING;
        }
     
        int damage()
        {
            return dice(4) + dice(4);
        }
    };
     
    struct SW1H01 : Weapon
    {
        SW1H01()
        {
            damageType = SLASHING;
        }
     
        int damage()
        {
            return dice(6);
        }
    };
     
     
     
     
     
     
    int main()
    {
        srand(time(0));
     
        std::vector<Weapon*> weapons;
     
        weapons.push_back(new HAMM01);
        weapons.push_back(new SW1H01);
     
        std::cout<<weapons[0]->damage();
     
        return 0;
    }
    L'idée est simple : on a un marteau, qui inflige 2 dés 4 points de dégât contondant, et une épée, qui inflige 1 dé 6 points de dégât tranchant. Le but du jeu, c'est de coder la chose le plus proprement possible, et le plus lisiblement possible surtout. J'ai choisi l'héritage parce que les armes peuvent avoir des effets très différents de l'une à l'autre, et j'ai pensé que pour garder la plus grande souplesse possible dans mon code, le plus simple était encore d'écrire la fonction damage() à la main, pour chaque arme. Ça ne parait pas justifié dans mon exemple, ici, un vector stockant les jets de dé aurait amplement suffi. Mais imaginez qu'à chaque coup porté, la cible ait 5% de chance d'être aveugle pendant 3 rouds.. On ne s'en sort plus.
    Ce code est à peu près cohérent, je pense, mais quelque chose m'embête : on a donc une structure par arme, et je ne trouve pas ça très "propre" : le bon sens voudrait qu'on ait une structure la plus souple possible (appelons la "Arme", qu'on crée une première instance de cette structure appelée "marteau", une deuxième, "épée", et qu'on précise, pour chaque instance, les modalités du combat (toi tu infliges 2 dés 4, toi 1 dé 6). Mais là je me mords la queue : et si une arme rend l'ennemi aveugle pendant.. Bref.
    Une alternative envisageable serait de créer effectivement cette structure Arme, et que l'un de ses membres soit un pointeur sur une fonction, dans ce cas il faudrait créer plein de fonctions de dommage (dommage1(), dommage2(), etc) et, une fois que l'on a créé les instances de la classe, faire pointer ces pointeurs sur la bonne fonction. Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Arme marteau;
    marteau.damageFunction = damageFunction1;
    marteau.damageType = CRUSHING;
     
    Arme épée;
    épée.damageFunction = damageFunction2;
    épée.damageType = SLASHING;
    Mais la lisibilité du code n'est pas terrible, on se retrouve avec plein de fonctions de dommage en tête de mon fichier, sans trop savoir à quoi ça correspond ni à quelle arme cette fonction de dommage est associée. Alors qu'avec mon code qui utilise le polymorphisme, c'est clair tout de suite.

    Bref, je suis un peu torturé par tout ça, si un expert passe par là et qu'il a un conseil à me donner, je prends !

    Cordialement,

  2. #2
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 759
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 759
    Par défaut
    La question a été posée ... en Java Édit: Conseils conception logiciel

    L'intervenant comme toi voulait faire du polymorphisme/ héritage pour un jeu mais ne voulait pas passer par des traits ou autres [j'ai vu passé le terme de mixin mais pas sûr de sa définition].

    La raison aussi été la même: pleins de classes à coder/ maintenir. Il a tout à fait raison, mais on peut passer des valeurs par défaut en C++

    La solution: une classe générique avec un parser de fichier XML/ CSV/ json/ autre [même peut-être à tester base de données] qui contient toutes les valeurs.
    Un exemple en XML
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <root>
      <weapon name="HAMM01" damage="CRUSHING">
        <damage nb="2">
          <dice>4</dice>
          <dice>4</dice>
        </damage>
      </weapon>
      <weapon name="SW1H01" damage="SLASHING">
        <damage nb="1">
          <dice>6</dice>
        </damage>
      </weapon>
    </root>
    J'ai oublié de dire que les experts du forum avait opté pour cette solution parce qu'il n'y avait que des attributs, et en petit nombre.

  3. #3
    Membre confirmé
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Par défaut
    Je viens de regarder la discussion dont tu as envoyé le lien, je ne suis pas très habitué (pas du tout même) à utiliser des fichiers externes pour la création de mes classes. Il me vient déjà une question : imaginons que je crée une arme dont les dégâts seraient doublés lorsqu'elle est utilisée contre une certaine classe. Genre "super épée de la mort anti paladin". Ce comportement est quelque chose de très original, un comportement qui, à mon avis (mais je peux me tromper), ne peut pas être géré par des fichiers XML, CSV, ou properties.. Si ?
    Mais tant qu'à faire appel à des fichiers externes, je me suis à un moment posé la question de savoir si l'utilisation d'un langage de script ne pouvait pas être utile. Jusqu'à présent, je me suis débrouillé sans, mais peut être que c'est le moment de m'y pencher d'un peu plus près. Je pensais notamment au Lua, très facile à comprendre. J'aimerais avoir ton avis.

    Cordialement,

  4. #4
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 759
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 759
    Par défaut
    C'est un travail pour le patron de conception ("design pattern") Visiteur/ Visitor
    Le lien qui va bien

    En gros, tu as chargé une liste de tout ce qui peut être touché par une attaque (dont ta "super épée de la mort anti paladin")
    Et tu vas coder
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Damage_Visitor
    {
        void visit(Game_Object obj);
    };
     
     
    class Mega_Sword_Damage_Visitor: public Damage_Visitor {
        void visit(Paladin obj);
    };
    Après on peut faire plusieurs fichiers externes (si c'est la solution retenue) dont un "damages" qui contient les dégâts spécifiques

    Sinon je ne connais pas LUA

  5. #5
    Membre confirmé
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Par défaut
    Merci pour le lien, jvais regarder tout ça

    Cordialement,

  6. #6
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Par défaut
    Salut,

    Je comprend ton problème et je pense qu'on peut commencer par déplacer le problème. En effet tu peux créer une unique classe Arme qui possède un type de dégat et le montant des dégats. Comme tu l'as dit, ça pose problème vu que les armes peuvent avoir différent effets bien distincts les unes des autres. Dans ce cas, en découpant mieux, tu peux créer une classe Effect et chaque effets d'une arme héritera de cette classe, ainsi tu améliores la compositionabilité en gardant un nombre de classes réduits (plus 1 classe/arme mais 1 classe/effet). Ça donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    class Hero; // Représente un personnage héro.
    class Effect
    {
      virtual act(Hero) = 0;
      virtual ~Effect();
    };
     
    class BlindEffect : public Effect
    {
    private:
      double duration;
      double blindness;
     
    public:
      BlindEffect(double, double);
      virtual act(Hero h);
      virtual ~BlindEffect();
    };
     
    class WeakenEffect : public Effect
    {
    private:
      double duration;
      double slowdown;
     
    public:
      WeakenEffect(double, double);
      virtual act(Hero h);
      virtual ~WeakenEffect();
    };
     
    class Weapon
    {
      double damage;
      DamageKind kind;
      std::vector<std::unique_ptr<Effect>> effects;
     
    public:
      Weapon(double, DamageKind);
      void addEffect(std::unique_ptr<Effect>&& effect);
    };
     
    // Création d'une épée qui ralenti :
    Weapon sword(2, SLASHING);
    std::unique_ptr<Effect> weaken(new WeakenEffect(0.7, 50));
    sword.addEffect(std::move(weaken));
    Ce qui est bien c'est que tu peux ré-utiliser tes effets pour autres choses que les armes (l'environnement) et que tu as une combinaison infinie d'armes. Tu peux aussi ajouter des effets temporaires aux armes (bonus).

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Conception de classes
    Par Seth77 dans le forum Général Dotnet
    Réponses: 8
    Dernier message: 15/01/2007, 15h57
  2. [POO] conception des classes
    Par poukill dans le forum C++
    Réponses: 229
    Dernier message: 19/07/2006, 08h28
  3. [conception] reprise classes mal pensées
    Par in dans le forum Général Java
    Réponses: 8
    Dernier message: 05/06/2006, 13h45
  4. Conception de classe
    Par Azharis dans le forum C++
    Réponses: 9
    Dernier message: 17/12/2005, 10h15
  5. probleme de conception de classe
    Par NhyMbuS dans le forum C++
    Réponses: 2
    Dernier message: 08/05/2005, 17h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo