Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 7 sur 7
  1. #1
    Invité de passage
    Homme Profil pro
    Inscrit en
    novembre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : novembre 2012
    Messages : 11
    Points : 0
    Points
    0

    Par défaut Réaliser des projectiles (shooter)

    Bonjour,

    Alors voilà, je travaille, avec la SFML, sur un petit projet du genre Space Invaders (en un peu plus moderne visuellement). Pour l'instant j'ai donc un vaisseau qui se déplace sur un fond. J'aimerai bien sûr qu'il puisse tirer des projectiles. Je problème c'est que je ne sais pas du tout comment faire. Tout ce que j'ai pu faire, c'est impléménter un classe Projectile comme un personnage (CAD un sprite qui se déplace d'un point à un autre). Mais je pense qu'il y a mieux, surtout que ça pose problème dès que je veux tirer plus d'un coup.

    J'ai vaguement lu sur le net qu'il faudrait une classe hériter de sf:: Drawable, pour dessiner une trajectoire mais je n'ai aucune idée de comment m'y prendre.

    Donc si quelqu'un avait une idée, son aide serai la bienvenue (parce que c'est nul un jeu de shoot qui shoot pas )

    Merci d'avance pour votre aide

  2. #2
    Invité de passage
    Homme Profil pro
    Inscrit en
    novembre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : novembre 2012
    Messages : 11
    Points : 0
    Points
    0

    Par défaut

    Rebonsoir ! J'ai donc fait une classe Projectile, et implémenté une méthode Attaquer dans ma classe Vaisseau. Dans cette méthode, j'appelle le constructeur de Projectile avec comme paramètre le filePath, le SubRect, la position de départ (le plus compliqué pour moi) et la vitesse. De manière à appeler la méthode Tirer du Vaisseau depuis le main dans les evennements. Le problème c'est que je ne sais pas comment dessiner le sprite Projectile, vu que je n'ai pas d'objet projectile dans le main.

    J'ai essayé de faire une méthode pour récuperer le sprite dans le Vaisseau mais je m'embrouille. Mon code sera peut être plus parlant :

    Projectile.hpp
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #ifndef PROJECTILE_HPP_INCLUDED
    #define PROJECTILE_HPP_INCLUDED
     
    #include <SFML/Graphics.hpp>
     
    class Projectile
    {
        public :
            Projectile(const std::string & filePathProj, sf::IntRect subRect, sf::Vector2f positionDepart, int vitesse);
     
            sf::Sprite GetSprite();
            void Tirer();
     
        private :
            sf::Image imgProjectile;
            sf::Sprite m_projectile;
     
            int m_vitesse;
    };
    #endif // PROJECTILE_HPP_INCLUDED
    Projectile.cpp
    Code :
    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
    #include <iostream>
    #include "Projectile.hpp"
     
    using namespace sf;
    using namespace std;
     
    Projectile::Projectile(const string & filePathProj, IntRect subRect, Vector2f positionDepart, int vitesse) : m_vitesse(vitesse);
    {
        if (!imgProjectile.LoadFromFile(filePathProj)
        {
            cerr << "Erreur dans le chargement de "<<filePathProj << endl;
        }
        else
        {
            imgProjectile.CreateMaskFromColor(Color::Black);
            m_projectile.SetImage(imgProjectile);
            m_projectile.SetSubRect (subRect);
            m_projectile.SetPosition(positionDepart.x, positionDepart.y)
        }
    }
     
    void Projectile::Tirer()
    {
        m_projectile.Move(0, -m_vitesse);
    }
     
    Sprite Projectile::GetSprite();
    {
        return m_projectile;
    }
    Vaisseau.hpp
    Code :
    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
    #ifndef VAISSEAU_HPP_INCLUDED
    #define VAISSEAU_HPP_INCLUDED
     
    #include <SFML/Graphics.hpp>
     
    class Vaisseau
    {
        public :
            Vaisseau(const std::string& filePath, sf::Vector2f position, sf::IntRect subRect, float vitesse);
     
            enum Direction {AVANT, ARRIERE, DROITE, GAUCHE};
            enum Action {FEU}; 
            sf::Sprite GetSprite();
            sf::Sprite GetProjSprite();
     
            void Deplacement(Direction direction);
            void Attaquer(Action action, sf::Vector2f positDepart);
     
            sf::Vector2f GetPositAct();
     
        private :
            sf::Image imgVaisseau;
            sf::Sprite m_vaisseau;
     
            float m_vitesse;
            float m_X;
            float m_Y;
    };
    #endif // VAISSEAU_HPP_INCLUDED
    Vaisseau.cpp
    Code :
    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
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    #include "Vaisseau.hpp"
    #include "Projectile.hpp"
    #include <iostream>
     
    using namespace sf;
    using namespace std;
     
     
     
    Vaisseau::Vaisseau(const string& filePath, Vector2f position, IntRect subRect, float vitesse) : m_vitesse(vitesse)
    {
        if(!imgVaisseau.LoadFromFile(filePath))
        {
            cerr << "Erreur dans le chargement de " <<filePath <<endl;
        }
        else
        {
            imgVaisseau.CreateMaskFromColor(Color::White);
            m_vaisseau.SetImage(imgVaisseau);
            m_vaisseau.SetSubRect(subRect);
            m_vaisseau.SetPosition(position);
            m_vaisseau.SetScale(0.7, 0.7);
        }
    }
     
    Sprite Vaisseau::GetSprite()
    {
        return m_vaisseau;
    }
     
    Vector2f Vaisseau::GetPositAct()
    {
          Vector2f positAct = m_vaisseau.GetPosition(); //Tentative d'actuallisation de la position du vaisseau après déplacement
          return positAct;
    }
     
    void Vaisseau::Deplacement(Direction direction)
    {
        if (direction == AVANT)
        {
            m_vaisseau.Move(0, -m_vitesse);
        }
        if (direction == ARRIERE)
        {
            m_vaisseau.Move(0, m_vitesse);
        }
        if (direction == DROITE)
        {
            m_vaisseau.Move(m_vitesse, 0);
        }
        if (direction == GAUCHE)
        {
            m_vaisseau.Move(-m_vitesse, 0);
        }
    }
     
     
        Projectile tirCentre(PROJ_FILE_PATH, PROJ_SUB_RECT, POS_DEPART_PROJ, VITESSE_PROJ); /* Je ne sais pas où mettre mon constructeur. J'ai besoin de tirCentre dans les deux méthodes suivante,
        mais je ne veux pas que l'on voit le projectile avant d'avoir appeler la méthode Attaquer*/
     
    void Vaisseau::Attaquer(Action action, Vector2f positDepart)
    {
        const string PROJ_FILE_PATH = "tirCentral.png";
        const IntRect PROJ_SUB_RECT (0,0,40,84);
        const Vector2f POS_DEPART_PROJ (positDepart.x + 63, positDepart.y + 20); //Pour définir la position du départ du tir par rapport au sprite du vaisseau.
        const int VITESSE_PROJ = 10;
     
        if (action == FEU)
        {
            tirCentre.Tirer(); // appel de la méthode Tirer, qui déplace le sprite projectile.
        }
    }
     
    Sprite Vaisseau::GetProjSprite()                    //ici, c'est une tentative de methode pour renvoyer le sprite du projectile. En l'appelant depuis le main.
    {
        Sprite projSprite = tirCentre.GetSprite();
        return projSprite;
     
    }
    main.cpp
    Code :
    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
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    #include <iostream>
    #include "Vaisseau.hpp"
    #include "Projectile.hpp"
     
    using namespace sf;
    using namespace std;
     
    const string VAISSEAU_FILE_PATH = "vaisseau.png";
    const string BACKGROUND_FILE_PATH = "background.png";
    const string ENNEMI_FILE_PATH = "Ennemi1.png";
     
    const Vector2f VAISSEAU_POSIT_INIT (400, 400);
    const Vector2f ENNEMI_1_POSIT_INIT (100, -146);
    const Vector2f ENNEMI_2_POSIT_INIT (300, -146);
    const Vector2f ENNEMI_3_POSIT_INIT (500, -146);
    const Vector2f ENNEMI_4_POSIT_INIT (700, -146);
     
    const IntRect VAISSEAU_SUBRECT (0, 0, 128, 180);
    const IntRect ENNEMI_SUBRECT (0, 0, 134, 146);
     
    const float VAISSEAU_VITESSE = 0.5;
     
    const Vector2f TAILLE_FANETRE (1024, 768);
     
    int main()
    {
        Image imgBackground;
        Sprite background;
     
        Vaisseau monVaisseau(VAISSEAU_FILE_PATH, VAISSEAU_POSIT_INIT, VAISSEAU_SUBRECT, VAISSEAU_VITESSE);
        Vaisseau ennemi_1 (ENNEMI_FILE_PATH, ENNEMI_1_POSIT_INIT, ENNEMI_SUBRECT, VAISSEAU_VITESSE); //ne faites pas attention aux vaisseau ennemis, c'est juste un essai.
        Vaisseau ennemi_2 (ENNEMI_FILE_PATH, ENNEMI_2_POSIT_INIT, ENNEMI_SUBRECT, VAISSEAU_VITESSE);
        Vaisseau ennemi_3 (ENNEMI_FILE_PATH, ENNEMI_3_POSIT_INIT, ENNEMI_SUBRECT, VAISSEAU_VITESSE);
        Vaisseau ennemi_4 (ENNEMI_FILE_PATH, ENNEMI_4_POSIT_INIT, ENNEMI_SUBRECT, VAISSEAU_VITESSE);
     
        RenderWindow App(VideoMode((int)TAILLE_FANETRE.x,(int)TAILLE_FANETRE.y, 32), "Alien Epurator");
     
        if (!imgBackground.LoadFromFile(BACKGROUND_FILE_PATH))
        {
            cerr << "Erreur dans le chargement de "<<BACKGROUND_FILE_PATH << endl;
        }
        else
        {
            background.SetImage(imgBackground);
        }
     
        while (App.IsOpened())
        {
            Event event;
            while (App.GetEvent(event))
            {
                if ((event.Type == Event::KeyPressed && event.Key.Code == Key::Escape)||event.Type == Event::Closed)
                    {
                        App.Close();
                    }
            }
     
            ennemi_1.Deplacement(Vaisseau::ARRIERE); //
            ennemi_2.Deplacement(Vaisseau::ARRIERE);
            ennemi_3.Deplacement(Vaisseau::ARRIERE);
            ennemi_4.Deplacement(Vaisseau::ARRIERE);
     
            const Input & input = App.GetInput();
     
            if(input.IsKeyDown(Key::Up))
            {
                monVaisseau.Deplacement(Vaisseau::AVANT);
            }
            if(input.IsKeyDown(Key::Down))
            {
                monVaisseau.Deplacement(Vaisseau::ARRIERE);
            }
            if(input.IsKeyDown(Key::Right))
            {
                monVaisseau.Deplacement(Vaisseau::DROITE);
            }
            if (input.IsKeyDown(Key::Left))
            {
                monVaisseau.Deplacement(Vaisseau::GAUCHE);
            }
            if (input.IsKeyDown(Key::Space))
            {
                vector2f positionActuelle = monVaisseau.GetPositAct();
                monVaisseau.Attaquer(Vaisseau::FEU, positionActuelle.x, positionActuelle.y); //Le but ici est d'appeler indirectement le constructeur de Projectile si on appuie sur Space.
            }
     
            App.Clear();
            App.Draw(background);
            App.Draw(monVaisseau.GetSprite());
            App.Draw(monVaisseau.GetProjSprite()); // Imposiible de dessiner le sprite Projectile, j'ai besoin d'une instance de Projectile dans le main.
            App.Draw(ennemi_1.GetSprite());
            App.Draw(ennemi_2.GetSprite());
            App.Draw(ennemi_3.GetSprite());
            App.Draw(ennemi_4.GetSprite());
            App.Display();
        }
        return EXIT_SUCCESS;
    }
    Voila, désolé pour mon amateurisme (j'ai peut être été un peu ambitieux sur ce coup là )

    Merci d'avance pour votre aide!

  3. #3
    Membre habitué Avatar de quentinh
    Homme Profil pro Quentin Henriet
    Étudiant
    Inscrit en
    mars 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Nom : Homme Quentin Henriet
    Âge : 22
    Localisation : France, Ardennes (Champagne Ardenne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : mars 2011
    Messages : 79
    Points : 123
    Points
    123

    Par défaut

    Tu t'es lancé un peu vite dans l'écriture du code et tu as zappé un peu vite la conception ^^
    Il y a plusieurs problèmes dans ton code :
    → La classe Projectile ne devrait pas contenir sa sf::Image, car d'après ce que j'ai compris, un nouveau Projectile est créé à chaque tir ; et donc, l'image est rechargée à chaque fois, c'est extrêmement lent, et tu as donc plusieurs copies de la même image en mémoire si tu as plusieurs projectiles en même temps (ce qui est très probable). Tu devrais entièrement externaliser ta gestion des images pour ne charger et ne décharger qu'une seule fois les images nécessaires. (y compris pour les vaisseaux)
    → Ta fonction Sprite Vaisseau::GetProjSprite() ne devrait pas exister, évite de faire ce genre de truc bizarre qui de toute façon ne marche pas bien…
    → Tu disais que tu avais un problème au niveau du main() étant donné que tu n'a pas l'objet Projectile ; une solution serait par exemple (c'est ce que je fais pour mon jeu mais c'est peut-être pas ce qu'il y a de mieux…) de faire une classe de base pour tout élément sur l'écran, puis en faire des classes dérivées pour chaque type d'élément (vaisseau, projectile, etc…). Ainsi les fonctions communes comme l'affichage par exemple sont dans la classe de base, et les fonctions plus spécifiques dans les classes dérivées. Tu peux ensuite créer un conteneur (list par exemple) de type «pointeur sur la classe de base», au niveau global, dans lequel tu pourrais placer tes vaisseaux qui a leur tour pourraient placer des projectiles. Ainsi une fois le projectile créé, il est indépendant et dissocié du vaisseau qui l'a créé et tu n'as plus besoin de fonctions bizarre comme celle au-dessus, et tu peux en créer autant que tu veux avec le même vaisseau. Le main gère ainsi cette liste d'éléments de manière basique, sans savoir quel est leur type précis, et sans se soucier de leur nombre.

    C'est loin d'être simple ce que je raconte, ce n'est qu'une méthode parmi d'autres, mais c'est celle que j'utilise personnellement ^^
    Et surtout, un jeu vidéo ça commence sur papier et non dans un éditeur de code, retravaille bien ta conception avant de te lancer dans le codage.
    Mon projet : Devilsai

  4. #4
    Invité de passage
    Homme Profil pro
    Inscrit en
    novembre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : novembre 2012
    Messages : 11
    Points : 0
    Points
    0

    Par défaut

    Oui je sais je tatonne carrément. mais ça me fait pratiquer et me force à reflechir sur mes erreurs. Pour l'organisation papier, c'est juste qu'à la base, je ne sais pas vraiment comment m'y prendre, alors je me confronte au code, je m'aide avec des codes d'autres programmes, pour reprendre leurs fonctionnalités en les adaptant. Je voulais réussir à faire tirer mon vaisseau, pour ensuite réfléchir à l'organisation globale du projet. C'est pour ça que c'est un peu fouillis. Mais je commence maintenant à penser plus "global".

    Sinon je suis en train de suivre tes conseils mais j'ai un peu de mal à manipuler les vector<Objet*>. Un de mes plus gros soucis de ces dernières heures, c'est réussir à transmettre la position actualisée de mon vaisseau au projectile (vu que je ne peux pas le faire dans le constructeur <Projectile*>, c'est bien ça?). En gros, comment puis je appeler mes fonction membres avec un vecteur dynamique? Parce qu'au moment ou je crée un new <Projectile>, la classe projectile ne "sait" pas d'où partir.

    merci

  5. #5
    Membre habitué Avatar de quentinh
    Homme Profil pro Quentin Henriet
    Étudiant
    Inscrit en
    mars 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Nom : Homme Quentin Henriet
    Âge : 22
    Localisation : France, Ardennes (Champagne Ardenne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : mars 2011
    Messages : 79
    Points : 123
    Points
    123

    Par défaut

    Le type vector ne doit pas être le plus approprié. À mon avis, une list ou une map serait plus approprié. L'avantage d'une map serait de pouvoir donner un identificateur unique à chaque élément, ce qui peut être pratique si par exemple un élément doit être «connecté» à un autre.
    Voici une idée avec une map :
    Code :
    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
    #include <map>
     
    using namespace std;
     
    struct Element
    {
         int PosX, PosY;
    };
    struct Projectile : public Element
    {
         Projectile(int x, int y)
         {
              PosX = x;
              PosY = y;
         }
         Projectile()
         {
         }
    };
     
    typedef map < int, Element* > MapPointeursElements; //Plus pratique pour la suite
    MapPointeursElements ListeElements; //Notre variable globale
     
     
    int NouvelId() //Donne un identifiant unique à chaque élément
    {
         static int id = 0;
         return ++id;
    }
     
    void CreerProjectile(int x, int y)
    {
         Projectile *prj = NULL;
         int IdPrj = NouvelId();
     
         ListeElements.insert(MapPointeursElements::value_type(IdPrj, prj));
         MapPointeursElements::iterator i = ListeElements.find(IdPrj);
     
         i->second = new Projectile(x, y);
    }
     
    int main()
    {
         CreerProjectile(0, 0);
     
         for (MapPointeursElements::iterator i = ListeElements.begin() ; i != ListeElements.end() ; ++i)
         {
              //Gestion de tous les éléments
         }
     
         //Suppression :
         for (MapPointeursElements::iterator i = ListeElements.begin() ; i != ListeElements.end() ; ++i)
         {
              delete i->second;
         }
     
         ListeElements.clear();
    }
    Mon projet : Devilsai

  6. #6
    Invité de passage
    Homme Profil pro
    Inscrit en
    novembre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : novembre 2012
    Messages : 11
    Points : 0
    Points
    0

    Par défaut

    Désolé du retard, j'ai vraiment des problèmes de connexion (ahhh la belgique ). Je vais essayer de pas poster deux fois les mêmes réponses...

    D'abord, merci pour ton aide. Ceci dit, ça va devoir attendre avant d'être fonctionnel car mon savoir et mon expérience ont leurs limites. En effet, je n'ai pas encore vu les itérateurs (ou très vageument), c'est pourquoi je pansais à un vector.
    Ensuite, il me semble que le type "struct" appartient plus au langage C non? Ca non plus je ne suis pas vraiment au point ; je ne connais que le C++, et encore dans une certaine mesure. Mais je vais de ce pas me mettre au point

    Sinon, j'ai trouvé une ressource sur un autre site.

    Ils n'expliquent pas toute la marche à suivre, mais ils utilisent bien de vector. Je vais donc essayer de faire ça de plusieurs manière de façon à déterminer la plus appropriée.

    Merci beaucoup

  7. #7
    Membre habitué Avatar de quentinh
    Homme Profil pro Quentin Henriet
    Étudiant
    Inscrit en
    mars 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Nom : Homme Quentin Henriet
    Âge : 22
    Localisation : France, Ardennes (Champagne Ardenne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : mars 2011
    Messages : 79
    Points : 123
    Points
    123

    Par défaut

    Le "struct" en C++ est équivalent au "class", à la différence près que les champs sont par défaut de type "public" dans un struct, et de type "private" dans une class. C'est toujours mieux de privilégier les champs private, ça évite de faire des erreurs, mais pour le petit bout de code que j'ai posté ça n'a pas vraiment d'importance. Des class fonctionneraient tout aussi bien.
    L'intérêt d'utiliser des vector serait, d'après l'article que tu cites, d'améliorer les performances du programme. Personnellement, je ne suis pas convaincu du réel intérêt des vector, d'abord parce qu'il y a des structures de données plus simples à utiliser, et ensuite parce qu'il y a aussi mieux à faire en termes de performances. À mon avis, le plus important c'est que tu comprennes bien comment fonctionne le code, et donc fais au plus simple. T'auras le temps de t'occuper des questions de performances plus tard ^^ Mais si c'est bien expliqué et que tu y arrives c'est le principal !
    Mon projet : Devilsai

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •