Partage
  • Partager sur Facebook
  • Partager sur Twitter

SFML Les entrées clavier

Sujet résolu
    20 janvier 2019 à 13:47:35

    Coucou,

    J'ai commencé la SFML depuis peu et j'apprends avec la documentation officielle, et j'ai un problème : j'ai un programme qui affiche un joueur que l'on peux déplacer avec Z Q S et D, le seul problème étant que le mouvement est saccadé (Comme lorsqu'on laisse une touche appuyé sur un éditeur de texte). Voici le programme :

    #include <SFML/Graphics.hpp>
    #include <SFML/System.hpp>
    #include <SFML/Window.hpp>
    #include <SFML/Audio.hpp>
    #include <math.h>
    #include <iostream>
    #include <cstdlib>
    
    using namespace sf;
    
    int main()
    {
    
    //---FENÊTRE---\\
    
    
    RenderWindow rWindow(VideoMode(900,700,64),"The CB",Style::Resize);
    Texture texture;
    
    
    //---SPR PLAYER---\\
    
    
    if(!texture.loadFromFile("Player.png"))
        return EXIT_FAILURE;
    Sprite sprPlayer(texture);
    rWindow.draw(sprPlayer);
    
    
    //---VARIABLES___\\
    
    float playerX=450;
    float playerY=350;
    Time y;
    Time t=milliseconds(10);
    
    
    
    
    sprPlayer.setPosition(playerX,playerY);
    
    Event event;
    while(rWindow.isOpen())
    {
        rWindow.pollEvent(event);
        switch(event.type)
        {
    
        //---TOUCHES CLAVIER---\\
    
        case Event::KeyPressed:
    
            switch (event.key.code)
            {
    
            case Keyboard::Z:
            playerY-=2;
            std::cout<<"Z"<<std::endl;
            break;
    
            case Keyboard::Q:
            playerX-=2;
            std::cout<<"Q"<<std::endl;
            break;
    
            case Keyboard::S:
            playerY+=2;
            std::cout<<"S"<<std::endl;
            break;
    
            case Keyboard::D:
            playerX+=2;
            std::cout<<"D"<<std::endl;
            break;
    
            }
        break;
    }
    
    
    
        sleep(t);
        rWindow.clear();
        sprPlayer.setPosition(playerX,playerY);
        rWindow.draw(sprPlayer);
        rWindow.display();
    }
        return EXIT_SUCCESS;
    }
    



    • Partager sur Facebook
    • Partager sur Twitter
      20 janvier 2019 à 16:08:47

      Hello,

      Oui c'est parce qu'il faut garder l'état des touches en mémoire en dehors de la boucle d'events et effectuer le mouvement dans la partie update du code.

      Sinon plusieurs choses :

      • je te déconseille d'utiliser la directive using namespace sf au risque d'avoir des suprises
      • le sleep(t) est complètement inutile ici et il ralentit le programme pour rien
      • set la position du jouer pendant le draw c'est pas cool ^^
      • pour des déplacement uniforme au temps d'éxecution, il faut mulitplier la vitesse par le temps d'exécution d'une frame (enfin ça c'est un minimum vital, il y a des techniques plus complexe et plus sûr)

      Un petit code d'exemple :

      #include <SFML/Graphics.hpp>
      #include <map>
      
      /////////////////////////////////// MAIN
      int main()
      {
          ///////////////// WINDOW
          const unsigned WINDOW_WIDTH{800};
          const unsigned WINDOW_HEIGHT{600};
          sf::RenderWindow window{sf::VideoMode{WINDOW_WIDTH, WINDOW_HEIGHT}, "Brouillon_SFML"};
      
          ///////////////// RESSOURCES
          sf::RectangleShape player{sf::Vector2f{32.f, 32.f}};
          const float speed{350};
          std::map<std::string, bool> keysState{
              {"Z", false},
              {"Q", false},
              {"S", false},
              {"D", false}
          };
          sf::Clock clock{};
          sf::Time dt{};
      
          ///////////////// GAME LOOP
          while(window.isOpen())
          {
              sf::Event event{};
              ///////////////// EVENTS LOOP
              while(window.pollEvent(event))
              {
                  if(event.type == sf::Event::KeyPressed){
                      if(event.key.code == sf::Keyboard::Z) keysState["Z"] = true;
                      if(event.key.code == sf::Keyboard::Q) keysState["Q"] = true;
                      if(event.key.code == sf::Keyboard::S) keysState["S"] = true;
                      if(event.key.code == sf::Keyboard::D) keysState["D"] = true;
                  }
      
                  if(event.type == sf::Event::KeyReleased){
                      if(event.key.code == sf::Keyboard::Z) keysState["Z"] = false;
                      if(event.key.code == sf::Keyboard::Q) keysState["Q"] = false;
                      if(event.key.code == sf::Keyboard::S) keysState["S"] = false;
                      if(event.key.code == sf::Keyboard::D) keysState["D"] = false;
      
                      if(event.key.code == sf::Keyboard::Escape){
                          window.close();
                      }
                  }
      
                  if(event.type == sf::Event::Closed){
                      window.close();
                  }
              }
      
              ///////////////// UPDATE
              // retourne le temps d'exécution d'une frame
              dt = clock.restart();
      
              sf::Vector2f movement{0.f, 0.f};
              // Distance relative au temps d'execution d'une frame -> d = (v*t)
              if(keysState["Z"]) movement.y -= speed*dt.asSeconds();
              if(keysState["Q"]) movement.x -= speed*dt.asSeconds();
              if(keysState["S"]) movement.y += speed*dt.asSeconds();
              if(keysState["D"]) movement.x += speed*dt.asSeconds();
      
              player.move(movement);
      
              ///////////////// DRAW
              window.clear();
              window.draw(player);
              window.display();
          }
      
          return 0;
      }

      -
      Edité par Guit0Xx 20 janvier 2019 à 16:22:38

      • Partager sur Facebook
      • Partager sur Twitter

      ...

        20 janvier 2019 à 19:51:48

        Coucou, merci pour la réponse qui (du moins, si le reste du code suit) fonctionne, mais voilà : je ne voulais pas recopier le code car je ne connaissais pas certaine notions (en cas de pépins je serais perdu sinon ^^'), alors j'ai fait ceci en me basant GRANDEMENT sur ton code ;) mais il reste un problème, rien ne s'affiche :/

        #include <SFML/Graphics.hpp>
        #include <SFML/System.hpp>
        #include <SFML/Window.hpp>
        #include <SFML/Audio.hpp>
        #include <math.h>
        #include <iostream>
        #include <cstdlib>
        
        
        int main()
        {
        
        //---FENÊTRE---\\
        
        sf::RenderWindow rWindow(sf::VideoMode(900,700,64),"The CB",sf::Style::Resize);
        sf::Texture texture;
        
        //---SPR PLAYER---\\
        
        if(!texture.loadFromFile("Player.png"))
            return EXIT_FAILURE;
        sf::Sprite sprPlayer(texture);
        rWindow.draw(sprPlayer);
        
        //---VARIABLES___\\
        
        bool pressZ,pressQ,pressS,pressD=false;
        sf::Event event;
        sf::Clock clock;
        sf::Time dt;
         float xBis=300;
         float yBis=300;
        //---SETTINGS---\\
        
        sprPlayer.setPosition(300,300);
        rWindow.draw(sprPlayer);
        
        //---BOUCLE G---\\
        
        while(rWindow.isOpen())
        {
        
            //---EVENT---\\
        
            while(rWindow.pollEvent(event))
            {
        
                //---CLAVIER---\\
        
                    //---TOUCHES PRESSEES---\\
        
                if(event.type == sf::Event::KeyPressed)
                {
                    if(event.key.code == sf::Keyboard::Z) {pressZ=true;std::cout<<"Z PRESS"<<std::endl;}
                    if(event.key.code == sf::Keyboard::Q) {pressQ=true;std::cout<<"Q PRESS"<<std::endl;}
                    if(event.key.code == sf::Keyboard::S) {pressS=true;std::cout<<"S PRESS"<<std::endl;}
                    if(event.key.code == sf::Keyboard::D) {pressD=true;std::cout<<"D PRESS"<<std::endl;}
                }
        
                    //---TOUCHES RELACHEES---\\
        
                if(event.type == sf::Event::KeyReleased)
                {
                    if(event.key.code == sf::Keyboard::Z) {pressZ=false;std::cout<<"Z RELEASE"<<std::endl;}
                    if(event.key.code == sf::Keyboard::Q) {pressQ=false;std::cout<<"Q RELEASE"<<std::endl;}
                    if(event.key.code == sf::Keyboard::S) {pressS=false;std::cout<<"S RELEASE"<<std::endl;}
                    if(event.key.code == sf::Keyboard::D) {pressD=false;std::cout<<"D RELAESE"<<std::endl;}
                }
        
        
        
        
        
            }
        
            //---UPDATE---\\
        
            dt = clock.restart();
        
            if(pressD)xBis -=200*dt.asSeconds();
            if(pressZ)yBis +=200*dt.asSeconds();
            if(pressQ)xBis +=200*dt.asSeconds();
            if(pressS)yBis -=200*dt.asSeconds();
        
            sprPlayer.move(xBis,yBis);
        
            //---AFFICHAGE---\\
        
            rWindow.clear();
            rWindow.draw(sprPlayer);
            rWindow.display();
        }
            return EXIT_SUCCESS;
        }
        



        -
        Edité par DeveCout 20 janvier 2019 à 19:53:00

        • Partager sur Facebook
        • Partager sur Twitter
          20 janvier 2019 à 21:04:32

          Les draw(...) n'ont rien à faire ici :

          // ...
           
          if(!texture.loadFromFile("Player.png"))
              return EXIT_FAILURE;
          sf::Sprite sprPlayer(texture);
          rWindow.draw(sprPlayer); // A RETIRER !!!!!!!!!!!!!
            
          // ...
           
          sprPlayer.setPosition(300,300);
          rWindow.draw(sprPlayer); // A RETIRER !!!!!!!!!!!!!
           
          //---BOUCLE G---\\
           
          while(rWindow.isOpen())
          
          // ...

          Un draw par tour c'est suffisant :) :

          //---AFFICHAGE---\\
           
          rWindow.clear();
          rWindow.draw(sprPlayer); // OK 1 seul draw suffit
          rWindow.display();

          -
          Edité par Guit0Xx 20 janvier 2019 à 21:05:26

          • Partager sur Facebook
          • Partager sur Twitter

          ...

            20 janvier 2019 à 21:39:09

            J'ai retiré les draw(...) en trop mais il y a toujours un gros bug : Rien ne s'affiche :/ et je ne comprend pas pourquoi?
            • Partager sur Facebook
            • Partager sur Twitter
              20 janvier 2019 à 22:24:53

              En fait si, il y a un affichage mais si on regarde attentivement ton code, on voit que même si une touche n'est pas appuyée, le personnage avance (très très vite) et du coup il sort de l'écran  à peine la fenêtre lancée.

              Dans un premier temps, les booléens représentant l'état des touches sont mals initialisés, prend l'habitude d'initialiser une variable par ligne :

              bool pressZ{false};
              bool pressQ{false};
              bool pressS{false};
              bool pressD{false};

              Ensuite les variables xBis et yBis ne servent à rien (c'est d'ailleurs la cause qui fait que ton personnage sort de l'écran) :

              float xBis=300; // À virer
              float yBis=300; // À virer

              Aussi tu t'es emmêlé les pinceaux au niveau du mouvement :

              • Z -> On monte (mouvement y négatif)
              • Q -> On va à gauche (mouvement x négatif)
              • S -> On descend (mouvement y positif)
              • D -> On va à droite (mouvement x positif)
              Du coup ça donne ça :
              float distance_x{0.f};
              float distance_y{0.f};
              
              if(pressZ) distance_y -= 200*dt.asSeconds();
              if(pressQ) distance_x -= 200*dt.asSeconds();
              if(pressS) distance_y += 200*dt.asSeconds();
              if(pressD) distance_x += 200*dt.asSeconds();
              
              sprPlayer.move(distance_x, distance_y);

              À la place des tes 2 variables xBis et yBis, suffit d'initialiser 2 variables x et y représentant la distance de déplacement juste avant de calculer celle-ci selon la touche appuyée.

              -
              Edité par Guit0Xx 20 janvier 2019 à 22:28:15

              • Partager sur Facebook
              • Partager sur Twitter

              ...

                20 janvier 2019 à 22:55:37

                Pourtant même en aillant suivit tes instructions (à savoir : retirer xBis et yBis, copier les conditions pour les touches pressées, et initialisé correctement mes variables), l'affichage reste noir, là par contre je suis perdu, si tu lance le programme sur ton PC, tu as un résultats?

                Code (au cas ou):

                #include <SFML/Graphics.hpp>
                #include <SFML/System.hpp>
                #include <SFML/Window.hpp>
                #include <SFML/Audio.hpp>
                #include <math.h>
                #include <iostream>
                #include <cstdlib>
                
                
                int main()
                {
                
                //---FENÊTRE---\\
                
                sf::RenderWindow rWindow(sf::VideoMode(900,700,64),"The CB",sf::Style::Resize);
                sf::Texture texture;
                
                //---SPR PLAYER---\\
                
                if(!texture.loadFromFile("Player.png"))
                    return EXIT_FAILURE;
                sf::Sprite sprPlayer(texture);
                
                //---VARIABLES---\\
                
                bool pressZ=false;
                bool pressQ=false;
                bool pressS=false;
                bool pressD=false;
                sf::Event event;
                sf::Clock clock;
                sf::Time dt;
                
                //---SETTINGS---\\
                
                sprPlayer.setPosition(300,300);
                
                //---BOUCLE G---\\
                
                while(rWindow.isOpen())
                {
                
                    //---EVENT---\\
                
                    while(rWindow.pollEvent(event))
                    {
                
                        //---CLAVIER---\\
                
                            //---TOUCHES PRESSEES---\\
                
                        if(event.type == sf::Event::KeyPressed)
                        {
                            if(event.key.code == sf::Keyboard::Z) {pressZ=true;std::cout<<"Z PRESS"<<std::endl;}
                            if(event.key.code == sf::Keyboard::Q) {pressQ=true;std::cout<<"Q PRESS"<<std::endl;}
                            if(event.key.code == sf::Keyboard::S) {pressS=true;std::cout<<"S PRESS"<<std::endl;}
                            if(event.key.code == sf::Keyboard::D) {pressD=true;std::cout<<"D PRESS"<<std::endl;}
                
                        }
                
                            //---TOUCHES RELACHEES---\\
                
                        if(event.type == sf::Event::KeyReleased)
                        {
                            if(event.key.code == sf::Keyboard::Z) {pressZ=false;std::cout<<"Z RELEASE"<<std::endl;}
                            if(event.key.code == sf::Keyboard::Q) {pressQ=false;std::cout<<"Q RELEASE"<<std::endl;}
                            if(event.key.code == sf::Keyboard::S) {pressS=false;std::cout<<"S RELEASE"<<std::endl;}
                            if(event.key.code == sf::Keyboard::D) {pressD=false;std::cout<<"D RELAESE"<<std::endl;}
                        }
                
                
                
                    }
                
                    //---UPDATE---\\
                
                    dt = clock.restart();
                
                float distance_x{0.f};
                float distance_y{0.f};
                
                if(pressZ) distance_y -= 200*dt.asSeconds();
                if(pressQ) distance_x -= 200*dt.asSeconds();
                if(pressS) distance_y += 200*dt.asSeconds();
                if(pressD) distance_x += 200*dt.asSeconds();
                
                sprPlayer.move(distance_x, distance_y);
                
                    //---AFFICHAGE---\\
                
                
                    rWindow.draw(sprPlayer);
                     rWindow.clear();
                    rWindow.display();
                }
                    return EXIT_SUCCESS;
                }
                

                Merci quand même : tu m'aura déjà bien aidé pour apprendre à comprendre les Event clavier ;)

                • Partager sur Facebook
                • Partager sur Twitter
                  20 janvier 2019 à 23:13:44

                  Oui là c'est parce que tu as inversé l'ordre des opérations au niveau du draw, dans l'ordre c'est :

                  • clear
                  • draw
                  • display

                  Dans tons code tu as placé le clear() après le draw() donc forcément on se retrouve avec une fenêtre vide ^^.

                  Autre chose, j'me fait hurler dessus par mon compilo à cause de la forme de tes commentaires, un conseil évite de mettre des antislash en fin de ligne commentée.

                  Dernière petite chose, ça :

                  pressZ=true;std::cout<<"Z PRESS"<<std::endl;

                  On évite ! Une instruction par ligne maximum. Là tu en as 2.

                  -
                  Edité par Guit0Xx 20 janvier 2019 à 23:16:45

                  • Partager sur Facebook
                  • Partager sur Twitter

                  ...

                    21 janvier 2019 à 0:31:10

                    MMEERRCCII!!! :D Ca marche!! Je n'étais jamais arrivés à quelque chose d'aussi correct dans un programme merci ^^!
                    • Partager sur Facebook
                    • Partager sur Twitter
                      21 janvier 2019 à 0:34:14

                      No problemo ;).

                      À bientôt.

                      • Partager sur Facebook
                      • Partager sur Twitter

                      ...

                      SFML Les entrées clavier

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                      • Editeur
                      • Markdown