不知不覺都作到這裏了,是否是再學習完音頻以後就考慮作個小遊戲呢?惋惜不會PS呢... ios
國慶天天的娛樂活動就是搞搞SDL,和朋友打打籃球,看看電影,吃吃美食之類的,很爽了。
哈哈,切入正題吧,今天學習SDL如何進行圖片分割,若是使圖片動起來,在貼代碼以前,博主說幾句廢話:
雖然咱們如今寫的是測試Demo,但不要覺得就能夠隨意爲之,良好的代碼風格和設計思想在哪都是須要注意的 數組
下面來看看博主的工程結構:
ide
工程下多了一個sheet.jpg,這就是今天要用於切割的圖片
函數
圖片是400 * 400 pixel(像素)
接下來咱們要作的工做就是,把這張圖切割成4個圓,而且把背景變成透明 學習
說明:博主在SDL_fun.h這個頭文件中增長了一個類,用於管理全局惟一的屏幕接口,個人考慮是,screen surface實際上只須要創建一個。而且,其餘的surface實際上都是「依賴」於這個surface才能顯示出來的。在SDL中,屢次SDL_SetVideoMode()的效果其實是保留了最後一次的surface做爲了screen surface,因此,屢次SDL_SetVideoMode()實際上是沒有實際意義的。 測試
/* * SDL_fun.h * * Created on: 2013-10-1 * Author: Christian */ #ifndef SDL_FUN_H_ #define SDL_FUN_H_ #include <iostream> #include <SDL/SDL.h> class ScreenSurface{ public: ScreenSurface(SDL_Surface* screen); ScreenSurface(int width, int height, int bpp = 32, Uint32 flags = SDL_SWSURFACE); ~ScreenSurface(void); bool flip(void) const; SDL_Surface* acquire(void); private: SDL_Surface* screen; }; void drawBitmap(ScreenSurface s, const char* fileName); void readKeyboard(ScreenSurface s); void getRadioInfo(ScreenSurface s); void renderPictures(ScreenSurface s, const char* fgFile, const char* bgFile); void drawClips(ScreenSurface s, const char* file, SDL_Rect* clip = NULL, int size = 0); #endif /* SDL_FUN_H_ */你們看到了吧,其中的ScreenSurface的flip方法是將數據化的SDL_Surface Push到屏幕上,讓用戶看到,而acquire是獲取當前的屏幕接口,其餘的就是一些構造方法和構析方法。下面的方法都須要傳一個ScreenSurface,這樣是否是就統一管理了呢?全局就只需建立一個惟一的通向物理屏幕的接口~
頭文件中的drawClips就是圖片分割的方法,下面是它的實現:
ui
/** 圖片切割 */ void drawClips(ScreenSurface s, const char* file, SDL_Rect* clip, int size) { SDL_Surface* dots = IMG_Load(file); SDL_Surface* optimizedImage = NULL; if (s.acquire() == 0 || dots == 0 || clip == NULL) { std::cerr << SDL_GetError() << " 227 \n"; return; } else { optimizedImage = SDL_DisplayFormat(dots); SDL_FreeSurface(dots); //這兩句代碼把圖片背景置爲透明 Uint32 colorkey = SDL_MapRGB(optimizedImage->format, 0, 0xFF, 0xFF); SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY, colorkey); } //把整個背景填充爲白色 SDL_FillRect(s.acquire(), &s.acquire()->clip_rect, SDL_MapRGB(s.acquire()->format, 0xFF, 0xFF, 0xFF)); bool over = false; SDL_Event event; SDL_Rect offset; while (!over) { SDL_ClearError(); SDL_PollEvent(&event); if (event.type == SDL_QUIT || event.key.keysym.sym == SDLK_ESCAPE) { over = true; } //參數size表明圖片切割的數量,也就是clip數組的數量 for (int x = 0; x < size; x++) { offset.x = clip[x].x + x*100; offset.y = clip[x].y + x*100; if (SDL_BlitSurface(optimizedImage, &clip[x], s.acquire(), &offset) != 0) { std::cerr << SDL_GetError() << " 275 \n"; break; } } if (!s.flip()) { std::cerr << SDL_GetError() << " 281\n"; break; } } SDL_FreeSurface(dots); }
再來看看main的入口函數: spa
//=================================================================== // Name : SDL_demo.cpp // Author : Christian // Version : // Copyright : Copyright (c) Christian 2012/9/28 // Description : Hello World in C++, Ansi-style //=================================================================== #include "include/SDL_init.h" #include "include/SDL_fun.h" using namespace std; //這裏定義了4個clip void cutPic(ScreenSurface s){ SDL_Rect clip[4]; //Clip range for the top left clip[0].x = 0; clip[0].y = 0; clip[0].w = 100; clip[0].h = 100; //Clip range for the top right clip[1].x = 100; clip[1].y = 0; clip[1].w = 100; clip[1].h = 100; //Clip range for the bottom left clip[2].x = 0; clip[2].y = 100; clip[2].w = 100; clip[2].h = 100; //Clip range for the bottom right clip[3].x = 100; clip[3].y = 100; clip[3].w = 100; clip[3].h = 100; drawClips(s, "sheet.jpg", clip, 4); } int main(int argc, char* args[]) { //SDL_putenv("SDL_VIDEODRIVER=directx"); //putenv("SDL_VIDEODRIVER=directx"); createSDL("Christian Test"); ScreenSurface s(600, 600); //drawBitmap(s, "3.jpg"); //readKeyboard(); //getRadioInfo(); //renderPictures(s, "3.jpg", "2.bmp"); cutPic(s); atexit(destorySDL); return EXIT_SUCCESS; }
下面是運行效果: 線程
博主是按照官網文檔去作的,爲何圖片背景仍是沒有徹底透明請高手解答一下。 設計
好了,圖片切割完成!下面講講若是對圖片進行移動~第一章的時候我們不是講了SDL的按鍵的事件功能麼,是時候結合一下了~
下面是改動後的drawClips函數:
/** 圖片切割及移動 */ void drawClips(ScreenSurface s, const char* file, SDL_Rect* clip, int size) { SDL_Surface* dots = IMG_Load(file); SDL_Surface* optimizedImage = NULL; if (s.acquire() == 0 || dots == 0 || clip == NULL) { std::cerr << SDL_GetError() << " 227 \n"; return; } else { optimizedImage = SDL_DisplayFormat(dots); SDL_FreeSurface(dots); Uint32 colorkey = SDL_MapRGB(optimizedImage->format, 0, 0xFF, 0xFF); SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY, colorkey); } //把整個背景填充爲白色 SDL_FillRect(s.acquire(), &s.acquire()->clip_rect, SDL_MapRGB(s.acquire()->format, 0xFF, 0xFF, 0xFF)); bool over = false; SDL_Event event; SDL_Rect offset; Uint8* keys; offset.x = 0; offset.y = 0; while (!over) { //從這裏獲取每一個按鍵的即時狀態,監聽8個按鍵,w/s/a/d/up/down/left/right keys = SDL_GetKeyState(0); if (keys[SDLK_UP] || keys[SDLK_w]) { offset.y -= 1; } if (keys[SDLK_DOWN] || keys[SDLK_s]) { offset.y += 1; } if (keys[SDLK_LEFT] || keys[SDLK_a]) { offset.x -= 1; } if (keys[SDLK_RIGHT] || keys[SDLK_d]) { offset.x += 1; } SDL_ClearError(); SDL_PollEvent(&event); if (event.type == SDL_QUIT || event.key.keysym.sym == SDLK_ESCAPE) { over = true; } for (int x = 0; x < size; x++) { // offset.x = clip[x].x; // offset.y = clip[x].y; if (SDL_BlitSurface(optimizedImage, &clip[x], s.acquire(), &offset) != 0) { std::cerr << SDL_GetError() << " 275 \n"; break; } } if (!s.flip()) { std::cerr << SDL_GetError() << " 281\n"; break; } } SDL_FreeSurface(dots); }
很差意思的說,這是我亂按上下左右鍵的結果...
這裏是Freestyletime@foxmail.com,歡迎交流。
本人原創做品,轉載請標明出處。