您的位置:首頁 > 軟件教程 > 教程 > SDL窗口和背景色繪制

SDL窗口和背景色繪制

來源:好特整理 | 時間:2024-06-14 08:57:20 | 閱讀:157 |  標(biāo)簽: 2 一個 S   | 分享到:

在上一篇文章中我們已經(jīng)利用 SDL 的日志接口實現(xiàn)了簡單的字符串輸出,實際上是解決了開發(fā)環(huán)境搭建問題,接下來我們將在已有代碼的基礎(chǔ)上繼續(xù)開發(fā),實現(xiàn)第一個窗口的創(chuàng)建和背景色繪制。 初始化 首先設(shè)置日志輸出級別: SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE

在上一篇文章中,我們利用SDL的日志接口實現(xiàn)了簡單的字符串輸出,解決了開發(fā)環(huán)境搭建問題。接下來,我們將在已有代碼的基礎(chǔ)上繼續(xù)開發(fā),實現(xiàn)第一個窗口的創(chuàng)建和背景色繪制。

初始化

首先,設(shè)置日志輸出級別:

SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE);

由于仍處于開發(fā)階段,我們將輸出日志級別設(shè)置為最低的VERBOSE。這樣可以使所有的日志都輸出,有助于觀察SDL的運行情況。當(dāng)出現(xiàn)錯誤時,可以獲得盡可能詳細(xì)的出錯信息,有助于快速定位問題。

接下來,初始化SDL庫,參數(shù) SDL_INIT_VIDEO 指定初始化的子系統(tǒng)為視頻系統(tǒng):

if (SDL_Init(SDL_INIT_VIDEO) < 0) {
    SDL_Log("SDL_Init failed: %s", SDL_GetError());
    return -1;
}

實際上,這一步可以省略,因為在調(diào)用SDL API時其內(nèi)部會自行檢查和初始化所需使用的子系統(tǒng)。比如接下來要使用的 SDL_CreateWindow 函數(shù),內(nèi)部有這樣的代碼:

if (!_this) {
    /* Initialize the video system if needed */
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        return NULL;
    }

    ...
}

其中 _this 是視頻子系統(tǒng)初始化完成后設(shè)置的全局變量。雖然不是必須的,但我們?nèi)匀唤ㄗh調(diào)用 SDL_Init 對主要用到的子系統(tǒng)進行顯式初始化。這樣做有兩個目的:清晰完整地展示出執(zhí)行過程,有助于理解代碼;如果執(zhí)行失敗,可以在第一時間定位出錯位置,提高排障效率。

創(chuàng)建窗口和渲染器

創(chuàng)建一個800x600大小的窗口,然后將其移動到屏幕居中的位置:

SDL_Window* window = SDL_CreateWindow("Hello, SDL3!", 800, 600, SDL_WINDOW_RESIZABLE);
if (!window) {
    SDL_Log("Could not create a window: %s", SDL_GetError());
    return -1;
}

SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);

創(chuàng)建和窗口關(guān)聯(lián)的渲染器:

SDL_Renderer* renderer = SDL_CreateRenderer(window, nullptr);
if (!renderer) {
    SDL_Log("Create renderer failed: %s", SDL_GetError());
    return -1;
}

所有圖形圖像都是通過渲染器繪制到窗口。以背景色繪制為例,代碼如下:

SDL_SetRenderDrawColor(renderer, 16, 0, 16, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);

這里使用的背景色是RGB(16, 0, 16)。這種顏色值常見于曾經(jīng)使用DirectDraw渲染視頻的老手們。但這里只是為了和SDL窗口默認(rèn)的黑色區(qū)分,便于觀察渲染結(jié)果,沒有其他特殊效果。

事件循環(huán)

SDL有兩種方式獲取事件隊列中的事件:

  1. SDL_PollEvent 類似Win32 API中的PeekMessage,無論隊列中有無事件都會立即返回;區(qū)別只是返回值不同。
  2. SDL_WaitEvent 類似Win32 API中的WaitMessage,如果隊列中沒有事件會阻塞等待,直到收到第一個事件才返回。

我們使用第二種方式實現(xiàn)事件循環(huán):

SDL_Event event{};
bool keep_going = true;

while (keep_going) {
    SDL_WaitEvent(&event);

    switch (event.type) {
        case SDL_EVENT_QUIT: {
            keep_going = false;
            break;
        }

        case SDL_EVENT_KEY_DOWN: {
            keep_going = keep_going && (event.key.keysym.sym != SDLK_ESCAPE);
            break;
        }

        case SDL_EVENT_WINDOW_EXPOSED: {
            SDL_SetRenderDrawColor(renderer, 16, 0, 16, 255);
            SDL_RenderClear(renderer);
            SDL_RenderPresent(renderer);
            break;
        }
    }
}

SDL_EVENT_QUIT 表示點擊了關(guān)閉窗口按鈕,所以收到該事件后跳出循環(huán);

SDL_EVENT_KEY_DOWN 表示鍵盤按下事件。這里我們實現(xiàn)了按下'Esc'鍵退出的功能;

SDL_EVENT_WINDOW_EXPOSED 表示需要對窗口進行重繪,所以我們將繪制背景色的代碼放在這個事件中執(zhí)行。

可以在while循環(huán)中增加一行日志來觀察收到了哪些事件:

SDL_Log("Event: %d", event.type);

注意上面這個事件循環(huán)的寫法和大多數(shù)SDL的示例不同。實際上,在這里我們是把SDL當(dāng)作一個正經(jīng)的窗口系統(tǒng)在使用,而不是當(dāng)作一個游戲引擎。兩者一個重要的區(qū)別是使用游戲引擎時一般是按照固定幀率持續(xù)進行窗口重繪,而一般的GUI軟件使用窗口系統(tǒng)時只進行必要的重繪,以最大程度節(jié)省CPU和GPU的使用。視頻雖然也有幀率的概念,但采用的是第二種方式,只在視頻幀刷新時執(zhí)行重繪。

完整代碼

添加退出前清理資源的代碼后,完整的代碼如下:

#include 
#include 

int main(int argc, char* argv[])
{
    SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE);

    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        SDL_Log("SDL_Init failed: %s", SDL_GetError());
        return -1;
    }

    SDL_Window* window =
        SDL_CreateWindow("Hello, SDL3!", 800, 600, SDL_WINDOW_RESIZABLE);
    if (!window) {
        SDL_Log("Could not create a window: %s", SDL_GetError());
        return -1;
    }

    SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);

    SDL_Renderer* renderer = SDL_CreateRenderer(window, nullptr);
    if (!renderer) {
        SDL_Log("Create renderer failed: %s", SDL_GetError());
        return -1;
    }

    SDL_Event event{};
    bool keep_going = true;

    while (keep_going) {
        SDL_WaitEvent(&event);

        switch (event.type) {
            case SDL_EVENT_QUIT: {
                keep_going = false;
                break;
            }

            case SDL_EVENT_KEY_DOWN: {
                keep_going = keep_going && (event.key.keysym.sym != SDLK_ESCAPE);
                break;
            }

            case SDL_EVENT_WINDOW_EXPOSED: {
                SDL_SetRenderDrawColor(renderer, 16, 0, 16, 255);
                SDL_RenderClear(renderer);
                SDL_RenderPresent(renderer);
                break;
            }
        }
        SDL_Log("Event: %d", event.type);
    }

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}

輸出效果如圖:

SDL窗口和背景色繪制 小編推薦閱讀

好特網(wǎng)發(fā)布此文僅為傳遞信息,不代表好特網(wǎng)認(rèn)同期限觀點或證實其描述。

相關(guān)視頻攻略

更多

掃二維碼進入好特網(wǎng)手機版本!

掃二維碼進入好特網(wǎng)微信公眾號!

本站所有軟件,都由網(wǎng)友上傳,如有侵犯你的版權(quán),請發(fā)郵件[email protected]

湘ICP備2022002427號-10 湘公網(wǎng)安備:43070202000427號© 2013~2025 haote.com 好特網(wǎng)