简体   繁体   中英

SFML Sprite movement not updating correctly

I' creating a simple game, using game states. I have a gameLoop() method that calls a running() method, which contains the switching states, which works correctly. This is the gameLoop() method:

void Game::gameLoop()
{
  while (window.isOpen()) {
    Event event;
    while (window.pollEvent(event)) {
      if (event.type == Event::Closed){
        window.close();
      }
    }
    if (Keyboard::isKeyPressed(Keyboard::Escape)) {
      window.close();
    }

    window.clear();
    running();              //this calls the states
    window.display();
}

running() method calls all the states:

void Game::running()
{

    switch (state)
    {
        //other cases here

        case s_play:
            play();
            break;

        default:
            break;
    }
}

And the play() method draws the sprite and moves it:

void Game::play()
{
    Texture myTexture;   //I've also tried to declare these outside the method
    Sprite mySprite;

///////////Graphics

    myTexture.loadFromFile("res/img/player.png");

    mySprite.setTexture(myTexture);

//////////Movement

    static sf::Clock clock;
    float dt = clock.restart().asSeconds();
    Vector2f move;

    if (Keyboard::isKeyPressed(Keyboard::A)) 
        {
            move.x--;
        }

        std::cout << mySprite.getPosition().x << "\n";
    }

    if (Keyboard::isKeyPressed(Keyboard::D))
        {
            move.x++;
        }

        std::cout << mySprite.getPosition().x << "\n";
    }

    mySprite.move(move*300.0f*dt);

    window.draw(mySprite);

}

The problem is that the sprite just moves on the spot, and the output obtained from the std::cout is the following, when pressing A or D:

在此处输入图片说明

The function of the movement works, because it was tested elsewhere. I think that I'm updating correctly or initializing something in the wrong way, but I can't figure it out.

I am not familiar with SFML so I hope I am not off base here, however, looking at your code. In your play() method, you create a local variable move. From the looks of it, move contains the x and y coordinate for your Sprite. Since you define move inside the play() method, a local copy of this variable is created on the stack at run time each time your code runs through the play() method. Then you check for key presses, and inc or dec move accordingly. move needs to be at global scope so that it is not reset every time you call play(). You were correct when you moved myTexture and mySprite outside the function play(). You should also move move outside of the play() method.

Something like this:

Texture myTexture;   //I've also tried to declare these outside the method
Sprite mySprite;
Vector2f move;

    void Game::play()
    {

    ///////////Graphics

        myTexture.loadFromFile("res/img/player.png");

        mySprite.setTexture(myTexture);

    //////////Movement

        static sf::Clock clock;
        float dt = clock.restart().asSeconds();

        if (Keyboard::isKeyPressed(Keyboard::A)) 
            {
                move.x--;
            }

            std::cout << mySprite.getPosition().x << "\n";
        }

        if (Keyboard::isKeyPressed(Keyboard::D))
            {
                move.x++;
            }

            std::cout << mySprite.getPosition().x << "\n";
        }

        mySprite.move(move*300.0f*dt);

        window.draw(mySprite);

    }

Hope that helps

You should declare myTextureand and mySprite outside of the loop on a place where they stay as long as they should. Currently you are creating them again in each iteration, which is bad for performance (espacially myTexture.loadFromFile("res/img/player.png"); ). The recreation resets also the transform (position, rotation, etc.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM