2015-08-31 3 views
0

Chaque fois que j'appuie sur une touche pour déplacer une image-objet, l'écran ne se met pas à jour tant que je n'ai pas relâché la touche. La seule façon dont j'ai pu résoudre ce problème est d'effacer, dessiner et afficher la fenêtre dans chaque boucle KeyPressed.La fenêtre cesse d'être rafraîchie lorsque la touche est enfoncée

Il est beaucoup plus logique de faire chacune de ces choses une fois, indépendamment de toute pression sur une touche. Je ne sais pas pourquoi cela ne fonctionne pas, ou quelle serait la meilleure façon de régler cela.

Dans le programme ci-dessous, j'ai affiché le code d'effacement/affichage/affichage dans plusieurs endroits différents en espérant que le mettre au bon endroit fonctionnera. Jusqu'à présent, ce n'est pas le cas. La redondance est par ailleurs inutile.

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

using namespace std; 

int main() 
{ 
int windowx = 800; 
int windowy = 600; 

float playerx = 400.0; 
float playery = 300.0; 

sf::Sprite playersprite; 
sf::Sprite enemysprite; 

float playerspeedx = 0; 
float playerspeedy = 0; 

float playerspeedx2 = 0; 
float playerspeedy2 = 0; 

float accelerationx = 50.0; 
float accelerationy = 50.0; 
float deccelerationx = 50.0; 
float deccelerationy = 50.0; 
float frictionx = 25.0; 
float frictiony = 25.0; 
float playermaxspeedx = 500.0; 
float playermaxspeedy = 200.0; 

sf::Texture hoverdrone; //player's sprite 
if (!hoverdrone.loadFromFile("hoverdrone.png")) 
    { 
     cout << "error loading image"; 
    } 
sf::Texture floatdrone; //for sprite enemysprite 
    if (!floatdrone.loadFromFile("floatdrone.png")) 
    { 
     cout << "error loading image"; 
    } 

    playersprite.setTexture(hoverdrone); 
    enemysprite.setTexture(floatdrone); 
    enemysprite.setPosition(sf::Vector2f(400, 400)); 
    playersprite.setPosition(sf::Vector2f(400, 300)); 


sf::RenderWindow mywindow(sf::VideoMode(windowx, windowy), "FishTank"); 

//sf::Clock clock; //Begin clock. 
//sf::Int32 baseclock = clock.getElapsedTime().asMilliseconds(); 

// run the program as long as the window is open 
while (mywindow.isOpen()) 
{ 
    // check all the window's events that were triggered since the last iteration of the loop 
    sf::Event event; 

    while (mywindow.pollEvent(event)) 
    { 
     // "close requested" event: we close the window 
     if (event.type == sf::Event::Closed) 
      { 
       cout <<"You have closed the window."<<endl; 
       mywindow.close(); 
      } 
     mywindow.clear(sf::Color::Black); 
     mywindow.draw(playersprite); 
     mywindow.draw(enemysprite); 
     playersprite.setPosition(sf::Vector2f(playerx, playery)); 
     mywindow.display(); 
     sf::sleep(sf::microseconds(5)); 

     // left key is pressed: move our character 
     if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) 
      { 
       sf::Clock leftclock; 

       while (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) 
       { 
        playerx -= 0.01; //will replace later with time based movement 
        sf::Int32 leftclock1 = leftclock.getElapsedTime().asMilliseconds(); 
        cout << leftclock1 << endl; 

        /*mywindow.clear(sf::Color::Black); 
        mywindow.draw(playersprite); 
        mywindow.draw(enemysprite); 
        playersprite.setPosition(sf::Vector2f(playerx, playery)); 
        mywindow.display();*/ 

       } 

      } 
     // right key is pressed: move our character 
     if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) 
      { 
       sf::Clock rightclock; 

       while (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) 
       { 
        playerx += 0.01; //will replace later with time based movement 
        sf::Int32 rightclock1 = rightclock.getElapsedTime().asMilliseconds(); 
        cout << rightclock1 << endl; 

        /*mywindow.clear(sf::Color::Black); 
        mywindow.draw(playersprite); 
        mywindow.draw(enemysprite); 
        playersprite.setPosition(sf::Vector2f(playerx, playery)); 
        mywindow.display();*/ 

       } 
      } 
     if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) 
      { 
       // up key is pressed: move our character 
       //will replace later with time based movement 
       (playery--); 
      } 
     if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) 
      { 
       // down key is pressed: move our character 
       // currently just resets sprite position for testing purposes 
        playerx = 400.0; 
        playery = 300.0; 
      } 
     if (playerx < 0) //Player cannot leave screen x left boundary 
      { 
       playerx = 0; 
      } 
     if (playerx > windowx) //Player cannot leave screen x right boundary 
      { 
       playerx = windowx - 10; 
      } 
    } 
    mywindow.clear(sf::Color::Black); 
    mywindow.draw(playersprite); 
    mywindow.draw(enemysprite); 
    playersprite.setPosition(sf::Vector2f(playerx, playery)); 
    mywindow.display(); 
    sf::sleep(sf::microseconds(5)); 
} 
mywindow.clear(sf::Color::Black); 
mywindow.draw(playersprite); 
mywindow.draw(enemysprite); 
playersprite.setPosition(sf::Vector2f(playerx, playery)); 
mywindow.display(); 
sf::sleep(sf::microseconds(5)); 
return 0; 

}

+0

Pour l'arrière-plan, comprenez-vous déjà * pourquoi * les fenêtres ne sont pas mises à jour, ou avez-vous besoin de cela expliqué? – immibis

+0

Je ne sais pas pourquoi il ne sera pas mis à jour. – Jager57

Répondre

1

L'ordinateur exécute des instructions dans l'ordre qu'il est censé. Ce code:

mywindow.clear(sf::Color::Black); 
mywindow.draw(playersprite); 
mywindow.draw(enemysprite); 
playersprite.setPosition(sf::Vector2f(playerx, playery)); 
mywindow.display(); 
sf::sleep(sf::microseconds(5)); 

met à jour la fenêtre. Si le code de mise à jour de la fenêtre ne fonctionne pas, alors bien sûr la fenêtre ne sera pas mise à jour.

Si la touche gauche est enfoncée, l'ordinateur fonctionnera cette boucle:

while (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) 
{ 
    playerx -= 0.01; //will replace later with time based movement 
    sf::Int32 leftclock1 = leftclock.getElapsedTime().asMilliseconds(); 
    cout << leftclock1 << endl; 
    // there was commented-out code here; I removed it to save space in this answer 
} 

Il vérifie si la touche gauche est toujours pressée. Si c'est le cas, le joueur laissera un peu, imprimera l'heure et répétera. Il va donc vérifier à nouveau si la touche gauche est encore enfoncée. Si c'est le cas, le lecteur se remettra un peu, imprimera de nouveau l'heure et répètera à nouveau. Etc. Il ne sera jamais fait avec cette boucle jusqu'à ce que le joueur lâche la touche gauche - il reste juste là à bouger le joueur à gauche (pas que vous pouvez le voir) et à spammer votre console avec le temps.

La solution typique consiste simplement à supprimer les boucles qui vérifient les pressions sur les touches. Conservez les if s, mais déplacez-les en dehors de la boucle de gestion des événements. Donc, vous avez quelque chose comme ceci: (pas de code réel)

while(window is open) 
{ 
    while(have an event to process) 
    { 
     process event 
    } 
    if(left key pressed) 
    { 
     move player left 
    } 
    if(right key pressed) 
    { 
     move player right 
    } 
    // and so on 
    update window 
} 

Vous n'avez pas besoin de mettre à jour la fenêtre à l'intérieur de la boucle d'événements, en passant - à moins qu'un événement prend vraiment beaucoup de temps à traiter (ce qui ne devrait pas) alors vous finirez la boucle d'événement rapidement.

+0

Cela signifie-t-il que je ne peux pas avoir une boucle while dans mon code si je veux que l'écran continue à rafraîchir? – Jager57

+0

@ Jager57 Vous pouvez avoir des boucles while tant qu'elles se terminent rapidement. – immibis