在上一篇文章 SDL 開發實戰(一):SDL介紹及開發環境配置 中,我們配置好了SDL的開發環境,並成功運行了SDL的Hello World 代碼。但是可能大部分人還是讀不太明白具體Hello Wold的代碼的意義。下面我們來根據SDL的使用思路來講解一下SDL核心API,各位可以將此文結合上一篇文章,我們寫的HelloWorld代碼進行理解和思考。
基本的SDL的使用思路,基本分為三部分:初始化 ---> 循環渲染 ---> 銷毀釋放資源。
SDL 初始化相關方法 :
- SDL_Init(): 初始化SDL
- SDL_CreateWindow(): 創建窗口(Window)
- SDL_CreateRenderer(): 基於窗口創建渲染器(Render)
- SDL_CreateTexture(): 創建紋理(Texture)
SDL 渲染數據相關方法:
- SDL_UpdateTexture(): 設置紋理的數據。
- SDL_RenderCopy(): 紋理復制給渲染器。
- SDL_RenderPresent(): 顯示。
SDL 銷毀釋放資源相關方法:
- SDL_DestroyTexture(tex) : 釋放紋理資源
- SDL_DestroyRenderer(ren) : 釋放渲染器
- SDL_DestroyWindow(win) : 釋放窗口
- SDL_Quit() : 關閉所有SDL子系統
下面我們就按照這個順序對核心的API進行講解。
一、初始化函數 SDL_Init()
該初始化函數可以確定希望激活的子系統。函數原型如下:
int SDLCALL SDL_Init(Uint32 flags)
其中Uint32 flags參數為要啟動的子系統的flag值,具體可以傳入的內容如下:
- SDL_INIT_TIMER:定時器
- SDL_INIT_AUDIO:音頻
- SDL_INIT_VIDEO:視頻
- SDL_INIT_JOYSTICK:搖桿
- SDL_INIT_HAPTIC:觸摸屏
- SDL_INIT_GAMECONTROLLER:游戲控制器
- SDL_INIT_EVENTS:事件
- SDL_INIT_NOPARACHUTE:不捕獲關鍵信號(這個不理解)
- SDL_INIT_EVERYTHING:包含上述所有選項
SDL_Init() 的實現位於SDL.c中。定義如下:
int SDL_Init(Uint32 flags) { return SDL_InitSubSystem(flags); }
調用的代碼只有這一句,但是我們能很清楚的了解到,SDL_Init(Uint32 flags)所做的操作就是啟動SDL系統下指定的子系統。再結合我們上面的Hello World代碼,我們可以知道,我們要初始化的是Video子系統。
二、創建窗口 SDL_CreateWindow()
SDL_Window結構體定義了一個SDL2中的窗口。而SDL_CreateWindow()方法就是用於創建一個窗口。函數的原型如下:
SDL_Window * SDLCALL SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags);
下面解釋一下各個參數的含義:
- title :窗口標題
- x :窗口位置x坐標。也可以設置為SDL_WINDOWPOS_CENTERED或SDL_WINDOWPOS_UNDEFINED。
- y :窗口位置y坐標。同上。
- w :窗口的寬
- h :窗口的高
- flags :支持窗口的狀態屬性的標識。包括了窗口的是否最大化、最小化,能否調整邊界等等屬性。
返回創建完成的窗口的ID。如果創建失敗則返回0。
結合我們Hello World代碼,可以知道,我們要展示的窗口的標題為 “Hello World”,窗口的坐標為x = 100, y = 100, 窗口的寬度為640,高度為480,窗口的狀態屬性為SDL_WINDOW_SHOWN,即展示窗口。
三、創建渲染器 SDL_CreateRenderer()
SDL中使用SDL_CreateRenderer()基於窗口創建渲染器。SDL_CreateRenderer()函數的原型如下:
SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags);
下面解釋一下各個參數的含義:
- window : 渲染的目標窗口。
- index :打算初始化的渲染設備的索引。設置“-1”則初始化默認的渲染設備。
- flags :支持以下值(位於SDL_RendererFlags定義中)SDL_RENDERER_SOFTWARE -> 使用軟件渲染;SDL_RENDERER_ACCELERATED -> 使用硬件加速;SDL_RENDERER_PRESENTVSYNC -> 和顯示器的刷新率同步
返回創建完成的渲染器的ID。如果創建失敗則返回NULL。
結合我們的HelloWorld代碼,可以知道,我們要渲染的目標窗口是第二節我們創建的窗口,索引值為默認的渲染設備,設置的渲染屬性為 “使用硬件加速 + 和選時期的刷新率同步”。
四、創建紋理 SDL_CreateTexture()
SDL使用SDL_CreateTexture()基於渲染器創建紋理。SDL_CreateTexture()函數的原型如下:
SDL_Texture * SDLCALL SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int h);
下面解釋一下各個參數的含義:
- renderer:目標渲染器。
- format :紋理的格式。后面會詳述。
- access :可以取以下值(定義位於SDL_TextureAccess中) SDL_TEXTUREACCESS_STATIC -> 變化極少 ; SDL_TEXTUREACCESS_STREAMING :變化頻繁;
- w :紋理的寬
- h :紋理的高
這個函數創建成功則返回紋理的ID,失敗返回0。
五、更新紋理 SDL_UpdateTexture()
SDL使用SDL_UpdateTexture()更新紋理的像素數據。SDL_UpdateTexture()函數的原型如下:
int SDLCALL SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect, const void *pixels, int pitch);
下面解釋一下各個參數的含義:
- texture:目標紋理。
- rect:更新像素的矩形區域。設置為NULL的時候更新整個區域。
- pixels:像素數據。
- pitch:一行像素數據的字節數。
這個函數更新紋理成功的話返回0,失敗的話返回-1。
六、復制紋理到渲染目標 SDL_RenderCopy()
SDL使用SDL_RenderCopy()將紋理數據復制給渲染目標。SDL_RenderCopy()函數的原型如下:
int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect);
下面解釋一下各個參數的含義:
- renderer:渲染目標。
- texture:輸入紋理。
- srcrect:選擇輸入紋理的一塊矩形區域作為輸入。設置為NULL的時候整個紋理作為輸入。
- dstrect:選擇渲染目標的一塊矩形區域作為輸出。設置為NULL的時候整個渲染目標作為輸出。
這個函數執行成功的話返回0,失敗的話返回-1。
七、顯示畫面 SDL_RenderPresent()
SDL使用SDL_RenderPresent()顯示畫面。SDL_RenderPresent()函數的原型如下:
void SDLCALL SDL_RenderPresent(SDL_Renderer * renderer);
其中參數 renderer 用於指定渲染器。
八、SDL 核心 API 使用流程
介紹完了SDL的核心API,將這些API串聯調用的流程步驟如下:
- 初始化:SDL_Init()
- 創建SDL_Window:SDL_CreateWindow()
- 創建SDL_Render:SDL_CreateRenderer()
- 創建SDL_Texture:SDL_CreateTexture()
- 更新SDL_Texture:SDL_UpdateTexture()
- 渲染SDL_Texture:SDL_RenderCopy()
- 顯示:SDL_RenderPresent()
- 返回步驟4繼續執行