【问题标题】:How to move a sprite smoothly?如何平滑移动精灵?
【发布时间】:2016-05-13 11:36:05
【问题描述】:

我用 C++ 和 SFML 编写了一个简单的程序。我的问题是当我移动我的精灵时它非常不稳定。我的精灵会移动一点,然后加速到平稳的移动,直到我按下另一个键,它会再次停止然后继续。我希望这是有道理的,但简而言之,我只是希望我的精灵运动更平滑。我的代码:

#include <SFML/Graphics.hpp>
#include <math.h>
#include <iostream>

int main()
{
    float x = 0;
    float y = 0;
    sf::Vector2f position;
    sf::Vector2f velocity;
    float maxspeed = 3.0f;
    float accel = 1.0f;
    float decel = 0.02f;
    sf::RenderWindow window(sf::VideoMode(400, 400), "SFML works!");
    sf::Texture tplayer;

    if (!tplayer.loadFromFile("character.png"))
    {
        // error...
    }

    sf::Sprite splayer;
    splayer.setTexture(tplayer);
    splayer.setOrigin(sf::Vector2f(0, 0));
    splayer.setTextureRect(sf::IntRect(0, 0, 16, 38));

    sf::Vector2f pos = splayer.getPosition();

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
            {
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
                    velocity.x -= accel;
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
                    velocity.x += accel;
                else
                    velocity.x *= decel;

                if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
                    velocity.y -= accel;
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
                    velocity.y += accel;
                else
                    velocity.y *= decel;

                if (velocity.x < -maxspeed) velocity.x = -maxspeed;
                if (velocity.x > maxspeed)  velocity.x = maxspeed;
                if (velocity.y < -maxspeed) velocity.y = -maxspeed;
                if (velocity.y > maxspeed)  velocity.y = maxspeed;

                position += velocity;
                splayer.setPosition(position);
            }
        }

        window.clear();
        window.draw(splayer);
        window.display();
        window.setFramerateLimit(60);
    }

    return 0;
}

【问题讨论】:

    标签: c++ animation sprite codeblocks sfml


    【解决方案1】:

    谷歌frame independent movement

    //Before main loopp
    sf::Clock clock;
    
    // Start main loop
    
             //Somewhere in the main loop
             sf::Time deltaTime = clock.restart().asSeconds();
             velocity.x *= deltaTime.asSeconds();
             velocity.y *= deltaTime.asSeconds();
             //move is just a setPosition but it adds given argument to actual position so it's basically splayer.setPosition(sf:Vector2f(position.x + velocity.x,position.y + velocity.y));
             splayer.move(velocity);
    

    【讨论】:

      【解决方案2】:

      不要在轮询事件循环中使用sf::Keyboard::isKeyPressed-方法!此方法提供了一种在程序中任意位置请求关键状态的方法。如果您之前检查过当前轮询事件与您的想法一致,则仅在您的轮询事件循环中编写代码。正如您已经发现的那样,您这样做if(event.type == sf::Event::Closed)。 因此,只需将所有代码(窗口关闭事件除外)移出轮询事件循环即可。 我感觉你不明白事件循环到底是做什么的,所以我给你解释一下: 前一帧中发生的每个事件(例如鼠标事件、按键事件、窗口大小调整等)都会排队,并且轮询事件循环会遍历每个排队的事件。例如,首先您有鼠标移动事件,然后是按键事件。并且您只想在发生一个特定事件时执行一次操作,因此您必须使用此 if 块询问当前事件是否与其搜索的事件匹配。并且做某事。一次。

      顺便说一句:您甚至可以在窗口打开之前调用window.setFramerateLimit(60);,这样您就不会浪费资源来设置每帧的限制。

      【讨论】:

      • 谢谢!在投票事件中让我的精灵移动是一个很大的错误。非常感谢您了解这一点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多