Forum de la communauté SFML

Aide => Fenêtrage => Discussion démarrée par: yusera le Avril 17, 2012, 10:53:11 pm

Titre: Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 17, 2012, 10:53:11 pm
Bonjour,

Alors voilà tout d'abord je ne sais pas si ce post est à mettre dans la partie Graphique ou Fenêtre mais j'ai choisi le forum Fenêtrage car le problème est en lien avec ceci.

Donc j'ai un problème lorsque je clique sur la barre de la fenêtre ou lorsque je la déplace. En effet, je gère la collision d'un sprite et lorsque je fais une des 2 actions ci-dessus, le système de collision est comme "endormi" c'est-à-dire qu'il ne marche plus jusqu'à ce que j’arrête de cliquer ou déplacer la fenêtre.
Voici un code qui fait cela :

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

int main()
{
        sf::RenderWindow App(sf::VideoMode(800, 600, 32), "SFML Window");

        sf::Image Image, image2;
        if (!Image.LoadFromFile("test.png"))
                return EXIT_FAILURE;

        image2.LoadFromFile("test2.png");

        sf::Sprite Sprite(Image);
        //Sprite.SetBlendMode(sf::Blend::None);
        Sprite.SetPosition(200.f, 500.f);

        int ok = 0;
        int descente = 0;
        int v = 0;

        sf::Image BackgroundImage;
    if (!BackgroundImage.LoadFromFile("background.jpg"))
        return EXIT_FAILURE;

        while (App.IsOpened())
        {
                sf::Event Event;
                while (App.GetEvent(Event))
                {
                        if (Event.Type == sf::Event::Closed)// Fenêtre fermée
                                App.Close();
                        if(Event.Type == sf::Event::KeyPressed && Event.Key.Code == sf::Key::Up)
                                ok = 1;
                        if(Event.Type == sf::Event::KeyPressed && Event.Key.Code == sf::Key::Down)
                        {
                                sf::Sprite s;
                                s.SetImage(image2);
                                Sprite = s;
                        }
                }

               
                float ElapsedTime = App.GetFrameTime();
               
                if (App.GetInput().IsKeyDown(sf::Key::Right)) Sprite.Move( 110 * ElapsedTime, 0);
                if (App.GetInput().IsKeyDown(sf::Key::Left)) Sprite.Move( -110 * ElapsedTime, 0);

                if(ok == 1)
                {
                        if(descente == 0)
                        {
                                if(Sprite.GetPosition().y > 425)
                                {
                                        Sprite.Move(0, (-100+v) * ElapsedTime);
                                        v -= 1;
                                }
                                else
                                {
                                        descente = 1;
                                }
                        }
                        else
                        {
                                if(Sprite.GetPosition().y < 500)
                                {
                                        Sprite.Move(0, (100+v) * ElapsedTime);
                                        v += 1;
                                }
                                else
                                {
                                        descente = 0;
                                        ok = 0;
                                        v = 0;
                                }
                        }
                               
                }

                App.Clear();

                App.Draw(Sprite);

                App.Display();
        }

        return EXIT_SUCCESS;
}
 
C'est un code que j'avais fait pour tester la SFML pour la première fois.
Savez-vous comment régler le problème car, à moins d'imposer le fullscreen, si l'utilisateur bouge la fenêtre le sprite et les pnj du jeu passeront à travers les murs ?

Merci.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Laurent le Avril 18, 2012, 08:18:40 am
Il n'y a pas que les collisions qui sont bloquées, c'est tout ton thread principal qui l'est. La seule façon de continuer à tourner pendant le déplacement / redimensionnement de la fenêtre, c'est d'avoir du code dans un autre thread que celui qui gère les évènements.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 18, 2012, 09:59:01 am
Oui enfin là c'était pour l'exemple et merci pour la précision.
Mais dans ce cas, pour que l'application continue normalement, dois-je copier le thread principal dans le thread secondaire ? Et faut-il l'activer dès que le thread principal est bloqué (si on peut savoir) ?

EDITE: Ou peut-être faut il juste appeler la fonction collision et l'associer au thread secondaire ?
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Laurent le Avril 18, 2012, 10:30:09 am
Après tu t'organises comme tu veux, ça dépend de ton application, mais en gros la c'est la fonction GetEvent qui va bloquer ; donc tout ce que tu veux qui ne bloque pas, il faut que ce soit dans un autre thread que celui qui appelle GetEvent.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 18, 2012, 11:11:31 am
OK merci !
En fait, je dois faire "tourner" le thread secondaire tout le temps ?

J'ai une dernière question :
Est ce que le fait de faire une classe Thread secondaire fait la même chose que créer un sf::Thread et d'appeler une fonction qui  tourne en boucle du type :
void Fonction(void* UserData)
{
    bool value(true);
    while(value)
    {
        // Si on veut arreter la boucle
        value = false;
    }
}
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Laurent le Avril 18, 2012, 11:15:39 am
J'ai pas très bien compris ta question.

Mais est-ce que tu es à l'aise avec les threads ? C'est un peu dangereux de les utiliser sans bien maîtriser le sujet -- même si je sais bien que c'est la seule solution pour régler ce problème-là.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 18, 2012, 11:35:56 am
À vrai dire, je ne m'en suis jamais servi.
En fait si j'ai bien compris son principe, il permet de faire d'autres instructions en même temps que le thread principal.
Mais dans les exemples du tutoriel, il ne fait qu'afficher 10 fois "Je suis le thread numero 1". Or je veux l'utiliser pour gérer les collisions, donc je dois bien le faire tourner en boucle vu que l'on appelle qu'une seule fois la fonction Launch() ?
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Laurent le Avril 18, 2012, 12:25:17 pm
Oui c'est ça, ton thread secondaire doit boucler indéfiniment, de manière parallèle à la boucle d'évènements.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 18, 2012, 02:38:57 pm
Merci pour la réponse !
Mais comment fait-on pour passer un paramètre à la fonction car j'aimerai qu'elle est accès au sf::RenderWindow ? J'ai du mal à utiliser le code du tutoriel suivant :
void ThreadFunction(void* UserData)
{
    // Transtypage du paramètre en son type réel
    MyClass* Object = static_cast<MyClass*>(UserData);
}

En gros, je devrais faire :
int Classe::Run(sf::RenderWindow &App)
{
        Running = true;
        sf::Thread Thread(&ThreadFonction, &App);
        Thread.Launch();

        while(Running)
        {
       
        }
        //....
}

void Classe::ThreadFonction(void *UserData)
{
        sf::RenderWindow* App = static_cast<sf::RenderWindow*>(UserData);
        while(Running)
        {
       
        }
}
 

Mais ça ne marche pas, j'ai une erreur :
error C2276: '&' : opération non conforme sur l'expression d'une fonction membre liée
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Laurent le Avril 18, 2012, 02:48:46 pm
Lis le tutoriel, c'est expliqué.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 18, 2012, 03:15:01 pm
C'est ce que j'ai fait mais là je trouve pas ... Ça bloque ici:
sf::Thread Thread(&ThreadFonction, &App);
Avec l'erreur sur mon post précédent.

Faut-il obligatoirement que la fonction ThreadFonction(void* UserData) soit globale ?
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Laurent le Avril 18, 2012, 03:22:55 pm
Il faut utiliser ll'approche décrite dans le paragraphe "Utilisation de sf::Thread en tant que classe de base". La première approche ne marche que pour les fonctions non-membres.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 18, 2012, 05:00:31 pm
Merci beaucoup !
Et donc vu que je gère le déplacement du personnage & ceux des pnj, je dois utiliser des pointeurs dans le thread pour qu'ils pointent vers le perso, les pnj et le sf::RenderWindow pour les utiliser ?
Ça me parait être le seul moyen ...
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Laurent le Avril 18, 2012, 05:03:19 pm
Pas forcément, tu peux accéder à n'importe quelle variable depuis un thread, pas besoin de lui passer en paramètre.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 19, 2012, 10:23:48 am
Oui mais dans mon cas, j'utilise cette methode (http://www.sfml-dev.org/wiki/fr/tutoriels/multiecransjeu) pour gérer un menu, l'interface de jeu etc...
Et donc de cette façon, je devrais hériter la classe Screen de sf::Thread ? Car au début, j'étais parti pour créer un membre sf::Thread d'une classe Jeu qui hérite de Screen. Or dans ce cas là, je ne pouvais pas accéder aux autres membres de la classe Jeu (c'est à dire le personnage, les pnj ...)
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Laurent le Avril 19, 2012, 10:30:51 am
De toute façon oui, avec SFML 1.6 tu es obligé de faire dériver de sf::Thread la classe qui "fait les trucs threadés".
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 19, 2012, 10:44:12 am
Pas avec SFML 2.0 ?
Merci pour tes réponse ! Je vais essayer comme ça.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Laurent le Avril 19, 2012, 12:13:43 pm
Avec SFML 2 déjà tu ne dérives plus de sf::Thread.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 19, 2012, 03:07:08 pm
OK mais j'ai encore un problème. Y a t'il une solution pour envoyer un sf:RenderWindow en paramètre pour la classe qui hérite de sf::Thread ? Car les "Screen" ont pour fonction virtual int Run(sf::RenderWindow &App) = 0;
Or si je tappe:
sf::RenderWindow App(...);
Screen t;
t.Run(App);
Ça ne va pas lancer le thread car ça ne marche pas, le programme arrête totalement de fonctionner lorsque qu'on bouge la fenêtre...
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Laurent le Avril 19, 2012, 03:17:25 pm
Tu veux faire ça ?
// ça c'est le point d'entrée public
void Screen::Run(sf::RenderWindow& window)
{
    m_window = &window;
    Launch();
}

// et ça c'est la fonction threadée
void Screen::Run()
{
    // use m_window ...
}
 
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 19, 2012, 05:26:48 pm
Oui, c'est simple en fait mais j'ai une erreur lorsque l'attribut sf::RenderWindow de la classe Screen fait réference à sf::RenderWindow& window :
error C2758: 'Screen::App' : doit être initialisé(e) dans la liste des initialiseurs base/membre du constructeur
// Screen.hpp
class Screen : public sf::Thread
{
        public :
                Screen();
                int Run(sf::RenderWindow &window);
               
        protected :
                sf::RenderWindow &App;
                int exit;
};

// Screen.cpp
Screen::Screen() : exit(-1)
{

}

int Screen::Run(sf::RenderWindow &window)
{
        App = window;
        Launch();

        return exit;
}
 

J'ai tenté d'initialiser sf::RenderWindow App dans le constructeur en mettant: App(sf::RenderWindow()) mais ça ne marche pas.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Laurent le Avril 19, 2012, 06:16:41 pm
Tu ne peux pas "binder" une référence après sa construction, c'est pourquoi j'ai utilisé un pointeur dans mon exemple.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 20, 2012, 09:01:09 pm
En effet, j'avais oublié.
Je te répondrai plus en détail plus tard car il y a encore quelques problèmes etje n'ai pas le temps ce week-end.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 26, 2012, 07:19:29 pm
Alors me revoilà.
Donc en fait il y a un problème de pointage, c'est-à-dire que lorsque je crée une classe Jeu qui hérite de Screen avec pour fonction virtual void Run(), l'attribut hérité de Screen (sf::RenderWindow *App) ne "marche" pas dans la fonction héritée.

Il y a comme un problème de pointage avec le sf::RenderWindow App(sf::VideoMode(1024, 768, 32), "Nouveau Jeu", sf::Style::Close) du main puisque par exemple lorsque j'appelle GetWidth() de sf::RenderWindow, aucune valeur n'est renvoyée ...

De plus, rien n'est affiché à l'écran.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Laurent le Avril 26, 2012, 09:05:30 pm
Citer
aucune valeur n'est renvoyée
Ca veut dire quoi ? Ca crashe ? Ca renvoie zéro ? Du caca ?

Le code est-il suffisamment petit pour que tu puisses nous le montrer (au moins en partie) ?
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 26, 2012, 11:18:05 pm
Ça ne crash pas mais si je veux afficher la valeur avec cout :
cout << App->GetWidth() << endl;
Aucune valeur n'est affichée alors que si je place ce bout de code dans la fonction Run(sf::RenderWindow &App) qui est déclarée dans la classe Screen, ça affiche bien la longueur de la fenêtre (ici 1024)

Voilà un bout de code :
class Screen : public sf::Thread
{
        public :
                Screen();
                int Run(sf::RenderWindow &window);
                //int GetExit();
                //virtual void Run();
               
        protected :
                sf::RenderWindow *App;
                int exit;

        //private :
                //virtual void Run() = 0;
};
Screen::Screen() : exit(-3)
{

}

int Screen::Run(sf::RenderWindow &window)
{
        App = &window;
        Launch();

        while(exit == -3);

        return exit;
}
void Jeu::Run()
{
        bool Running(true);
        sf::Event Event;

        while(Running)
        {
                while(App->GetEvent(Event))
                {
                        if(Event.Type == sf::Event::Closed)

                                exit = SCREEN_EXIT;
                        if(Event.Type == sf::Event::KeyPressed)
                        {
                                switch(Event.Key.Code)
                                {
                                        case sf::Key::Escape:
                                                exit = SCREEN_MENU;
                                                break;
                                }
                        }
                }
               
                if(exit != -3)
                        Running = false;

                // Affichage
                App->Clear(sf::Color(0, 255, 0));
                App->Display();
        }

        exit = SCREEN_EXIT;
}
 
Et la fonction main :
int main(int argc, char** argv)
{
        sf::RenderWindow App(sf::VideoMode(1024, 768, 32), "Nouveau Jeu", sf::Style::Close);//|sf::Style::Fullscreen);
        //sf::RenderWindow App(sf::VideoMode(800, 600, 32), "Nouveau Jeu", sf::Style::Close);

        // Vue
        sf::View view(sf::FloatRect(0, 0, 1024, 768));
        App.SetView(view);

        // Menu/Jeu/Options
        std::vector<Screen*> screens;
        int screen = 0;

        Jeu s_jeu; // Creation d'un affichage pour le jeu
        screens.push_back(&s_jeu);

        while(screen >= 0)
        {
                screen = screens[screen]->Run(App);
        }

        return EXIT_SUCCESS;
}
 

Une remarque :
Par rapport à la ligne while(exit == -3);, ça ne fonctionne pas comme je veux donc ne la prend pas en compte, c'est juste pour ne pas répéter la boucle du main.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Laurent le Avril 26, 2012, 11:37:13 pm
Donc en fait Jeu::Run() n'est pas du tout appelé ? C'est ça ?
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 27, 2012, 05:31:28 pm
Si si puisque un cout << "text" << endl; dans la fonction Run() affiche correctement le texte dans la console. C'est le pointeur sf::RenderWindow *App qui a un problème car le fait d'afficher un fond rouge
App->Clear(sf::Color(0, 255, 0));
App->Display();
ne marche pas puisqu'il y a un écran noir.

De plus, App->GetEvent(Event) renvoie toujours false car la boucle while(App->GetEvent(Event)) de la fonction Run() n'est jamais lancé. Donc j'en déduit qu'il y a un problème de pointage ... Et je ne comprends pas pourquoi ça ne marche pas
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Laurent le Avril 27, 2012, 07:33:46 pm
T'es sûr que tu n'as pas une autre instance de sf::RenderWindow, non initialisée, qui traîne quelque part et qui pourrait être pointée à la place de la bonne instance ?
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 28, 2012, 01:41:30 pm
Je suis sûr. En fait, ça vient du fait que la classe jeu hérite de Screen car dans la fonction Run(sf::RenderWindow &window) de Screen, si j’ajoute:
App->Clear(sf::Color(255, 0, 0));
App->Display();
La fenêtre devient rouge alors que ça ne marche pas dans la classe Jeu ...
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Koryushin le Avril 28, 2012, 07:13:46 pm
Si jeu hérite de screen alors tu as 2 prototypes différents de run().

Il faut que la méthode run() de jeu est le même prototype que celui de screen non ?
int Run(sf::RenderWindow &window);
sinon la méthode run() de jeu n'est jamais appelée.

j'ai lu le thread en travers mais rejette un oeil au tuto du wiki
https://github.com/SFML/SFML/wiki/TutorialScreens (https://github.com/SFML/SFML/wiki/TutorialScreens)
et adapte en conséquences
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Laurent le Avril 28, 2012, 08:08:48 pm
Run(sf::RenderWindow&) n'est pas virtuelle, elle lance le thread qui lui va appeller Run().
Titre: Re : Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 28, 2012, 10:03:56 pm
Run(sf::RenderWindow&) n'est pas virtuelle, elle lance le thread qui lui va appeller Run().
Oui et j'avais testé avec un cout dans la fonction Run() de Jeu pour voir si elle était bien appelée, ce qui est le cas.
Je ne sais pu trop quoi faire pour résoudre le problème  :-\
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 28, 2012, 10:19:41 pm
Je vais passer bientôt à la SFML 2.0, ça réglera peut-être le problème ?
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: Laurent le Avril 28, 2012, 10:39:14 pm
Peut-être, peut-être pas ;)

Mais je ne pense pas, étant donné que ça sent quand même le problème dans ton code et non dans SFML.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Avril 29, 2012, 12:55:54 pm
Alors voilà, j'ai réussi à afficher le sf::RenderWindow mais avec un thread différent :

#include <SFML/Graphics.hpp>
#include "all_screens.hpp"

Engine::Engine(sf::RenderWindow &w) : App(w)
{

}

void Engine::Run()
{
        App.Create(sf::VideoMode(1024, 768, 32), "Nouveau Jeu", sf::Style::Close);

        // Vue
        sf::View view(sf::FloatRect(0, 0, 1024, 768));
        App.SetView(view);

        // Menu/Jeu/Options

        Menu s_menu; // Creation d'un menu
        screens.push_back(&s_menu);
        Jeu s_jeu; // Creation d'un affichage pour le jeu
        screens.push_back(&s_jeu);
        int screen(0);

        while(screen >= 0)
        {
                cout << screen << endl;
                screen = screens[screen]->Run(App);
        }
}

int main(int argc, char** argv)
{
        sf::RenderWindow Window;
        Engine App(Window);
        App.Launch();
        sf::Clock c;

        while(c.GetElapsedTime() < 20);

        return EXIT_SUCCESS;
}

#ifndef HEADER_ALL_SCREENS
#define HEADER_ALL_SCREENS

#include "Screen.hpp"

// Screens :
#include "Menu.hpp"
#include "Jeu.hpp"

class Engine : public sf::Thread
{
        public :
                Engine(sf::RenderWindow &w);
                virtual void Run();

        private :
                sf::RenderWindow &App;
                std::vector<Screen*> screens;
};

#endif

Et la fonction Run de Menu et Jeu :
int Menu::Run(sf::RenderWindow &w)
{
        sf::RenderWindow &App = w;
        // ....
}
 

Donc tout s'affiche correctement, le seul problème est que ce que le problème initial (le sujet de la discussion) n'est pas résolu. Lorsque je clique, déplace la fenêtre, le programme s'arrête toujours et donc dans mon cas, les collisions (le plus important actuellement) sont ignorées.
Titre: Re : Problème lors du déplacement de la fenêre
Posté par: yusera le Mai 02, 2012, 01:39:58 pm
Pas de réponse ?