Reputation: 3
Whenever I press a key to move a sprite, the screen will not update until I release the key. The only way I've been able to fix this is to clear, draw, and display the window within each and every KeyPressed loop.
It makes much more sense to do each of these things one time, independent of any key-presses. I don't know why this isn't working, or what the best way of fixing this would be.
In the program below, I posted the clear/draw/display code in multiple different places hoping that putting it in the right place will work. So far it hasn't. The redundancy is otherwise pointless.
#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;
}
Upvotes: 0
Views: 143
Reputation: 58909
The computer runs instructions in the order it's supposed to. This 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));
updates the window. If the window-updating code doesn't run, then of course the window doesn't get updated.
If the left key is pressed, then the computer will run this loop:
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
}
It will check if the left key is still pressed. If it is, it will move the player left a bit, print the time, and repeat. So it will check again if the left key is still pressed. If it is, it will move the player left a bit again, print the time again, and repeat again. And so on. It will never be done with this loop until the player lets go of the left key - it will just sit there moving the player left (not that you can see it) and spamming your console with the time.
The typical solution to this is just to remove those loops that check for key presses. Keep the if
s, but move them outside the event-handling loop. So you have something like this: (not actual code)
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
}
You don't need to update the window inside the event loop, by the way - unless an event takes a really long time to process (which they shouldn't) then you'll finish the event loop quickly.
Upvotes: 1