运动
现在我们知道了如何渲染、处理输入和处理时间,我们现在知道了我们需要在屏幕上移动东西的一切。在这里,我们将做一个基本的程序与一个点移动。
//The dot that will move around on the screen
class Dot
{
public:
//点的尺寸
static const int DOT_WIDTH = 20;
static const int DOT_HEIGHT = 20;
//点的最大轴速
static const int DOT_VEL = 10;
//Initializes the variables
Dot();
//按键并调整点的速度
void handleEvent( SDL_Event& e );
//移动点
void move();
//在屏幕上显示点
void render();
private:
//点的X和Y偏移量
int mPosX, mPosY;
//点的速度
int mVelX, mVelY;
};
这就是我们要在屏幕上移动的点的类,它有一些常量来定义它的尺寸和速度。它有一个构造函数、一个事件处理程序、一个每帧移动它的函数和一个渲染它的函数。至于数据成员,它有x/y位置和x/y速度的变量。
Dot::Dot()
{
//初始化偏移量
mPosX = 0;
mPosY = 0;
//初始化速度
mVelX = 0;
mVelY = 0;
}
构造函数只需初始化变量。
void Dot::handleEvent( SDL_Event& e ){
//如果按了一个键
if( e.type == SDL_KEYDOWN && e.key.repeat == 0 )
{
//调整速度
switch( e.key.keysym.sym )
{
case SDLK_UP: mVelY -= DOT_VEL; break;
case SDLK_DOWN: mVelY += DOT_VEL; break;
case SDLK_LEFT: mVelX -= DOT_VEL; break;
case SDLK_RIGHT: mVelX += DOT_VEL; break;
}
}
//如果有按键被释放
else if( e.type == SDL_KEYUP && e.key.repeat == 0 )
{
//调整速度
switch( e.key.keysym.sym )
{
case SDLK_UP: mVelY += DOT_VEL; break;
case SDLK_DOWN: mVelY -= DOT_VEL; break;
case SDLK_LEFT: mVelX += DOT_VEL; break;
case SDLK_RIGHT: mVelX -= DOT_VEL; break;
}
}
}
在我们的事件处理程序中,我们将根据按键的按压来设置速度。
你可能想知道为什么我们不在按键时简单地增加位置。如果我们说每次按正确的键都增加X位置,我们就必须重复按正确的键来保持它移动。通过设置速度,我们只需要按一次键就可以了。
如果你想知道为什么我们要检查按键重复是否为0,那是因为默认情况下按键重复是启用的,如果你按住一个键,它就会报告多次按键。这意味着我们必须检查键的按压是否是第一次,因为我们只关心键是什么时候被第一次按下的。
对于那些还没有学过物理的人来说,速度是一个物体的速度/方向。如果一个物体以每帧10像素的速度向右移动,它的速度是10。如果它以每帧10个像素的速度向左移动,它的速度是-10。如果点的速度是10,这意味着10帧后它将移动100个像素。
当我们释放一个键时,我们必须撤销第一次按下它时的速度变化。当我们按下右键时,我们把X速度加到了X速度上。当我们在这里释放右键时,我们从x速度中减去,使其返回到0。
void Dot::move(){
//向左或向右移动点
mPosX += mVelX;
//如果点向左或向右走得太远的话
if( ( mPosX < 0 ) || ( mPosX + DOT_WIDTH > SCREEN_WIDTH ) )
{
//退回
mPosX -= mVelX;
}
//向上或向下移动点
mPosY += mVelY;
//如果点向上或向下走得太远
if( ( mPosY < 0 ) || ( mPosY + DOT_HEIGHT > SCREEN_HEIGHT ) )
{
//退回
mPosY -= mVelY;
}
}
那么这里我们对y轴也做同样的处理。
void Dot::render(){
//显示点
gDotTexture.render( mPosX, mPosY );
}
在渲染函数中,我们在点的位置去渲染点的纹理。
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//将在屏幕上移动的小点
Dot dot;
在进入主循环之前,我们声明一个点对象。
//While application is running
while( !quit )
{
//Handle events on queue
while( SDL_PollEvent( &e ) != 0 )
{
//User requests quit
if( e.type == SDL_QUIT )
{
quit = true;
}
//点的处理输入
dot.handleEvent( e );
}
//移动点
dot.move();
//Clear screen
SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
SDL_RenderClear( gRenderer );
//Render objects
dot.render();
//Update screen
SDL_RenderPresent( gRenderer );
}
最后,我们在主循环中使用我们的点。在事件循环中,我们处理dot的事件。之后,我们更新点的位置,然后将其渲染到屏幕上。
现在,在本教程中,我们将速度作为每帧移动的数量。在大多数游戏中,速度是以每秒为单位的。每帧移动的原因是这样做比较容易,但如果你懂物理学,根据时间来更新点的位置应该不难。如果你不懂物理,就暂时坚持每帧速度。
在 这里下载本教程的媒体和源代码。
原文链接
关注我的公众号:编程之路从0到1