【问题标题】:SFML Sprite movement not updating correctlySFML Sprite 移动未正确更新
【发布时间】:2017-09-13 11:34:05
【问题描述】:

我'创建一个简单的游戏,使用游戏状态。 我有一个gameLoop() 方法,它调用了一个running() 方法,其中包含切换状态,可以正常工作。 这是gameLoop() 方法:

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() 方法调用所有状态:

void Game::running()
{

    switch (state)
    {
        //other cases here

        case s_play:
            play();
            break;

        default:
            break;
    }
}

play() 方法绘制精灵并移动它:

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

}

问题是精灵只是原地移动,按A或D时从std::cout得到的输出如下:

机芯的功能有效,因为它在其他地方进行了测试。我认为我正在正确更新或以错误的方式初始化某些内容,但我无法弄清楚。

【问题讨论】:

  • 每次迭代创建纹理和精灵是浪费资源。
  • 为什么每次调用都加载纹理并设置精灵?那只是浪费循环。只做一次。也许纹理、精灵时钟应该是Game类中的成员变量?
  • sf::Clock::restart() 返回经过的时间,然后 然后 重新启动它@Someprogrammerdude。时钟是静态的,所以应该没什么区别
  • 最后,您显示的代码是您的实际代码,还是只是您在问题中编写的代码?因为您显示的代码无效。你真的应该创建一个Minimal, Complete, and Verifiable Example 来展示给我们看。
  • @Someprogrammerdude 是的,我有这些作为班级成员,我在代码中添加了注释来说明这一点。关于时钟,它工作正常,就像在另一个项目中一样

标签: c++ sfml


【解决方案1】:

我对 SFML 不熟悉,所以我希望我不会离开这里,但是,看看你的代码。在您的 play() 方法中,您创建了一个局部变量 move。从外观上看,move 包含 Sprite 的 x 和 y 坐标。由于您在 play() 方法中定义 move ,因此本地副本 每次代码通过 play() 方法运行时,都会在运行时在堆栈上创建此变量。然后你检查按键,以及 inc 或 dec 相应地移动。 move 需要在全局范围内,以便每次调用 play() 时都不会重置它。 当您将 myTexture 和 mySprite 移到函数 play() 之外时,您是正确的。您还应该移到 play() 方法之外。

类似这样的:

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

    }

希望有帮助

【讨论】:

    【解决方案2】:

    您应该在循环之外声明myTextureandmySprite,只要它们应该停留的时间就可以。 目前,您在每次迭代中再次创建它们,这对性能不利(尤其是myTexture.loadFromFile("res/img/player.png");)。游戏还会重置变换(位置、旋转等)

    【讨论】:

    • 我已经在 cmets 中阐明了这一点。我在外面有,如果你看看我在代码中输入的 cmets
    • 是的,但是在哪里?只是在播放功能之外,但在运行功能中也很糟糕
    • 它们不在运行函数中,它们在循环之外
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-10
    • 1970-01-01
    • 2012-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-28
    相关资源
    最近更新 更多