this is my first post so I hope I get this right.
I'm currently working through the SFML Game Development Book. I am trying to understand how the FPS is calculated in the intro example.
My game class looks like this:
#include "Game.h"
const sf::Time Game::TIME_PER_FRAME = sf::seconds(1.f/60.f);
const float Game::PLAYER_SPEED = 100.f;
Game::Game() : Window(sf::VideoMode(640,480), "ORGELLA") {
isMovingUp = false;
isMovingDown = false;
isMovingLeft = false;
isMovingRight = false;
Player.setRadius(40.f);
Player.setPosition(100.f, 100.f);
Player.setFillColor(sf::Color::Cyan);
font.loadFromFile(resourcePath() + "sansation.ttf");
statsText.setFont(font);
statsText.setPosition(5.f, 5.f);
statsText.setCharacterSize(10);
}
void Game::run() {
sf::Clock clock;
sf::Time timeSinceLastUpdate = sf::Time::Zero;
while (Window.isOpen()) {
sf::Time dt = clock.restart();
timeSinceLastUpdate += dt;
while (timeSinceLastUpdate > TIME_PER_FRAME) {
timeSinceLastUpdate -= TIME_PER_FRAME;
handleEvents();
update(TIME_PER_FRAME);
}
updateGameStats(dt);
render();
}
}
void Game::handleEvents() {
sf::Event event;
while (Window.pollEvent(event)) {
switch (event.type) {
case sf::Event::KeyPressed:
handlePlayerInput(event.key.code, true);
break;
case sf::Event::KeyReleased:
handlePlayerInput(event.key.code, false);
break;
case sf::Event::Closed:
Window.close();
break;
}
}
}
void Game::update(sf::Time dt) {
sf::Vector2f movement(0.f, 0.f);
if (isMovingUp)
movement.y -= PLAYER_SPEED;
if (isMovingDown)
movement.y += PLAYER_SPEED;
if(isMovingLeft)
movement.x -= PLAYER_SPEED;
if (isMovingRight)
movement.x += PLAYER_SPEED;
Player.move(movement * dt.asSeconds());
}
void Game::render() {
Window.clear();
Window.draw(Player);
Window.draw(statsText);
Window.display();
}
void Game::handlePlayerInput(sf::Keyboard::Key key, bool isPressed) {
switch (key) {
case sf::Keyboard::W:
isMovingUp = isPressed;
break;
case sf::Keyboard::S:
isMovingDown = isPressed;
break;
case sf::Keyboard::A:
isMovingLeft = isPressed;
break;
case sf::Keyboard::D:
isMovingRight = isPressed;
break;
}
}
void Game::updateGameStats(sf::Time dt) {
statsTotalTimeElapsed += dt ;
statsNumberOfFrames += 1;
if (statsTotalTimeElapsed >= sf::seconds(1.0f)) {
statsText.setString(
"FPS = " + to_string(statsNumberOfFrames) + "\n" +
"Time/Update = " + to_string(statsTotalTimeElapsed.asMicroseconds() / statsNumberOfFrames) + "us");
statsTotalTimeElapsed -= sf::seconds(1.0f);
statsNumberOfFrames = 0;
}
}
Now, my question is this. How is the FPS being calculated that is rendered to my screen. From what i can understand the FPS is capped at 60fps but yet when i run the application the FPS that is displayed is around 500 - 1200 FPS.
Am i calculating this wrong or just not understanding this correctly?
I hope this post is okay, I can't seem to find a similar question.
Any advice or help will be greatly appreciated.
Given a framerate (for example 60 FPS):
auto framerate = 60; // FPS
auto elapsedMillisecondsExpected = 1000 / framerate; // in milliseconds
In SFML you use an sf::Clock and at every frame you cap it:
sf::Clock clock;
// frame logic
auto elapsedMilliseconds = clock.getElapsedTime().asMilliseconds();
if (elapsedMilliseconds < elapsedMillisecondsExpected) {
auto sleepMilliseconds = elapsedMillisecondsExpected - elapsedMilliseconds;
// sleep for sleepMilliseconds
}
Figured this one out! I was looking at total frames ran per second and not frames updated per second. When i log how many times the update method gets run per second i get a steady 60FPS.
Appreciate the help.
Nick
Related
I searched on this topic and found that using sf::Clock to implement frame independent update(using deltaTime) can help to solve it. However even after adding it the paddle movement stutters a bit. On the other hand when I shift the entire Playing case to the event polling loop without using deltatime the game seems to run smoothly.
How do I go about using sf::Clock properly in my code and why does my game seems to run smoothly when I shift the Playing case in event pool loop without even using deltatime?
Game initialization:
void Game::start() {
if (_gameState != Uninitialized) {
return;
}
//Creating window
_mainWindow.create(sf::VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32), "Pong");
_gameState = ShowingMenu;
//Adding game entities to the manager
VisibleGameObject *paddle1 = new PlayerPaddle("Player1", 1.0f, sf::Keyboard::Key::Up, sf::Keyboard::Key::Down);
VisibleGameObject *paddle2 = new PlayerPaddle("Player2", 1.0f, sf::Keyboard::Key::W, sf::Keyboard::Key::S);
VisibleGameObject *background = new Background("Background", 0.0f);
paddle1 -> setPosition(SCREEN_WIDTH - (paddle1 -> getWidth()), 0);
paddle2->setPosition(0, 0);
manager.addObject(paddle1);
manager.addObject(paddle2);
manager.addObject(background);
//Starting Clock
deltaTime = 0.0f;
frameClock.restart();
while (!isExiting()) {
gameLoop();
}
_mainWindow.close();
}
Game Loop :
void Game::gameLoop()
{
static bool firstPass = true;
sf::Event currentEvent;
//Event loop
while(_mainWindow.pollEvent(currentEvent) || firstPass)
{
if (firstPass) {
currentEvent = sf::Event();
currentEvent.type = sf::Event::GainedFocus;
firstPass = false;
}
if (currentEvent.type == sf::Event::Closed)
{
_gameState = Exiting;
}
switch (_gameState)
{
case ShowingMenu:
{
showingMenu();
break;
}
case Paused:
{
break;
}
default:
break;
}
}
//Extracting deltaTime to update game logic
deltaTime = frameClock.restart().asSeconds();
if(_gameState == Playing)
{
manager.updateAllLayers(deltaTime);
manager.drawAllLayers(_mainWindow);
_mainWindow.display();
}
}
Paddle Update Logic:
void PlayerPaddle::update(const float & elapsedTime)
{
sf::Vector2f currentPos = getPosition();
float displacement = 0.0f;
if (sf::Keyboard::isKeyPressed(controls.up))
{
displacement = -speed * elapsedTime;
}
else if (sf::Keyboard::isKeyPressed(controls.down))
{
displacement = speed * elapsedTime;
}
if (displacement + currentPos.y < 0.0f)
{
setPosition(currentPos.x, 0.0f);
return;
}
else if (displacement + currentPos.y + getHeight() > Game::SCREEN_HEIGHT)
{
setPosition(currentPos.x, Game::SCREEN_HEIGHT - getHeight());
return;
}
setPosition(currentPos.x, currentPos.y + displacement);
}
I don't have enough reputation to post a comment so I'll have to make this an answer...
You update (and draw) every frame. Your game loop doesn't make sense if you want to implement a fixed update time step.
This is how your game loop should look like. I use your variable names for your convenience:
// ...
sf::Clock frameClock;
const sf::Time timePerFrame = sf::seconds(1.0f / 60.0f);
sf::Time timeSinceLastUpdate = sf::Time::Zero;
while (_mainWindow.isOpen()) {
timeSinceLastUpdate += frameClock.restart();
// events
{
sf::Event evt;
while (_mainWindow.pollEvent(evt)) {
//...
}
}
// update
{
while (timeSinceLastUpdate > timePerFrame) {
timeSinceLastUpdate -= timePerFrame;
manager.updateAllLayers(timePerFrame);
}
}
// render
{
_mainWindow.clear();
// ...
_mainWindow.display();
}
}
// ...
This updates your game at a fixed rate (1/60s) and renders it whenever possible (you can use setFramerateLimit() to limit the FPS; this won't affect the fixed update interval, so no problem there).
You now pass sf::Time to your manager.updateAllLayers which is used like your elapsedTime (it has functions like .asSeconds() so essentially nothing changes but you'll obviously have to adjust the values for speed)
Currently I have this player.cpp class that I'm using for my sprite animations. I'm using a counter to update every frame. It animates, but it flies through the animations.
I want to slow this down. I found code that can be used to slow down sprite animations but I'm unsure how to implement it into my current program.
Below are my player.cpp file and following it is the code I found that can slow down sprite animations. When I've tried to add a clock to the counterWalking++ it didn't animate at all, and I've tried implementing this code to the same effect.
player::player()
{
rect.setSize(sf::Vector2f(32, 32));
rect.setFillColor(sf::Color::White);
rect.setPosition(300, 300);
sprite.setTextureRect(sf::IntRect(0, 0, 32, 32));
}
void player::update()
{
sprite.setPosition(rect.getPosition());
}
void player::updateMovement()
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) {
if (canMoveRight == true) {
rect.move(movementSpeed, 0);
sprite.setTextureRect(sf::IntRect(counterWalking * 32, 64, 32, 32));
direction = 4;
canMoveUp = true;
canMoveDown = true;
canMoveLeft = true;
canMoveRight = true;
}
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) {
if (canMoveLeft == true) {
rect.move(-movementSpeed, 0);
sprite.setTextureRect(sf::IntRect(counterWalking * 32, 32, 32, 32));
direction = 3;
canMoveUp = true;
canMoveDown = true;
canMoveLeft = true;
canMoveRight = true;
}
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
if (canMoveUp == true) {
rect.move(0, -movementSpeed);
sprite.setTextureRect(sf::IntRect(counterWalking * 32, 96, 32, 32));
direction = 1;
canMoveUp = true;
canMoveDown = true;
canMoveLeft = true;
canMoveRight = true;
}
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
if (canMoveDown == true) {
rect.move(0, movementSpeed);
sprite.setTextureRect(sf::IntRect(counterWalking * 32, 0, 32, 32));
direction = 2;
canMoveUp = true;
canMoveDown = true;
canMoveLeft = true;
canMoveRight = true;
}
}
else {
//Player not moving
}
counterWalking++;
if (counterWalking == 3)
counterWalking = 0;
}
Here is the code I found that displays a slow animation:
int main()
{
sf::RenderWindow renderWindow(sf::VideoMode(640, 480), "Demo Game");
sf::Event event;
sf::Texture texture;
texture.loadFromFile("images/player.png");
sf::IntRect rectSourceSprite(0, 0, 32, 32);
sf::Sprite sprite(texture, rectSourceSprite);
sf::Clock clock;
while (renderWindow.isOpen()) {
while (renderWindow.pollEvent(event)) {
if (event.type == sf::Event::EventType::Closed)
renderWindow.close();
}
if (clock.getElapsedTime().asSeconds() > 1.0f) {
if (rectSourceSprite.left == 96)
rectSourceSprite.left = 0;
else
rectSourceSprite.left += 32;
sprite.setTextureRect(rectSourceSprite);
clock.restart();
}
renderWindow.clear();
renderWindow.draw(sprite);
renderWindow.display();
}
}
Since a solution has been given in comment but not implemented in an answer, here's some kind of "code review"
Key Binding
This code is actually using the sf::Keyboard::isKeyPressed and sf::Keyboard::isKeyReleased wich needs to be called every loop while a simple boolean switched when the key is pressed/released could to the work using events.
while (renderWindow.pollEvent(event)) {
if (event.type == sf::Event::EventType::Closed)
renderWindow.close();
}
The Event used in the main loop does also contain information about KeyEvents but isn't used that way. I'll suggest sending the evet to the player eac time a key Event happens:
while (renderWindow.pollEvent(event)) {
switch(event.type){
case sf::Event::EventType::Closed:
renderWindow.close();
break;
case sf::Event::KeyPressed: case sf::Event::KeyReleased:
myPlayer.keyEvent(event);
break;
}
}
The keyEvent function in player should then look like this:
void player::keyEvent(sf::Event event){
//Keycode of your keyboard's arrows goes from 71 to 74
if (event.key.code >= 71 && event.key.code <= 74){
//Gets the array ID from the enumeration value
int ID = event.key.code - 71;
//Stores false if the key is release, and true if it's pressed
keys[ID] = (event.type == sf::Event::KeyPressed);
}
}
Wich changes each values of the array in Player.h:
private:
bool keys[4];
Movement
Now all you have to do is call the player update() function in your game loop each second:
if (clock.getElapsedTime().asSeconds() > 1.0f) {
if (rectSourceSprite.left == 96)
rectSourceSprite.left = 0;
else
rectSourceSprite.left += 32;
sprite.setTextureRect(rectSourceSprite);
myPlayer.update();
clock.restart();
}
In the update() function, ou will then build you movement vector based on wich key is pressed:
void player::update()
{
sf::Vector2f movementVector(0,0);
//Left
if (keys[0]){
movementVector.x -= movementSpeed;
//Sends the sprite Rectangle position based on the movement type
move(32);
}
//Right
if (keys[1]){
movementVector.x += movementSpeed;
move(64);
}
//Up
if (keys[2]){
movementVector.y -= movementSpeed;
move(96);
}
//Down
if (keys[3]){
movementVector.y += movementSpeed;
move(0);
}
}
The move function will then move your sprite Position depending on the movement vector and the counter, the sprite will then be set.
Your movement counter will be incremented up to 30 and your player may only move when this counter is equal to 0, 10 or 20:
void move(int spritePos){
//Here, the check() function should tell if the player isn't going outside of the screen / in a wall
if (check(sprite.getPosition() + movementVector)){
sprite.move(movementVector);
++counterWalking %= 30;
if(!counterWalking % 10)
sprite.setTextureRect(sf::IntRect(counterWalking / 10 * 32, spritePos, 32, 32));
}
}
There are multiple ways of doing this, that's only the way I would do it
Sounds like you might need to learn about controlling the time-step. Essentially you only execute certain code when a desired amount of time has passed.
You'll commonly see this site referenced so maybe check it out:
https://gafferongames.com/post/fix_your_timestep/
I am trying to make a game and am stuck on gravity..... In the following code a rectangle stands for a player and when I press up key it moves in y-axis but when I activate gravity on it (i.e resetting its previous position) it does not animate (i.e. It does not jumps) instead it just stays in its position. I am using SFML library of C++ and that's a game development tool. Please Help!
#include <SFML/Graphics.hpp>
int main(){
sf::RenderWindow window(sf::VideoMode(800, 600, 32), "Gravity");
sf::RectangleShape rectangle;
rectangle.setSize(sf::Vector2f(100, 100));
rectangle.setFillColor(sf::Color::Black);
rectangle.setPosition(sf::Vector2f(10, 350));
while(window.isOpen())
{
sf::Event Event;
while(window.pollEvent(Event))
{
if(Event.type == sf::Event::Closed)
{
window.close();
}
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
{
rectangle.move(0, -1);
}
if(rectangle.getPosition().y >= 350-1)
{
rectangle.setPosition(0, 350);
}
window.display();
window.clear(sf::Color::Cyan);
window.draw(rectangle);
}
}
Theoretically your code would work, but there's one significant problem:
Your initial position is 350.
Now your "jumping code" (which will allow the player to fly indefinitely!) triggers and your position is changed to 349.
However, your code keeping the player from dropping off the screen (y >= 350-1) essentially resolves to the check y >= 349, which will be true, so your position is permanently reset to 350.
To solve this, just remove the -1 or replace the >= operator with >.
While your approach should be working (once the fix above is applied), you should rethink your strategy and store a velocity in addition to a position. I've recently written the following example code. It's far from being perfect, but it should teach you a few basics for a jump and run game (not necessarily the only way to do such things):
Allow the player to jump.
Apply gravity.
Allow the player to determine jump height based on how long he holds down a key.
#include <SFML/Graphics.hpp>
int main(int argc, char **argv) {
sf::RenderWindow window;
sf::Event event;
sf::RectangleShape box(sf::Vector2f(32, 32));
box.setFillColor(sf::Color::White);
box.setOrigin(16, 32);
box.setPosition(320, 240);
window.create(sf::VideoMode(640, 480), "Jumping Box [cursor keys + space]");
window.setFramerateLimit(60);
window.setVerticalSyncEnabled(false);
// player position
sf::Vector2f pos(320, 240);
// player velocity (per frame)
sf::Vector2f vel(0, 0);
// gravity (per frame)
sf::Vector2f gravity(0, .5f);
// max fall velocity
const float maxfall = 5;
// run acceleration
const float runacc = .25f;
// max run velocity
const float maxrun = 2.5f;
// jump acceleration
const float jumpacc = -1;
// number of frames to accelerate in
const unsigned char jumpframes = 10;
// counts the number of frames where you can still accelerate
unsigned char jumpcounter = 0;
// inputs
bool left = false;
bool right = false;
bool jump = false;
while (window.isOpen()) {
while (window.pollEvent(event)) {
switch(event.type) {
case sf::Event::KeyPressed:
case sf::Event::KeyReleased:
switch (event.key.code) {
case sf::Keyboard::Escape:
window.close();
break;
case sf::Keyboard::Left:
left = event.type == sf::Event::KeyPressed;
break;
case sf::Keyboard::Right:
right = event.type == sf::Event::KeyPressed;
break;
case sf::Keyboard::Space:
jump = event.type == sf::Event::KeyPressed;
break;
}
break;
case sf::Event::Closed:
window.close();
break;
}
}
// logic update start
// first, apply velocities
pos += vel;
// determine whether the player is on the ground
const bool onground = pos.y >= 480;
// now update the velocity by...
// ...updating gravity
vel += gravity;
// ...capping gravity
if (vel.y > maxfall)
vel.y = maxfall;
if (left) { // running to the left
vel.x -= runacc;
}
else if (right) { // running to the right
vel.x += runacc;
}
else { // not running anymore; slowing down each frame
vel.x *= 0.9;
}
// jumping
if (jump) {
if (onground) { // on the ground
vel.y += jumpacc * 2;
jumpcounter = jumpframes;
}
else if (jumpcounter > 0) { // first few frames in the air
vel.y += jumpacc;
jumpcounter--;
}
}
else { // jump key released, stop acceleration
jumpcounter = 0;
}
// check for collision with the ground
if (pos.y > 480) {
vel.y = 0;
pos.y = 480;
}
// check for collision with the left border
if (pos.x < 16) {
vel.x = 0;
pos.x = 16;
}
else if (pos.x > 624) {
vel.x = 0;
pos.x = 624;
}
// logic update end
// update the position
box.setPosition(pos);
window.clear();
window.draw(box);
window.display();
}
return 0;
}
I started studying SFML from the book "SFML Game Development" by Arthur Moreira. I'm trying to move a circle object on the screen using the keyboard. Here is the code that is given:
#include <SFML/Graphics.hpp>
class Game
{
public:
Game();
void run();
private:
void ProcessEvents();
void update();
void render();
void handlePlayerInput(sf::Keyboard::Key key, bool isPressed);
private:
sf::RenderWindow myWindow;
sf::CircleShape myPlayer;
bool movingLeft, movingUp, movingRight, movingDown;
};
Game::Game() : myWindow(sf::VideoMode(640, 480), "SFML Game"), myPlayer()
{
myPlayer.setRadius(40.f);
myPlayer.setFillColor(sf::Color::Red);
myPlayer.setPosition(100.f, 100.f);
}
void Game::run()
{
while (myWindow.isOpen())
{
ProcessEvents();
update();
render();
}
}
void Game::ProcessEvents()
{
sf::Event event;
while (myWindow.pollEvent(event))
{
switch(event.type)
{
case sf::Event::KeyPressed : handlePlayerInput(event.key.code, true); break;
case sf::Event::KeyReleased : handlePlayerInput(event.key.code, false); break;
case sf::Event::Closed : myWindow.close(); break;
}
}
}
void Game::handlePlayerInput(sf::Keyboard::Key key, bool isPressed)
{
if (key == sf::Keyboard::W) movingUp = isPressed;
else if (key == sf::Keyboard::S) movingDown = isPressed;
else if (key == sf::Keyboard::A) movingLeft = isPressed;
else if (key == sf::Keyboard::D) movingRight = isPressed;
}
void Game::update()
{
sf::Vector2f movement(0.f, 0.f);
if (movingUp) movement.y -= 1.f;
if (movingDown) movement.y += 1.f;
if (movingLeft) movement.x -= 1.f;
if (movingRight) movement.x += 1.f;
myPlayer.move(movement);
}
void Game::render()
{
myWindow.clear();
myWindow.draw(myPlayer);
myWindow.display();
}
int main()
{
Game game;
game.run();
return 0;
}
Here is what my problem is:
In the function update(), I'm updating the direction on which the cicle should go. But the first time when I try to move for example to left, the circle goes to right. The opposite is the same. If I try to go to right in the beginning, the circle goes to left. When I try to go Up and Down the result is the same. So, as I said, when I go to left, it goes to right. But if I press again left, the movement stops and I can move the circle correctlyto left and right. I should do the same thing to repair the direction if I want to go Up and Down. Do I have a mistake in my code?
And my second question is:
In the update function I have written the code that is in the book. But if I want to go Up, I think I should add 1 to 'y', not to substract 1. And if I want to go down, shouldn't I substract 1? I think that the update function should look like this:
void Game::update()
{
sf::Vector2f movement(0.f, 0.f);
if (movingUp) movement.y += 1.f; //Here we should add 1
if (movingDown) movement.y -= 1.f; //Here we should substract 1
if (movingLeft) movement.x -= 1.f;
if (movingRight) movement.x += 1.f;
myPlayer.move(movement);
}
Maybe it will be better for you to run the code if you are able in order to see what exactly is happening.
Your moving variables aren't initialized, so some of them may initially have a true value.
You should set them all to false in your Game constructor.
First of all, I already did ask this in SFML forums but they couldn't help, they actually copied my code and it worked perfectly, even with someone with the same OS as me (Windows 8)
I'm currently reading the SFML Game Development book, in the first chapter, when movement is introduced, I encountered some problems, I spawn a white circle in the centre of the window, now If i press any directional arrow, the circle keeps going in the other direction till I press it, and then it gets back to normal, and horizontal and vertical ones are seperate.
Example: I start "Game", press up, the circle keeps going down, i hold up, the circle stands still, I release, it keeps going down, I press down, it stops, now it responds normally to both keys, it will happen again with the right and left, it gets fixed after the initial error, but I wish to know how I can remove it
#include <SFML/Graphics.hpp>
using namespace sf;
class Game
{
public:Game();
void run();
private:
void processEvents();
void update(Time);
void render();
void handlePlayerInput(Keyboard::Key,bool);
bool mIsMovingUp, mIsMovingRight, mIsMovingLeft, mIsMovingDown;
float playerSpeed;
Time TimePerFrame;
private:
RenderWindow mWindow;
CircleShape mPlayer;
};
Game::Game():mWindow(VideoMode(640, 480), "SFML Application"),mPlayer(), playerSpeed(20.f), TimePerFrame(seconds(1.f / 60.f))
{
mPlayer.setRadius(20.f);
mPlayer.setPosition(220.f, 220.f);
mPlayer.setFillColor(Color::White);
}
void Game::handlePlayerInput(Keyboard::Key key, bool isPressed)
{
if (key == Keyboard::W || key == Keyboard::Up)
mIsMovingUp = isPressed;
else if (key == Keyboard::S || key == Keyboard::Down)
mIsMovingDown = isPressed;
else if (key == Keyboard::A || key == Keyboard::Left)
mIsMovingLeft = isPressed;
else if (key == Keyboard::D || key == Keyboard::Right)
mIsMovingRight = isPressed;
}
void Game::run()
{
Clock clock;
Time timeSinceLastUpdate = Time::Zero;
while (mWindow.isOpen())
{
processEvents();
timeSinceLastUpdate += clock.restart();
while (timeSinceLastUpdate > TimePerFrame)
{
timeSinceLastUpdate -= TimePerFrame;
processEvents();
update(TimePerFrame);
}
render();
}
}
void Game::processEvents()
{
Event event;
while (mWindow.pollEvent(event))
{
switch (event.type)
{
case Event::KeyPressed:
handlePlayerInput(event.key.code, true);
break;
case sf::Event::KeyReleased:
handlePlayerInput(event.key.code, false);
break;
case sf::Event::Closed:
mWindow.close();
break;
}
}
}
void Game::update(Time deltaTime)
{
Vector2f movement(0.f, 0.f);
if (mIsMovingUp)
movement.y -= playerSpeed;
if (mIsMovingDown)
movement.y += playerSpeed;
if (mIsMovingLeft)
movement.x -= playerSpeed;
if (mIsMovingRight)
movement.x += playerSpeed;
mPlayer.move(movement * deltaTime.asSeconds());
}
void Game::render()
{
mWindow.clear();
mWindow.draw(mPlayer);
mWindow.display();
}
int main()
{
Game game;
game.run();
}
Answer:
By default, these variables must be true:
bool mIsMovingUp, mIsMovingRight, mIsMovingLeft, mIsMovingDown;
In Game::Game(), declare them all as false. That should solve your problem.
Explanation:
In other words, when mIsMovingUp and down are mIsMovingDown true, it stays still. When you press up and let go, it makes mIsMovingUp false but leaves mIsMovingDown true, so the ball moves mIsMovingDown. After you press and let go of mIsMovingDown, it makes mIsMovingDown false, and then they are both false and movement ceases. Same for isMovingLeft and isMovingRight.