Partage
  • Partager sur Facebook
  • Partager sur Twitter

[AIDE] [QT] RPG partie combat

Sujet résolu
8 août 2018 à 22:47:37

Bonjour,

Tout d'abord merci de intéresser à ce sujet.

Je me présente Samuel CASAS DRAY, j'ai 17 ans et cela fait 5 ans que je code mais plus depuis 1 ans avec python et maintenant avec C++, j'ai donc touche a pas mal de langage.

Je ne pourrais pas mettre mon code ici car pour ce que j'ai besoin je devrais mettre plusieurs fichier et cela deviendrais illisible. (Si vous pensez que je peux quand même j’éditerais ce post). Le projet contient des classes de personnages, de combat, de fenetre, d'arme, d'evenement

Mon problème c'est que j'ai fini pratiquement les cours en C++ proposé et je voudrais faire un RPG car fan de l'univers fantastique pour réorganiser mes connaissances mais je bloque sinon je ne serais pas ici :p. En gros je suis en train de faire la partie combat et pour ne pas trop me compliquer je le fais a la mode Pokemon, le joueur et en face l'ennemi, chacun a tour de rôle exécute une action : attaquer, fuir, sac ... Mais j'ai 6 classe de personnage qui hérite de la class Personnage et le problème c'est que je n'arrive pas a récupérer la classe du joueur pour qu'il attaque, j'ai essayer avec des template ça ne marche pas, j'ai essayer en passant par des pointeurs ça ne marche pas. Mais je pense que la solution c'est d'utiliser des pointeur mais je n'y arrive pas.

Donc voila si une âme charitable pourrait m'aider j'ai discord, ts, skype et autre.

De plus si quelqu'un serait intéresser pour que l'on travaille ensemble pour le finir et ensuite l’améliorer, ce serait avec plaisir

Cordialement.

Samuel CASAS DRAY.

-
Edité par samuel | coopyso 8 août 2018 à 22:50:26

  • Partager sur Facebook
  • Partager sur Twitter
8 août 2018 à 23:09:52

Lu',

normalement ça devrait le faire avec le polymorphisme. Il nous faut un minimum de code pour voir ce qu'il ne va pas.

PS: le cour du site est obsolète. Fais des recherches si tu as des questions dessus.

  • Partager sur Facebook
  • Partager sur Twitter

Eug

8 août 2018 à 23:42:07

Salut,

Tu peux mettre ton code sur Github ou utiliser Pastebin ou d'autres sites de ce genre.

  • Partager sur Facebook
  • Partager sur Twitter
Tutoriel Ruby - Bon tutoriel C - Tutoriel SDL 2 - Python avancé - Faîtes un zeste, devenez des zesteurs
9 août 2018 à 13:08:22

Salut,

Ok ben je vais utiliser Github ta raison j'y avais pas penser attendez

EDIT :: https://github.com/deathxxx34/RPG-C-QT.git

EDIT 2 :: juste je le redis j'ai commencer c++ il y a 1 mois et je n'errete pas de faire des modif donc c'est assez confus et pas tres propre apres dite moi s'il y a des chose a corriger a ameliorer sa m'aiderait beaucoup

-
Edité par samuel | coopyso 9 août 2018 à 18:33:07

  • Partager sur Facebook
  • Partager sur Twitter
9 août 2018 à 15:08:13

Salut, tu peux montrer sinon juste la fonction où tu dois récupérer le personnage ?
  • Partager sur Facebook
  • Partager sur Twitter
Toujours plus
9 août 2018 à 18:30:43

bozo6919 a écrit:

Salut, tu peux montrer sinon juste la fonction où tu dois récupérer le personnage ?

Voila 

#include <QProgressBar>
#include "combat.h"
#include "Personnage.h"

Combat::Combat(Game *scene)
{
    m_scene = scene->GetScene();
    m_game = scene;


    if(QString(typeid(m_game->GetClass()).name()).contains("Magicien"))
    {
        *persoclass = m_game->GetClass();
    }


    m_scene->setSceneRect(0,0,640,640);

    m_scene->clear();

    QGraphicsPixmapItem *image;

    image = new QGraphicsPixmapItem(QPixmap::fromImage(QImage("images/decor combat.png")).scaled(640,640));
    image->setPos(0,0);
    m_scene->addItem(image);

    image = new QGraphicsPixmapItem(QPixmap::fromImage(QImage("images/perso.png")).scaled(200,270));
    image->setPos(50,120);
    m_scene->addItem(image);

    image = new QGraphicsPixmapItem(QPixmap::fromImage(QImage("images/monstre_3.png")).scaled(200,270));
    image->setPos(390,120);
    m_scene->addItem(image);

    //merlin = new Magicien;
    tueur = new Monstre;

    vie_1 = new QProgressBar;
    vie_2 = new QProgressBar;
    mana_1 = new QProgressBar;
    mana_2 = new QProgressBar;
    this->reload();
    vie_1->setGeometry(QRect(50,25,200,25));
    vie_2->setGeometry(QRect(390,25,200,25));
    mana_1->setGeometry(QRect(50,75,200,25));
    mana_2->setGeometry(QRect(390,75,200,25));
    vie_1->setAlignment(Qt::AlignCenter);
    //vie_2->setAlignment(Qt::AlignCenter);
    mana_1->setAlignment(Qt::AlignCenter);
    //mana_2->setAlignment(Qt::AlignCenter);
    vie_2->setTextVisible(false);
    mana_2->setTextVisible(false);
    m_scene->addWidget(vie_1);
    m_scene->addWidget(vie_2);
    m_scene->addWidget(mana_1);
    m_scene->addWidget(mana_2);

    persoclass->SetAttack(1,"Brise Regeneratrice");
    persoclass->SetAttack(2,"Caresse de l'ocean");

    QPushButton *b_attack1 = new QPushButton;
    b_attack1->setText(persoclass->GetAttack(1));
    b_attack1->setGeometry(QRect(25,440,150,50));
    m_scene->addWidget(b_attack1);

    QPushButton *b_attack2 = new QPushButton;
    b_attack2->setText(persoclass->GetAttack(2));
    b_attack2->setGeometry(QRect(200,440,150,50));
    m_scene->addWidget(b_attack2);

    QPushButton *b_attack3 = new QPushButton;
    b_attack3->setText("Rien");
    b_attack3->setGeometry(QRect(25,540,150,50));
    m_scene->addWidget(b_attack3);

    QPushButton *b_attack4 = new QPushButton;
    b_attack4->setText("Petit test 40");
    b_attack4->setGeometry(QRect(200,540,150,50));
    m_scene->addWidget(b_attack4);


    merlin = new Magicien;
    connect(b_attack1, &QPushButton::clicked, [=](){ merlin->attaquer(1,*merlin); this->reload(); });
    connect(b_attack2, &QPushButton::clicked, [=](){ merlin->attaquer(2,*tueur); this->reload(); });
}

void Combat::test() {QApplication::exit();}

void Combat::reload()
{
    vie_1->setValue(merlin->Cmbvie());
    vie_2->setValue(tueur->Cmbvie());
    mana_1->setValue(merlin->Cmbmana());
    mana_2->setValue(tueur->Cmbmana());
    vie_1->setFormat(QString::number(merlin->Cmbvie()));
    //vie_2->setFormat(QString::number(tueur->Cmbvie()));
    mana_1->setFormat(QString::number(merlin->Cmbmana()));
    //mana_2->setFormat(QString::number(tueur->Cmbmana()));
}



-
Edité par samuel | coopyso 9 août 2018 à 18:31:47

  • Partager sur Facebook
  • Partager sur Twitter
10 août 2018 à 11:37:22

C'est sur cette ligne ?

        *persoclass = m_game->GetClass();

Si non, c'est laquelle ? ^^

Edit :

tu connais dynamic_cast ? Tu peux l'utiliser pour retrouver ta sous classe.

Par exemple si tu as une classe mère véhicule et des sous classes comme voiture, moto et camion. Si tu veux savoir avec quelle sous classe tu te situe, tu peux faire :

void vehicule::searchSubClass()
{
    if (dynamic_cast<voiture>(this))
        qDebug() << "C'est une voiture";
    else if (dynamic_cast<moto>(this))
        qDebug() << "C'est une moto";
    else if (dynamic_cast<camion>(this))
        qDebug() << "C'est un camion";
}



-
Edité par bozo6919 10 août 2018 à 12:23:37

  • Partager sur Facebook
  • Partager sur Twitter
Toujours plus
10 août 2018 à 12:31:03

@bozo, le PO est nouveau en programmation, dynamic_cast est un truc dégueulasse pour faire du type switching (ce que tu fais dans ton exemple), donc ne montre pas d echoses dégueulasse à un débutant, tu vas lui donner de mauvaises habitudes.

@Samuel, L'utilisation de typeid, à l'instar de dynamic_cast, ne devrait pas être utilisé de cette manière. Afin de connaître le type réel d'un objet, utilises plutôt le design pattern visiteur.

Si ton nombre de classe est déjà défini, tu peux utiliser un std::variant plutôt qu'une hiérarchie de classe. Mais par pitié évite la RTTI (dynamic_cast / typeid sur objet polymorphique) pour faire du type switching.

Pour avoir un code propre et lisible, essaie de faire des fonctions plus courtes, d'une cinquantaine de ligne maximum ;).

EDIT : Evite les pointeurs nu. Utilises plutôt les smart pointers (unique_ptr ou shared_ptr). L'utilisation de new devrait être interdite à part pour les objets dérivant de QObject. Les delete quand à eux ne devraient pas exister)

-
Edité par Qnope 10 août 2018 à 12:33:35

  • Partager sur Facebook
  • Partager sur Twitter
http://cpp-rendering.io : Vous trouverez tout ce dont vous avez besoin sur Vulkan / OpenGL et le rendu 3D !
10 août 2018 à 13:43:30

Qnope a écrit:

@bozo, le PO est nouveau en programmation, dynamic_cast est un truc dégueulasse pour faire du type switching (ce que tu fais dans ton exemple), donc ne montre pas d echoses dégueulasse à un débutant, tu vas lui donner de mauvaises habitudes.

Oui je sais, mais c'est toujours une piste ;)
  • Partager sur Facebook
  • Partager sur Twitter
Toujours plus
10 août 2018 à 14:04:44

Bonjour,

Merci pour vos reponses.

@Qnope je vais essayer de faire ce que tu as dit si jamais je n'y arrive pas je reviendrais

  • Partager sur Facebook
  • Partager sur Twitter
14 août 2018 à 17:34:10

Qnope a écrit:

@bozo, le PO est nouveau en programmation, dynamic_cast est un truc dégueulasse pour faire du type switching (ce que tu fais dans ton exemple), donc ne montre pas de choses dégueulasse à un débutant, tu vas lui donner de mauvaises habitudes.

Je partage totalement ton avis sur le down-cast. Mais une question me viens à l'esprit... A défaut d'être inutile, est-ce vraiment "mauvais" ?
  • Partager sur Facebook
  • Partager sur Twitter
14 août 2018 à 19:46:08

Salut,

Sillimon a écrit:

Je partage totalement ton avis sur le down-cast. Mais une question me viens à l'esprit... A défaut d'être inutile, est-ce vraiment "mauvais" ?

Dans 99.5% des cas, oui!!!!

Il est toujours possible de trouver une situation dans laquelle le down-cast (qu'il soit basé sur dynamic_cast ou, de préférence sur static_cast parce que l'on sait en quoi on veut transttyper la donnée que l'on connait comme étant du type de la classe parent) pourra être utile et intéressant, mais dans la très grosse majorité des cas, le down-cast va surtout mener à un non respect de l'OCP (Open / Close Principle ou "principe ouvert / fermé; le O de SOLID ;) ), ce qui va occasionner une dette technique importante ;).

En effet, la règle de base, de l'OCP, c'est qu'un code qui a été écrit et validé ne doit pas nécessiter de modification pour pouvoir intégrer une évolution / une nouvelle fonctionnalité.

Or, si tu en viens à avoir un code proche de

if(condition1){
    dynamic_cast<Truc*>(ptr)->foo();
}else if (condition2){
    dynamic_cast<Machin*>(ptr)->bar();
}else if (condition3){
    dynamic_cast<Brol*>(ptr)->doIt();
}/* ... */

tu peux t'attendre à te retrouver très rapidement avec dix, quinze ou vingt (ou ... beaucoup plus  :p : P ) endroits de ton code où une telle logique sera mise en oeuvre.

Le problème, c'est que, lorsque tu voudra rajouter une nouvelle classe, chaque endroit de ton code qui ne sera pas mis à jour occasionnera un bug, ne serait-ce que parce que la possibilité de transtyper en NouvelleClasse ne sera pas prise en compte :p

Avec un peu (beaucoup ???) de chance, tu penseras à mettre un, deux ou trois endroits de ton code; mais tu en oubliera dix, quinze ou vingt (et encore, dans les projet les plus simples ), et ce sera à chaque fois un bug potentiel parce que  ton code n'était pas "fermé aux modifications" !

Le meilleur moyen (en orienté objets, s'entend) de traiter correctement une instance de classe dérivée qui est connue comme étant du type de base passe de manière systématique par le polymorphisme et / ou par le double dispatch (qui, le plus souvent, utilise de toutes manières le polymorphisme :D ).

Encore faut-il -- bien sur (Mais ca, c'est un tout autre débat ;) ) -- que l'héritage que l'on a défini ait lui-même du sens et que LSP était correctement respecté, car on trend, bien souvent,  compte lorsque l'on en arrive à envisager d'avoir recours au dow-casting, que c'est surtout parce que l'on a fait une connerie en décidant que le type de dériver devait hériter du type
de base. 

Ceci étant dit, l'approche orientée objet n'est qu'une des approches que l'on peut envisager en C++, et il est tout à fait faux de croire que c'est "le saint graal" du développeur.

N'allez pas croire que je refuse l'approche orientée objets ni que je crache dans la soupe!  Cette approche s'avère particulièrement puissante dans de très nombreux cas...  Mais pas lorsqu'il s'agit de créer un RPG dans lequel nous verrions nos classes se multiplier plus vite que des rats ou des souris ;)

Dans le cadre d'un RPG, l'approche qui présentera sans doute le plus de flexibilité et de facilité sera d'avantage de type ECS (Entity Component System)

  • Partager sur Facebook
  • Partager sur Twitter
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
16 août 2018 à 12:08:53

Merci beaucoup pour ce pavé pédagogique, Koala Senseï. C'est bien plus clair désormais.^^

  • Partager sur Facebook
  • Partager sur Twitter
16 août 2018 à 22:00:53

Bonjour,

Comme Sillimon l'a dit merci koala je me suis renseigne sur l'ECS et effectivement tu as raison c'est le mieux dans le cadre d'un RPG car cela convient mieux.

  • Partager sur Facebook
  • Partager sur Twitter