测试Demo,但不要以为就可以随意为之,良好的代码风格和设计思想在哪都是需要注意的
大家看到了吧,其中的ScreenSurface的flip方法是将数据化的SDL_Surface Push到屏幕上,让用户看到,而acquire是获取当前的屏幕接口,其他的就是一些构造方法和构析方法。下面的方法都需要传一个ScreenSurface,这样是不是就统一管理了呢?全局就只需创建一个唯一的通向物理屏幕的接口~
好了,就这么简单~只需在轮询线程内加上事件监听,判断后做出响应即可
运行结果图:
工程下多了一个sheet.jpg,这就是今天要用于切割的图片
图片是400 * 400 pixel(像素)
接下来我们要做的工作就是,把这张图切割成4个圆,并且把背景变成透明
说明:博主在SDL_fun.h这个头文件中增加了一个类,用于管理全局唯一的屏幕接口,我的考虑是,screen surface实际上只需要建立一个。并且,其他的surface实际上都是“依赖”于这个surface才能显示出来的。在SDL中,多次SDL_SetVideoMode()的效果实际上是保留了最后一次的surface作为了screen surface,所以,多次SDL_SetVideoMode()其实是没有实际意义的。
01 |
07 |
08 | #ifndef SDL_FUN_H_ |
09 | #define SDL_FUN_H_ |
10 |
11 | #include |
12 | #include |
13 |
14 | class ScreenSurface{ |
15 |
16 | public : |
17 | ScreenSurface(SDL_Surface* screen); |
18 | ScreenSurface( int width, int height, int bpp = 32, Uint32 flags = SDL_SWSURFACE); |
19 | ~ScreenSurface( void ); |
20 | bool flip( void ) const ; |
21 | SDL_Surface* acquire( void ); |
22 |
23 | private : |
24 | SDL_Surface* screen; |
25 | }; |
26 |
27 | void drawBitmap(ScreenSurface s, const char * fileName); |
28 | void readKeyboard(ScreenSurface s); |
29 | void getRadioInfo(ScreenSurface s); |
30 | void renderPictures(ScreenSurface s, const char * fgFile, const char * bgFile); |
31 | void drawClips(ScreenSurface s, const char * file, SDL_Rect* clip = NULL, int size = 0); |
32 |
33 | #endif |
头文件中的drawClips就是图片分割的方法,下面是它的实现:
01 |
02 | void drawClips(ScreenSurface s, const char * file, SDL_Rect* clip, int size) { |
03 |
04 | SDL_Surface* dots = IMG_Load(file); |
05 | SDL_Surface* optimizedImage = NULL; |
06 |
07 | if (s.acquire() == 0 || dots == 0 || clip == NULL) { |
08 | std::cerr << SDL_GetError() << " 227 \n" ; |
09 | return ; |
10 | } else { |
11 | optimizedImage = SDL_DisplayFormat(dots); |
12 | SDL_FreeSurface(dots); |
13 | //这两句代码把图片背景置为透明 |
14 | Uint32 colorkey = SDL_MapRGB(optimizedImage->format, 0, 0xFF, 0xFF); |
15 | SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY, colorkey); |
16 | } |
17 |
18 | //把整个背景填充为白色 |
19 | SDL_FillRect(s.acquire(), &s.acquire()->clip_rect, |
20 | SDL_MapRGB(s.acquire()->format, 0xFF, 0xFF, 0xFF)); |
21 |
22 | bool over = false ; |
23 | SDL_Event event; |
24 | SDL_Rect offset; |
25 | while (!over) { |
26 |
27 | SDL_ClearError(); |
28 | SDL_PollEvent(&event); |
29 | if (event.type == SDL_QUIT || event.key.keysym.sym == SDLK_ESCAPE) { |
30 | over = true ; |
31 | } |
32 | //参数size代表图片切割的数量,也就是clip数组的数量 |
33 | for ( int x = 0; x < size; x++) { |
34 |
35 | offset.x = clip[x].x + x*100; |
36 | offset.y = clip[x].y + x*100; |
37 |
38 | if (SDL_BlitSurface(optimizedImage, &clip[x], s.acquire(), &offset) |
39 | != 0) { |
40 | std::cerr << SDL_GetError() << " 275 \n" ; |
41 | break ; |
42 | } |
43 | } |
44 |
45 | if (!s.flip()) { |
46 | std::cerr << SDL_GetError() << " 281\n" ; |
47 | break ; |
48 | } |
49 | } |
50 |
51 | SDL_FreeSurface(dots); |
52 | } |
再来看看main的入口函数:
01 | //=================================================================== |
02 | // Name : SDL_demo.cpp |
03 | // Author : Christian |
04 | // Version : |
05 | // Copyright : Copyright (c) Christian 2012/9/28 |
06 | // Description : Hello World in C++, Ansi-style |
07 | //=================================================================== |
08 | #include "include/SDL_init.h" |
09 | #include "include/SDL_fun.h" |
10 |
11 | using namespace std; |
12 | //这里定义了4个clip |
13 | void cutPic(ScreenSurface s){ |
14 | SDL_Rect clip[4]; |
15 | //Clip range for the top left |
16 | clip[0].x = 0; |
17 | clip[0].y = 0; |
18 | clip[0].w = 100; |
19 | clip[0].h = 100; |
20 |
21 | //Clip range for the top right |
22 | clip[1].x = 100; |
23 | clip[1].y = 0; |
24 | clip[1].w = 100; |
25 | clip[1].h = 100; |
26 |
27 | //Clip range for the bottom left |
28 | clip[2].x = 0; |
29 | clip[2].y = 100; |
30 | clip[2].w = 100; |
31 | clip[2].h = 100; |
32 |
33 | //Clip range for the bottom right |
34 | clip[3].x = 100; |
35 | clip[3].y = 100; |
36 | clip[3].w = 100; |
37 | clip[3].h = 100; |
38 |
39 | drawClips(s, "sheet.jpg" , clip, 4); |
40 | } |
41 |
42 | int main( int argc, char * args[]) { |
43 | //SDL_putenv("SDL_VIDEODRIVER=directx"); |
44 | //putenv("SDL_VIDEODRIVER=directx"); |
45 |
46 | createSDL( "Christian Test" ); |
47 | ScreenSurface s(600, 600); |
48 |
49 | //drawBitmap(s, "3.jpg"); |
50 | //readKeyboard(); |
51 | //getRadioInfo(); |
52 | //renderPictures(s, "3.jpg", "2.bmp"); |
53 | cutPic(s); |
54 |
55 |
56 | atexit (destorySDL); |
57 |
58 | return EXIT_SUCCESS; |
59 | } |
下面是运行效果:

博主是按照官网文档去做的,为什么图片背景还是没有完全透明请高手解答一下。
好了,图片切割完成!下面讲讲如果对图片进行移动~第一章的时候咱们不是讲了SDL的按键的事件功能么,是时候结合一下了~
下面是改动后的drawClips函数:
01 |
02 | void drawClips(ScreenSurface s, const char * file, SDL_Rect* clip, int size) { |
03 |
04 | SDL_Surface* dots = IMG_Load(file); |
05 | SDL_Surface* optimizedImage = NULL; |
06 |
07 | if (s.acquire() == 0 || dots == 0 || clip == NULL) { |
08 | std::cerr << SDL_GetError() << " 227 \n" ; |
09 | return ; |
10 | } else { |
11 | optimizedImage = SDL_DisplayFormat(dots); |
12 | SDL_FreeSurface(dots); |
13 |
14 | Uint32 colorkey = SDL_MapRGB(optimizedImage->format, 0, 0xFF, 0xFF); |
15 | SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY, colorkey); |
16 | } |
17 |
18 | //把整个背景填充为白色 |
19 | SDL_FillRect(s.acquire(), &s.acquire()->clip_rect, |
20 | SDL_MapRGB(s.acquire()->format, 0xFF, 0xFF, 0xFF)); |
21 |
22 | bool over = false ; |
23 | SDL_Event event; |
24 | SDL_Rect offset; |
25 | Uint8* keys; |
26 | offset.x = 0; |
27 | offset.y = 0; |
28 |
29 | while (!over) { |
30 | //从这里获取每个按键的即时状态,监听8个按键,w/s/a/d/up/down/left/right |
31 | keys = SDL_GetKeyState(0); |
32 | if (keys[SDLK_UP] || keys[SDLK_w]) { |
33 | offset.y -= 1; |
34 | } |
35 | if (keys[SDLK_DOWN] || keys[SDLK_s]) { |
36 | offset.y += 1; |
37 | } |
38 | if (keys[SDLK_LEFT] || keys[SDLK_a]) { |
39 | offset.x -= 1; |
40 | } |
41 | if (keys[SDLK_RIGHT] || keys[SDLK_d]) { |
42 | offset.x += 1; |
43 | } |
44 |
45 | SDL_ClearError(); |
46 | SDL_PollEvent(&event); |
47 | if (event.type == SDL_QUIT || event.key.keysym.sym == SDLK_ESCAPE) { |
48 | over = true ; |
49 | } |
50 |
51 | for ( int x = 0; x < size; x++) { |
52 |
53 | // offset.x = clip[x].x; |
54 | // offset.y = clip[x].y; |
55 |
56 | if (SDL_BlitSurface(optimizedImage, &clip[x], s.acquire(), &offset) |
57 | != 0) { |
58 | std::cerr << SDL_GetError() << " 275 \n" ; |
59 | break ; |
60 | } |
61 | } |
62 |
63 | if (!s.flip()) { |
64 | std::cerr << SDL_GetError() << " 281\n" ; |
65 | break ; |
66 | } |
67 | } |
68 |
69 | SDL_FreeSurface(dots); |
70 | } |
好了,就这么简单~只需在轮询线程内加上事件监听,判断后做出响应即可
运行结果图:
