Спрайт SFML не двигается при нажатии на клавиатуру - PullRequest
1 голос
/ 04 августа 2020

Я создаю простую игру для перемещения спрайта с помощью кнопок клавиатуры (ASDW) и использую принципы OOP в моем коде. Кажется, все в порядке, и синтаксической ошибки нет, но когда я запускаю код, спрайт вообще не перемещается.

вот фрагмент моего кода для управления событием клавиатуры:

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 также вставил весь мой код по этой ссылке: https://pastebin.com/N9EH9yLi

Может ли кто-нибудь помочь мне с этим? Я в замешательстве.

1 Ответ

1 голос
/ 04 августа 2020

Я просмотрел ваш код и обнаружил несколько проблем.

  1. Во-первых, вы не инициализируете все переменные-члены Game объекта, в частности логические флаги, определяющие движение вверх или вниз , влево или вправо.
  2. Во-вторых, скорость проигрывателя имеет чрезвычайно низкое значение const float playerSpeed = 0.1f; Это стало еще менее заметным, потому что ваш код умножает дельта-время на 1/60 секунды, что приводит к практически незаметная стоимость. Я изменил значение на 100.f, чтобы убедиться, что он работает.
  3. В-третьих, когда клавиша отпускается, код не может отключить логический флаг. Это было исправлено путем изменения handlePlayerInput(event.key.code, true); на handlePlayerInput(event.key.code, false);, т. Е. Отключение движения в этом направлении при отпускании этой клавиши.
  4. В-четвертых, не уверен, было ли это намеренно, но вы запретили пользователю двигаться в обоих направлениях. x и y направления одновременно. Если это не так, проверьте движение как в вертикальном, так и в горизонтальном направлении с помощью двух отдельных блоков if / else.

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();
}

Я не уверен, что вы намеренно использовали ключевые события для перемещения спрайта, но лучшей и простой альтернативой было бы вызывать sf::Keyboard::isKeyPressed каждое обновление вместо отслеживания логических переменных, которые зависят от событий.

...