问题
目前我们的物体都是以匀速来运动的. 但是现实中能动的物体基本都会有速度变化的过程. 如何实现速度的变化. 这里会用到向量的知识.
向量
向量有2个属性, 方向和大小. 方向就是x和y(针对2D). 大小是 . 代码如下:
// 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;
}
修改其中的帧率可以查看效果