signed

QiShunwang

“诚信为本、客户至上”

SDL编程入门(26)运动

2020/12/30 3:32:52   来源:

运动

现在我们知道了如何渲染、处理输入和处理时间,我们现在知道了我们需要在屏幕上移动东西的一切。在这里,我们将做一个基本的程序与一个点移动。

//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
编程之路从0到1