如何顺利移动精灵?

时间:2016-02-04 01:58:43

标签: c++ animation sprite codeblocks sfml

我用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;
}

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

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

顺便说一下:您可以在窗口打开之前致电window.setFramerateLimit(60);,这样您就不会在每帧设置限制时浪费资源。