8.物体速度和加速度, 帧率问题

文章目录

问题

目前我们的物体都是以匀速来运动的. 但是现实中能动的物体基本都会有速度变化的过程. 如何实现速度的变化. 这里会用到向量的知识.

向量

向量有2个属性, 方向和大小. 方向就是x和y(针对2D). 大小是 x 2 + y 2 \sqrt{x^2+y^2} . 代码如下:

// Vector2D.h
#ifndef VECTOR2D_H_INCLUDED
#define VECTOR2D_H_INCLUDED

#include <math.h>

class Vector2D
{
public:
    Vector2D(float x, float y) : m_x(x), m_y(y) {}

    float getX() const { return m_x; }
    float getY() const { return m_y; }

    void setX(float x) { m_x = x; }
    void setY(float y) { m_y = y; }

    float length() { return sqrt(m_x * m_x + m_y * m_y); }

    Vector2D operator+(const Vector2D& v2) const
    {
        return Vector2D(m_x + v2.m_x, m_y + v2.m_y);
    }

    friend Vector2D& operator+=(Vector2D& v1, const Vector2D& v2)
    {
        v1.m_x += v2.m_x;
        v1.m_y += v2.m_y;

        return v1;
    }

    Vector2D operator*(float scalar)
    {
        return Vector2D(m_x * scalar, m_y * scalar);
    }

    Vector2D& operator*=(float scalar)
    {
        m_x *= scalar;
        m_y *= scalar;

        return *this;
    }

    Vector2D operator-(const Vector2D& v2) const
    {
        return Vector2D(m_x - v2.m_x, m_y - v2.m_y);
    }

    friend Vector2D& operator-=(Vector2D& v1, const Vector2D& v2)
    {
        v1.m_x -= v2.m_x;
        v1.m_y -= v2.m_y;

        return v1;
    }

    Vector2D operator/(float scalar)
    {
        return Vector2D(m_x / scalar, m_y / scalar);
    }

    Vector2D& operator/=(float scalar)
    {
        m_x /= scalar;
        m_y /= scalar;

        return *this;
    }

    void normalize()
    {
        float L = length();
        if (L > 0) {
            (*this) *= 1 / L;
        }
    }

private:
    float m_x;
    float m_y;
};

#endif // VECTOR2D_H_INCLUDED

有了上述这个向量我们就可以在SDLGameObject.cpp中将m_x和m_y替换掉. 变成如下

// SDLGameObject.h
class SDLGameObject : public GameObject
{
public:
    SDLGameObject(const LoaderParams* pParams);

    virtual void draw();
    virtual void update();
    virtual void clean();

protected:
    Vector2D m_position;
    Vector2D m_velocity;
    Vector2D m_acceleration;

    int m_width;
    int m_height;

    int m_currentRow;
    int m_currentFrame;

    std::string m_textureID;
};

由于我们的向量类实现了+,+=等一系列算术运算. 因此对于一个物体的速度可以有如下处理:
m_position += m_velocity; // 物体移动
m_velocity += m_acceleration; // 物体速度变化, 将m_acceleration置为0, 就是匀速运动.

帧率问题

将上面描述的内容应用到程序中, 如果设置了加速度, 程序运行中可以看到物体一下就消失了. 因为帧率太快, 无法看到加速的过程. 那么对于这个问题, 就引出了帧率的问题. 我们玩游戏应该有体会, 帧率越高, 游戏越流畅, 帧率低, 会感觉卡.

什么是帧率? 单位时间显示多少幅图片就是帧率. 如何实现固定帧率呢? 简单的说就是人为来控制显示时间.
举例:
我们要实现固定60帧. 那么就是说我们显示一帧需要1/60(s)秒, 然后我们记录游戏中显示一帧已经耗时多少. 然后和1/60(s)相比, 如果小于它, 那么剩余时间我们让其睡眠, 从而保证一帧用时1/60(s). 简单代码如下:

#include <SDL.h>
#include <iostream>
#include "Game.h"

using namespace std;

const int FPS = 60;	// 帧率
const int DELAY_TIME = 1000.0f / FPS; // 一帧用时(ms)

int main(int argc, char* argv[])
{
    Uint32 frameStart; // 开始时间
    Uint32 frameTime;  // 渲染一帧已经用时
    
    std::cout << "Game init attempt..\n";

    if (TheGame::Instance()->init("WM brother")) {
        while (TheGame::Instance()->running()) {
            frameStart = SDL_GetTicks();

            TheGame::Instance()->handleEvents();
            TheGame::Instance()->update();
            TheGame::Instance()->render();

            frameTime = SDL_GetTicks() - frameStart;
            if (frameTime < DELAY_TIME) {
                SDL_Delay((int)(DELAY_TIME - frameTime));
            }
        }
    }
    else {
        std::cout << "Game init failure - " << SDL_GetError() << "\n";
    }

    std::cout << "Game closing..\n";
    TheGame::Instance()->clean();

    return 0;
}

修改其中的帧率可以查看效果

猜你喜欢

转载自blog.csdn.net/creambean/article/details/88694495