SDL程式設計入門(26)運動

血色v殘陽發表於2020-12-30

運動

現在我們知道了如何渲染、處理輸入和處理時間,我們現在知道了我們需要在螢幕上移動東西的一切。在這裡,我們將做一個基本的程式與一個點移動。

//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

相關文章