Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Problème d'intégration d'un thread dans une classe  (Lu 8068 fois)

0 Membres et 1 Invité sur ce sujet

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Problème d'intégration d'un thread dans une classe
« le: Septembre 28, 2013, 06:46:12 pm »
Bonjour

Voilà mon problème je souhaite faire des projectiles donc j'utilise un thread. Mais je n'arrive pas à intégrer un thread dans ma scène principale afin de lier ma classe projectile malgré avoir regardé la doc sur les threads ...

Voici mon code :

#include "Projectile.h"

Projectile::Projectile()
{
    Projectile_Blue.setSize(sf::Vector2f(1, 1));
    Projectile_Blue.setPosition(0, 400);
    Projectile_Blue.setFillColor(sf::Color::Blue);
}

void Projectile::Move(sf::RenderWindow &window)
{
    sf::FloatRect ProjectileBox(Projectile_Blue.getPosition(), Projectile_Blue.getSize());
    bool the_end = true;

    while(the_end)
    {
        if (ProjectileBox.contains(window.getSize().x, Projectile_Blue.getPosition().y))
        the_end = false;
        Projectile_Blue.move(5, 0);
        sf::sleep(sf::milliseconds(25));
    }
}

void Projectile::setPosition(int x, int y)
{
    Projectile_Blue.setPosition(x, y);
}

int Projectile::getPositionX(){ return Projectile_Blue.getPosition().x; }
int Projectile::getPositionY(){ return Projectile_Blue.getPosition().y; }
 

#ifndef PROJECTILE_H
#define PROJECTILE_H

#include <SFML/Graphics.hpp>
#include <iostream>

class Projectile : public sf::Drawable
{
    public:
        Projectile();

        void Move(sf::RenderWindow &window);
        void setPosition(int x, int y);

        int getPositionX();
        int getPositionY();

    private:
        virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
        {
            target.draw(Projectile_Blue, states);
        }

        sf::RectangleShape Projectile_Blue;
};

#endif // PROJECTILE_H
 


#include "Scene.h"

sf::Clock horloge;
sf::Time tempsFrame;

Scene::Scene()
{
    sf::RenderWindow window(sf::VideoMode(), "Warrior Of Space", sf::Style::Fullscreen);
    window.setKeyRepeatEnabled(true);
    window.setFramerateLimit(60);

    sf::Texture image;
    if(!image.loadFromFile("Ressources/Background.png"))
       std::cout<<"Error"<<std::endl;
    sf::Sprite background(image);

    Spaceship spaceship;
    Projectile projectile;
    Gui gui(&spaceship);

    sf::View camera(sf::FloatRect(0, 0, 800, 600));
    sf::Thread t_projectileMove(std::bind(&Projectile::Move, &projectile, &window));

    float timer;

    while (window.isOpen())
        {
            timer += m_tempsFrame.asSeconds();
            sf::Event event;
            while (window.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                {
                    window.close();
                    t_projectileMove.terminate();
                }

                if (event.type == sf::Event::Resized)
                {
                    sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height);
                    window.setView(sf::View(visibleArea));
                }

                if ( (event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape) )
                {
                    window.close();
                    t_projectileMove.terminate();
                }


                if ( (event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Right) )
                {
                    spaceship.Move(5, 0);
                }
                if ( (event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Left) )
                {
                    spaceship.Move(-5, 0);
                }
                if ( (event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Z) )
                {
                    spaceship.addHealth(+5);
                }
                if ( (event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::A) )
                {
                    spaceship.addHealth(-5);
                }
                if ( (event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Space) )
                {
                    t_projectileMove.terminate();
                    t_projectileMove.launch();
                }
            }

            std::cout << spaceship.getHealth() << std::endl;

            window.clear();
            window.draw(background);
            window.draw(spaceship);
            window.draw(projectile);
            window.draw(gui);
            gui.Update(&spaceship);
            m_tempsFrame = m_horloge.restart();
            window.setView(camera);
            window.display();
        }
}
 


#ifndef SCENE_H
#define SCENE_H

#include <SFML/Graphics.hpp>
#include <iostream>
#include <functional>

#include "Spaceship.h"
#include "Projectile.h"
#include "Gui.h"

class Scene
{
    public:
        Scene();

    private:
        sf::Clock m_horloge;
                sf::Time m_tempsFrame;
};

#endif // SCENE_H
 

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Problème d'intégration d'un thread dans une classe
« Réponse #1 le: Septembre 28, 2013, 07:18:28 pm »
Citer
je souhaite faire des projectiles donc j'utilise un thread
Quel rapport ??

La seule bonne réponse à ce "problème", c'est : oublie cette idée saugrenue tout de suite, et fais tout dans ton thread principal ;)

En plus ton utilisation des threads est plus que douteuse (la doc indique bien que la fonction terminate() ne devrait jamais être utilisée).
Laurent Gomila - SFML developer

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Re : Problème d'intégration d'un thread dans une classe
« Réponse #2 le: Septembre 28, 2013, 09:17:52 pm »
J'aimerai faire un projectile et j'ai trouvé un tuto qui explique comment faire un projectile avec le thread.
À la base je faisais bouger mon projectile avec le timer de la SFML mais le soucis c'est que j'arrivai à faire qu'un seul projectile et là j'aimerai pouvoir en avoir une centaine en même temps sans avoir de soucis de lag ...

Il faudrait que mon personnage puisse se déplacer en X et Y ainsi que se rotate tout en tirant des projectiles.
Si vous avez une idée moins gourmande et plus efficace je suis vraiment preneur :)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Problème d'intégration d'un thread dans une classe
« Réponse #3 le: Septembre 28, 2013, 09:43:36 pm »
Si tu as trouvé un tutoriel qui explique comment gérer un projectile avec un thread, banis-le tout de suite de tes favoris. C'est presque un cas d'école.

Quel était le problème de tout gérer dans le thread principal ? Tu t'y prenais sûrement mal.
Laurent Gomila - SFML developer

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Re : Problème d'intégration d'un thread dans une classe
« Réponse #4 le: Septembre 28, 2013, 09:49:04 pm »
À la base j'avais une classe projectile donc avec un constructeur où j’initialisais mon rectangle, puis dans la classe principale où se trouvait la boucle principale je faisais avancer mon projectile de n x par rapport au temps.
Mais le soucis c'est que j'étais bloqué à un seul projectile :/ 

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Re : Problème d'intégration d'un thread dans une classe
« Réponse #5 le: Septembre 28, 2013, 09:53:51 pm »
Voilà comment je faisais avancer mon projectile :

projectile.Move(0, -0.1*timer);

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Problème d'intégration d'un thread dans une classe
« Réponse #6 le: Septembre 28, 2013, 10:45:20 pm »
Jusque là pas de souci. Pourquoi est-ce que tu étais bloqué à un seul projectile ? Où était la limitation ?
Laurent Gomila - SFML developer

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Re : Problème d'intégration d'un thread dans une classe
« Réponse #7 le: Septembre 28, 2013, 10:57:30 pm »
J'apprends le C++ et la SFML sur le tas donc j'ai encore pas mal de soucis :/

Voilà quand j'appuie sur une touche j'aimerai que ça lance un nouveau projectile mais faire appel au constructeur à chaque fois, c'est très lourd non ?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Problème d'intégration d'un thread dans une classe
« Réponse #8 le: Septembre 29, 2013, 09:30:15 am »
Pourquoi est-ce que ce serait très lourd ?

Au lieu de te poser tout un tas de questions, est-ce que tu as essayé de le faire ? Qu'est-ce qui a bloqué exactement ?

A mon avis tu devrais progresser encore un peu en C++ avant de chercher à faire des trucs compliqués. Là tu te crées des problèmes tout seul.
Laurent Gomila - SFML developer

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Re : Problème d'intégration d'un thread dans une classe
« Réponse #9 le: Septembre 29, 2013, 12:29:56 pm »
J'ai un peu repris le projectile.
Alors dès que j'appuie sur ma touche Espace le projectile repart de sa position initiale ce qui est normal car dans ma fonction update il y a un setPosition.
J'aimerai savoir comment faire pour qu'à chaque fois que j'appuie sur Espace un nouveau projectile soit créé et que ce ne soit pas le même à chaque fois qui revient à sa place ...

Le code :
Projectile projectile;

//gestion des events

if ( (event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Space) )
                {
                    projectile.Update();
                }

            }

// Fin de gestion des events
            projectile.Move(0, -0.1*timer);


void Projectile::Update()
{
    Projectile_Blue.setSize(sf::Vector2f(1, 1));
    Projectile_Blue.setPosition(0, 400);
    Projectile_Blue.setFillColor(sf::Color::Blue);
}

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Problème d'intégration d'un thread dans une classe
« Réponse #10 le: Septembre 29, 2013, 01:03:09 pm »
Il te faut un tableau dynamique de projectiles, dans lequel tu vas ajouter un nouvel élément à chaque fois que tu appuyes sur espace. Ensuite tu vas mettre à jour tous les projectiles en cours (ceux qui sont dans le tableau) -- et ne pas oublier de supprimer ceux qui sont arrivés en fin de vie.

Jette un oeil à la classe std::vector pour ton tableau dynamique.
Laurent Gomila - SFML developer

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Re : Problème d'intégration d'un thread dans une classe
« Réponse #11 le: Septembre 29, 2013, 06:18:10 pm »
J'ai fais ce que vous m'avez dit de faire.
Bon je suis confronté à un nouveau problème ...
Mon projectile n'avance pas ...

J'ai fais plusieurs tests comme récupérer la position de mon projectile mais le soucis c'est que cela ne correspond pas du tout à ce qui est affiché sur l'écran ...
Et mon projectile est bien affiché mais il reste fixe :/

Voici le code :

#include "ProjectileManager.h"

ProjectileManager::ProjectileManager()
{
    //ctor
}

ProjectileManager::~ProjectileManager()
{
    //dtor
}

void ProjectileManager::addProjectile()
{
    m_projectiles.push_back(Projectile());
}

void ProjectileManager::deleteProjectile()
{
    for (unsigned int i = 0; i < m_projectiles.size(); i++)
    if (m_projectiles[i].getPosition().y > 500)
        m_projectiles.erase(m_projectiles.begin() + i);
}

void ProjectileManager::moveProjectile(float &timer)
{
    for (unsigned int i = 0; i < m_projectiles.size(); ++i)
    {
        m_projectiles[i].move(10, 5 *timer);
        int y = m_projectiles[i].getPosition().y;
        int x = m_projectiles[i].getPosition().x;
        std::cout << x << " | " << y << std::endl;
    }
}

void ProjectileManager::displayProjectile(sf::RenderWindow& window)
{
    for (unsigned int i = 0; i < m_projectiles.size(); ++i)
        window.draw(m_projectiles[i]);
}
 

#ifndef PROJECTILEMANAGER_H
#define PROJECTILEMANAGER_H

#include <SFML/Graphics.hpp>
#include <iostream>
#include "Projectile.h"

class ProjectileManager
{
    public:
        ProjectileManager();
        ~ProjectileManager();

        void addProjectile();
        void deleteProjectile();
        void moveProjectile(float &timer);
        void displayProjectile(sf::RenderWindow& window);
    private:
        std::vector<Projectile> m_projectiles;
};

#endif // PROJECTILEMANAGER_H
 

#include "Scene.h"

sf::Clock horloge;
sf::Time tempsFrame;

Scene::Scene()
{
    sf::RenderWindow window(sf::VideoMode(), "Warrior Of Space", sf::Style::Fullscreen);
    window.setKeyRepeatEnabled(true);
    window.setFramerateLimit(60);

    sf::Texture image;
    if(!image.loadFromFile("Ressources/Background.png"))
       std::cout<<"Error"<<std::endl;
    sf::Sprite background(image);

    Spaceship spaceship;
    Gui gui(&spaceship);

    sf::View camera(sf::FloatRect(0, 0, 800, 600));
    ProjectileManager projectile;

    float timer;


    while (window.isOpen())
        {
            timer += m_tempsFrame.asSeconds();
            sf::Event event;
            while (window.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                window.close();

                if (event.type == sf::Event::Resized)
                {
                    sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height);
                    window.setView(sf::View(visibleArea));
                }

                if ( (event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape) )
                {
                    window.close();
                }


                if ( (event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Right) )
                {
                    spaceship.Move(5, 0);
                }
                if ( (event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Left) )
                {
                    spaceship.Move(-5, 0);
                }
                if ( (event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Z) )
                {
                    spaceship.addHealth(+5);
                }
                if ( (event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::A) )
                {
                    spaceship.addHealth(-5);
                }
                if ( (event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Space) )
                {
                    projectile.addProjectile();
                    projectile.moveProjectile(timer);
                }

            }



            window.clear();

            window.draw(background);
            window.draw(spaceship);
            projectile.displayProjectile(window);
            window.draw(gui);
            gui.Update(&spaceship);
            m_tempsFrame = m_horloge.restart();
            window.setView(camera);
            window.display();
        }
}
 

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Problème d'intégration d'un thread dans une classe
« Réponse #12 le: Septembre 29, 2013, 08:40:37 pm »
Comment ton projectile est-il censé avancer puisque tu n'appelles jamais moveProjectile après sa création ? ;)

Il faut l'appeler tout le temps, dans ta boucle principale avant de dessiner. Et avec le temps de la dernière frame, pas le temps cumulé, sinon ton projectile va aller de plus en plus vite et tu ne le verras pas longtemps. Donc, ta variable timer ne sert à rien.

Sinon, ta fonction deleteProjectile est mal implémentée. La boucle de suppression typique pour un std::vector est la suivante :

for (std::vector<T>::iterator it = v.begin(); it != v.end(); )
{
    if (...)
        it = v.erase(it);
    else
        ++it;
}

Comme ça l'itération n'est pas choucroutée lorsque tu supprimes un élement (avec ton code, l'élément suivant celui supprimé était sauté).
Laurent Gomila - SFML developer

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Re : Problème d'intégration d'un thread dans une classe
« Réponse #13 le: Octobre 05, 2013, 09:56:22 pm »
Bonsoir,


Après un peu de recherche j'ai réussi à faire bouger mes projectiles mais le soucis c'est que ça reste du virtuel.
Mon projectile avance d'après mon getPosition mais sur l'écran il reste à sa place ...

Le code :

void ProjectileManager::moveProjectile(float &timer, sf::RenderWindow& window)
{
    for (unsigned int i = 0; i < m_projectiles.size(); ++i)
    {
        m_projectiles[i].move(0, 1);
        int y = m_projectiles[i].getPosition().y;
        int x = m_projectiles[i].getPosition().x;
        std::cout << x << " | " << y << std::endl;
        window.draw(m_projectiles[i]);
       
    }
}

if ( (event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Space) )
                {
                    projectile.addProjectile();
                }
            }
            window.clear();
            window.draw(background);
            window.draw(rectangle);
            window.draw(spaceship);
            projectile.moveProjectile(timer, window);
            window.draw(gui);
            gui.Update(&spaceship);
            m_tempsFrame = m_horloge.restart();
            window.setView(camera);
            window.display();

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Re : Problème d'intégration d'un thread dans une classe
« Réponse #14 le: Octobre 15, 2013, 11:09:31 pm »
Bonsoir,

Je me permet de faire un up car je n'arrive vraiment pas à avancer avec ce problème :/