Ethan
Ethan

Reputation: 321

SFML sprite not moving when pressing keyboard

I am creating a simple game to move a sprite using keyboard buttons (ASDW) and I am using OOP principles in my code. Everything seems fine and there's no syntax error but when I run the code the sprite is not moving at all.

here is a piece of my code for controlling keyboard event:

void Game::proccessEvent()
{
sf::Event event;
while (mWindow.pollEvent(event)) {
    switch (event.type) {
        case sf::Event::Closed:
            mWindow.close();
            break;
            
        case sf::Event::KeyPressed:
            handlePlayerInput(event.key.code, true);
            break;
            
        case sf::Event::KeyReleased:
            handlePlayerInput(event.key.code, true);
            break;
            
        default:
            break;
    }
}
}

I also pasted my whole code in this link: https://pastebin.com/N9EH9yLi

Can anyone please help me out of this? I am confused.

Upvotes: 2

Views: 261

Answers (1)

Rabster
Rabster

Reputation: 1013

I took a look at your code and found a few issues.

  1. First, you are not initializing all of Game object member variables, specifically the boolean flags determining to move up, down, left, or right.
  2. Second, the player speed has an extremely low value of const float playerSpeed = 0.1f; It's made even less noticeable because your code is multiplying the delta time of 1/60th of a second which results in an almost unnoticeable value. I changed the value to 100.f just to verify that it works.
  3. Third, when the key is released the code fails to disable the boolean flag. This was fixed by changing handlePlayerInput(event.key.code, true); to handlePlayerInput(event.key.code, false);, i.e., disable movement in that direction when that key is released.
  4. Fourth, not sure if this intentional, but you disabled the user from moving in both the x and y direction at the same time. If this isn't then check for movement in both the vertical and horizontal direction with two separate if/else blocks.

https://pastebin.com/Mx4vzmmL

#include <SFML/Graphics.hpp>
#include <iostream>
class Game
{
public:
    Game();
    void run();

private:
    void proccessEvent();
    void update(sf::Time deltaTime);
    void render();
    void handlePlayerInput(sf::Keyboard::Key key, bool isPressed);

private:
    const float playerSpeed = 100.f;
    const sf::Time TimePerFrame = sf::seconds(1.0f / 60.0f);

    sf::RenderWindow mWindow;
    sf::Keyboard::Key key;
    sf::Texture texture;
    sf::RectangleShape rect;
    bool isPressed;
    bool mIsMovingUp;
    bool mIsMovingDown;
    bool mIsMovingRight;
    bool mIsMovingLeft;
};
Game::Game()
    : //Make sure to initialize member variables.
    playerSpeed(100.f),
    TimePerFrame(sf::seconds(1.f / 60.f)),
    mWindow(sf::VideoMode(640, 480), "SFML Application"),
    key(sf::Keyboard::Unknown),
    isPressed(false),
    mIsMovingUp(false),
    mIsMovingDown(false),
    mIsMovingRight(false),
    mIsMovingLeft(false)
{
    //  rect.setTexture(texture);
    rect.setFillColor(sf::Color::Red);
    rect.setSize(sf::Vector2f(20.0f, 20.0f));
}

void Game::run()
{
    sf::Clock clock;
    sf::Time timeSinceLastUpdate = sf::Time::Zero;

    while (mWindow.isOpen())
    {
        proccessEvent();
        sf::Time elapsedTime = clock.restart();
        timeSinceLastUpdate += elapsedTime;
        while (timeSinceLastUpdate > TimePerFrame)
        {
            timeSinceLastUpdate -= TimePerFrame;
            proccessEvent();
            update(TimePerFrame);
        }
        render();
    }
}

void Game::proccessEvent()
{
    sf::Event event;
    while (mWindow.pollEvent(event)) {
        switch (event.type) {
        case sf::Event::Closed:
            mWindow.close();
            break;
        case sf::Event::KeyPressed:
            handlePlayerInput(event.key.code, true);
            break;
        case sf::Event::KeyReleased:
            handlePlayerInput(event.key.code, false);
            break;
        default:
            break;
        }
    }
}

void Game::update(sf::Time deltaTime)
{

    sf::Vector2<float> movement(0.0f, 0.0f);
    if (mIsMovingUp)
    {
        movement.y -= playerSpeed;
    }
    else if (mIsMovingDown)
    {
        movement.y += playerSpeed;
    }
    if (mIsMovingRight)
    {
        // You were subtracting to move right, add instead.
        movement.x += playerSpeed;
    }
    else if (mIsMovingLeft)
    {
        movement.x -= playerSpeed;
    }
    rect.move(movement * deltaTime.asSeconds());

}

void Game::render()
{
    //if (!texture.loadFromFile("/Users/tahajalili/Desktop/Eagle.png"))
    //{
    //  std::cout << "Error occured" << std::endl;
    //}

    mWindow.clear();
    mWindow.draw(rect);
    mWindow.display();
}

void Game::handlePlayerInput(sf::Keyboard::Key key, bool isPressed)
{
    if (key == sf::Keyboard::W)
    {
        mIsMovingUp = isPressed;
    }
    else if (key == sf::Keyboard::S)
    {
        mIsMovingDown = isPressed;
    }
    else if (key == sf::Keyboard::D)
    {
        mIsMovingRight = isPressed;
    }
    else if (key == sf::Keyboard::A)
    {
        mIsMovingLeft = isPressed;
    }
}

int main(int, char const**)
{
    Game game;
    game.run();
}

I'm not sure if you are intentionally used key events to move a sprite, but a better and simpler alternative would be to call sf::Keyboard::isKeyPressed every update instead of keeping track of boolean variables that depend upon events.

Upvotes: 2

Related Questions