?
我們可以把表面想象成一張畫布, blit 表面就是把一個(gè)表面的某個(gè)區(qū)域 COPY 到另外一個(gè)表面上去。
//The headers
#include " SDL.h"
#include <string>
以上就是我們需要的頭文件了。
//The attributes of the screen
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;
3 個(gè)描述屏幕屬性的變量
SCREEN_BPP 是顏色深度,就是每個(gè)象素用多少為來(lái)表示,我們這里用 4 個(gè)字節(jié)。
//The surfaces that will be used
SDL_Surface *message = NULL;
SDL_Surface *background = NULL;
SDL_Surface *screen = NULL;
接著我們又定義了 3 個(gè)表面,一個(gè)用于顯示背景,一個(gè)用于顯示 Hello World ,還有一個(gè)當(dāng)然是代表屏幕了。
SDL_Surface *load_image( std::string filename )
{
??? //Temporary storage for the image that's loaded
??? SDL_Surface* loadedImage = NULL;
???
??? //The optimized image that will be used
SDL_Surface* optimizedImage = NULL;
好了,我們可以寫一個(gè)自己的圖像裝載函數(shù),該函數(shù)負(fù)責(zé) Load 圖片,并返回一個(gè)經(jīng)過(guò)優(yōu)化的表面,當(dāng)然圖片已經(jīng)在表面上了。
//Load the image
??? loadedImage = SDL_LoadBMP( filename.c_str() );
首先我們使用 SDL_LoadBMP() 函數(shù) Load 一張 BMP 格式的圖片。應(yīng)為位圖是 24 位,所以我們不應(yīng)該立即使用該表面,因?yàn)槠聊皇?/span> 32 位的。如果在二各具有不同 format 表面進(jìn)行 Blit ,那么 SDL 將會(huì)不停地進(jìn)行格式之間的轉(zhuǎn)換,程序就會(huì)變得很慢。 .
??? if( loadedImage != NULL )
??? {
??????? //Create an optimized image
?? ?????optimizedImage = SDL_DisplayFormat( loadedImage );
???????
??????? //Free the old image
??????? SDL_FreeSurface( loadedImage );
}
以上幾行代碼檢查了圖片是否被正確加載了,如果有錯(cuò)誤的話,那么 loadedImage 將是 NULL 。
SDL_DisplayFormat() 用于創(chuàng)建一個(gè)和屏幕表面相同格式的 Surface 。之所以這樣做就是為了加快程序速度,避免 SDL 類庫(kù)在對(duì)二個(gè)不同格式表面進(jìn)行 Blit 時(shí)進(jìn)行格式轉(zhuǎn)換。
好了,現(xiàn)在我們擁有二個(gè)表面了,一個(gè)上面有圖片,還有一個(gè)是前一個(gè)經(jīng)過(guò)格式轉(zhuǎn)換得到的。
因?yàn)榈谝槐砻嫖覀儾恍枰耍晕覀兙鸵尫诺簦?/span> SDL_FreeSurface() 函數(shù)就是干這件事情的。
??? //Return the optimized image
??? return optimizedImage;
}
好了,我們返回經(jīng)過(guò)優(yōu)化的表面。
void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination )
{
??? //Make a temporary rectangle to hold the offsets
??? SDL_Rect offset;
???
??? //Give the offsets to the rectangle
??? offset.x = x;
offset.y = y;
接下來(lái),我們?cè)賹懸粋€(gè) Blit 函數(shù)。 X,Y 是目標(biāo)表面的偏移量,另外二個(gè)自然是要進(jìn)行 Blit 的二個(gè)表面了。
首先我們把偏移量塞入到一個(gè) SDL_Rect 變量里面,這樣做的原因很簡(jiǎn)單,就是 SDL_BlitSurface 只接受 SDL_Rect 結(jié)構(gòu)中的偏移。
SDL_Rect 結(jié)構(gòu)代表一個(gè)長(zhǎng)方形 . 它有四個(gè)成員,左上角的坐標(biāo),長(zhǎng)和寬。
??? //Blit the surface
??? SDL_BlitSurface( source, NULL, destination, &offset );
}
好了,調(diào)用 SDL_BlitSurface 實(shí)現(xiàn) Blit 。第二個(gè)參數(shù)是源表面的要被 Blit 的區(qū)域,我們用 NULL 表示要對(duì)整個(gè)源表面進(jìn)行 Blit 。
int main( int argc, char* args[] )
{
??? if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
??? {
??????? return 1;???
??? }
在 SDL_Init() 函數(shù)中,我們使用 SDL_INIT_EVERYTHING 參數(shù),表示我們希望啟動(dòng)所有 SDL 子系統(tǒng),其中包括,視頻,聲音,時(shí)間,以及其他一些制作游戲所用到的組建。
?? screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );
現(xiàn)在我們用 SDL_SetVideoMode 函數(shù)新建一個(gè)窗口,它返回一個(gè)指向窗口表面的指針,這樣我們就可以把圖像往屏幕上 Blit 了。
??? if( screen == NULL )
??? {
??????? return 1;???
??? }
如果函數(shù)有問(wèn)題的話,就返回 NULL 。下面我們也可以改變一下窗口的標(biāo)題。 ??? SDL_WM_SetCaption( "Hello World", NULL );
?? message = load_image( "hello_world.bmp" );
?? background = load_image( "background.bmp" );
?? apply_surface( 0, 0, background, screen );
現(xiàn)在我們把背景 Blit 到屏幕上,在 Blit 背景之前,窗口是黑色,如下圖。
再這之后,窗口的背景就改變了。
用同樣的方法,我們把 message 也 Blit 到屏幕上去。
apply_surface( 180, 140, message, screen );
??? if( SDL_Flip( screen ) == -1 )
??? {
??????? return 1;???
??? }
雖然我們把背景表面和消息表面都 Blit 到屏幕表面上去了,窗口還是一片漆黑,因?yàn)槲覀儧](méi)有調(diào)用 SDL_Flip 函數(shù)來(lái)更新窗口,記住,屏幕表面是建立在系統(tǒng)內(nèi)存當(dāng)中的。
? SDL_Delay( 2000 );
好了,讓窗口停頓二秒,以免我們什么也不到。
??? //Free the surfaces
??? SDL_FreeSurface( message );
??? SDL_FreeSurface( background );
???
??? //Quit SDL
??? SDL_Quit();
???
??? //Return
??? return 0;
}
好了,我們的主函數(shù)也寫完了,最后我釋放了二個(gè)表面,并調(diào)用了 SDL_Quit 函數(shù),清理我們所使用到其他資源。
好了,運(yùn)行一下程序,你不意外你就能看到如下的效果了。如果有什么錯(cuò)誤的話,看看第一個(gè)教程。