基于Agg的扫雷程序实现
摘要:agg是一个非常优秀的开源矢量图形库,还有一个类似的库是Cairo。与Cairo相比,Agg的效率更高,网上有人做了一个比喻,Agg是一堆进口车零件,而Cairo是一辆完整的国产车。
这意味着Agg使用Agg需要我们自己对其进行封装,它提供从最原始的显存操作到最终的反走样操作的类的封装,只要细心研究它的文档,还是比较容易上手的。当然对图形渲染的流水线有个认识,能够更好的理解图形库,好了废话不多说,下面进入正题。
我们选择在Windows Vs2005下开发扫雷程序,窗口系统选择SDL,SDL是一款非常优秀的多媒体工具库,适用于各种嵌入式程序,并且是跨平台的。
1、首先新建一个vs2005的Win32工程。 配置Agg库,把agg 库源码放进工程,在工具 –>选项->项目和解决方案里面将包含目录 及 源码项分别增加一项 具体的值就是我们的当前的agg目录。
配置SDL将SDL将两个lib文件放入microsoft visual stdio8里面的vc目录的lib目录,
在include目录下建个sdl目录, 将头文件放进去 在工具->选项->项目解决方案 ,将此目录包含在内。
在 项目 –>项目属性(最下面一个)里面 链接器 输入里面增加对lib的引用
最后将sdl的dll文件放入system32目录下。
至此环境配置完毕。
2、封装一个渲染引擎,以便我们能够实现画东西,我们封装一个render_handler类,核心代码如下:
Code
1
class render_handler
{
2
public:
3
void init_buffer(const int& w, const int& h, unsigned char*& buffer)
4
{
5
buffer = new unsigned char [w * h * 4];
6
7
rbuf.attach(buffer, w, h, w * 4);
8
pixfmt.attach(rbuf);
9
renb.attach(pixfmt);
10
ren.attach(renb);
11
12
renb.clear(agg::rgba8(255, 255, 255, 255));
13
//the same as : memset(buffer, 255, w * h * 4);
14
}
15
16
void render_cell(cell& cl)
17
{
18
ren.color(cl.m_color);
19
ras.add_path(cl.m_path);
20
agg::render_scanlines(ras, sl, ren);
21
}
22
23
void init_scene(const int w_num, const int h_num)
24
{
25
26
//some init code
27
28
}
29
30
public:
31
agg::rendering_buffer rbuf;
32
agg::pixfmt_rgba32 pixfmt;
33
agg::renderer_base<agg::pixfmt_rgba32> renb;
34
agg::renderer_scanline_aa_solid<agg::renderer_base<agg::pixfmt_rgba32> > ren;
35
agg::scanline_p8 sl;
36
agg::rasterizer_scanline_aa<> ras;
37
};
38
39
40
其中的cell类实现了每一个小格子的相关属性信息及实现,
Code
1
class cell
2
{
3
public:
4
cell(int x, int y) : m_x(x), m_y(y)
5
{
6
m_width = cell_width;
7
m_height = cell_height;
8
m_checked = false;
9
m_is_bomb = false;
10
11
}
12
13
cell(int x, int y, int w, int h) : m_x(x), m_y(y), m_width(w), m_height(h)
14
{
15
m_checked = false;
16
m_is_bomb = false;
17
}
18
19
void Draw_Cell(agg::rgba8 color)
20
{
21
m_path.move_to(m_x * cell_width, m_y * cell_height);
22
m_path.line_to(m_x * cell_width , m_y * cell_height + m_height);
23
m_path.line_to(m_x * cell_width + cell_width, m_y * cell_height + m_height);
24
m_path.line_to(m_x * cell_width + m_width, m_y * cell_height);
25
m_color = color;
26
}
27
28
void Cell_On()
29
{
30
31
}
32
33
public:
34
int m_x;
35
int m_y;
36
int m_width;
37
int m_height;
38
bool m_checked;
39
bool m_is_bomb;
40
agg::rgba8 m_color;
41
agg::path_storage m_path;
42
};
以上两个类分别实现了对agg图形库的封装操作,以及缓冲区的绑定,还有一个函数用来初始化SDL,主要代码如下:
Code
1
namespace render_engin
{
2
3
bool initSDL(render_engin::render_handler& rh, SDL_Surface*& screen, SDL_Surface*& surface, unsigned char*& buff, int screen_width, int screen_height )
4

{
5
rh.init_buffer(render_engin::width, render_engin::height, buff);
6
7
int stride = screen_width * (SDL_GetVideoInfo()->vfmt->BytesPerPixel);
8
screen = SDL_SetVideoMode(screen_width, screen_height, 32, SDL_SWSURFACE|SDL_ANYFORMAT);
9
surface = SDL_CreateRGBSurfaceFrom((void* )buff, screen_width, screen_height, SDL_GetVideoInfo()->vfmt->BitsPerPixel, stride, 0x00, 0x00, 0x00, 0xff<<24);
10
11
SDL_WM_SetCaption("Agg_Bomb Game", NULL);
12
13
14
if( SDL_BlitSurface(surface, NULL, screen, NULL) < 0)
15
return false;
16
SDL_UpdateRect(screen, 0, 0, 0, 0);
17
18
return true;
19
20
}
21
22
};
程序的逻辑比较简单,就是有点麻烦,因为天色已晚,剩下的部分留作下一篇再介绍,今天先发个扫雷的界面截图上来,

初始化了雷盘之后,玩家开始点击雷盘中的小格子,我们暂且称之为Cell,这时候初始化雷盘,要保证当前点击的地方不为炸弹,否则,一开始玩就被KO了。
1、初始化雷盘。初始化代码主要放在InitInstance 函数中,如下:
Code
1
BOOL InitInstance()
2

{
3
if((SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO)==-1))
{
4
printf("Could not initialize SDL: %s.\n", SDL_GetError());
5
exit(-1);
6
}
7
8
// segment 1
9
render_engin::initSDL(rh, sdl_screen, sdl_surface, buffer, render_engin::width, render_engin::height);
10
11
//segment 2
12
rh.init_scene(render_engin::width / 32, render_engin::height / 32);
13
return TRUE;
14
}
15
16
//segment 1
17
18
bool initSDL(render_engin::render_handler& rh, SDL_Surface*& screen, SDL_Surface*& surface, unsigned char*& buff, int screen_width, int screen_height )
19

{
20
rh.init_buffer(render_engin::width, render_engin::height, buff);
21
22
int stride = screen_width * (SDL_GetVideoInfo()->vfmt->BytesPerPixel);
23
screen = SDL_SetVideoMode(screen_width, screen_height, 32, SDL_SWSURFACE|SDL_ANYFORMAT);
24
surface = SDL_CreateRGBSurfaceFrom((void* )buff, screen_width, screen_height, SDL_GetVideoInfo()->vfmt->BitsPerPixel, stride, 0x00, 0x00, 0x00, 0xff<<24);
25
26
SDL_WM_SetCaption("Agg_Bomb Game", NULL);
27
28
29
if( SDL_BlitSurface(surface, NULL, screen, NULL) < 0)
30
return false;
31
SDL_UpdateRect(screen, 0, 0, 0, 0);
32
33
return true;
34
35
}
36
37
//segment 2
38
39
namespace render_engin
{
40
41
42
int width = 512;
43
int height = 512;
44
render_engin::cell* pCell[16][16];
45
46
class render_handler
{
47
public:
48
void init_buffer(const int& w, const int& h, unsigned char*& buffer)
49
{
50
buffer = new unsigned char [w * h * 4];
51
52
rbuf.attach(buffer, w, h, w * 4);
53
pixfmt.attach(rbuf);
54
renb.attach(pixfmt);
55
ren.attach(renb);
56
57
renb.clear(agg::rgba8(255, 255, 255, 255));
58
//the same as : memset(buffer, 255, w * h * 4);
59
}
60
61
void render_cell(cell& cl)
62
{
63
ren.color(cl.m_color);
64
ras.add_path(cl.m_path);
65
agg::render_scanlines(ras, sl, ren);
66
}
67
68
void init_scene(const int w_num, const int h_num)
69
{
70
for(int iL1 = 0; iL1 < h_num; iL1 ++)
71
{
72
for(int iL2 = 0; iL2 < w_num; iL2 ++ )
73
{
74
pCell[iL1][iL2] = new cell(iL1, iL2);
75
if(iL2 % 2 == 0 && iL1 % 2 == 1)
76
{
77
pCell[iL1][iL2]->Draw_Cell(agg::rgba8(200, 122, 50));
78
}
79
else if(iL2 % 2 == 1 && iL1 % 2 == 0)
80
{
81
pCell[iL1][iL2]->Draw_Cell(agg::rgba8(232, 0, 210));
82
}
83
else if(iL2 % 2 == 0 && iL1 % 2 == 0)
84
{
85
pCell[iL1][iL2]->Draw_Cell(agg::rgba8(132, 110, 210));
86
}
87
else if(iL2 % 2 == 1 && iL1 % 2 == 1)
88
{
89
pCell[iL1][iL2]->Draw_Cell(agg::rgba8(0, 232, 210));
90
}
91
92
render_cell(*pCell[iL1][iL2]);
93
}
94
}
95
}
96
97
public:
98
agg::rendering_buffer rbuf;
99
agg::pixfmt_rgba32 pixfmt;
100
agg::renderer_base<agg::pixfmt_rgba32> renb;
101
agg::renderer_scanline_aa_solid<agg::renderer_base<agg::pixfmt_rgba32> > ren;
102
agg::scanline_p8 sl;
103
agg::rasterizer_scanline_aa<> ras;
104
};
105
};
在init_map函数中,我们采用srand与rand函数来产生随机数,因为rand函数实际上产生的是伪随机数,srand去得的种子如果相同,rand产生的随机数就相同,所以我们采用系统时间的秒数来初始化srand, 初始化雷盘没什么,不是有雷就是没雷,因为随机函数产生的雷太多,而且过于集中,所以我们做些混淆,撒雷的时候每次隔6列,做六次,对雷数也有限制。
init_count_map计算每个区域周围有几个雷,然后保存起来。方法就是对于每个区域,扫描周围的8个位置,看是否为雷,如果是,就将数值加一,最后的值就是count_map保存的值,也是到时候我们显示的值。
check_map是为了自动展开功能而写的,如果一个区域周围的雷都已探明,此时应该将周围的数字全部展开。方法是对于每一个像素都检查周围的8个相邻区域,递归进行,直到不满足条件。对于一次点击要判断此处是不是雷,如果是则game over,否则显示数字,并探测是否需要自动展开。
如果是右键点击,首先判断是否是雷,如果是雷,则将is_bomb位激活,下次自动检测时可以将此位归为一个雷。如果第二次点击,则将标志位都归为,重新给区域画上背景色。给人一个悔过的机会。这部分代码在鼠标事件处。
Code
1
//初始化地图,假设炸弹去为16 * 16,那么我们的地图去设为18*18
2
//这样做得好处是在计算每个16*16的每个点周围有几个炸弹,
3
//边界点我们可以在18 * 18的地图内设为0
4
void init_map(int p[][18])
5

{
6
7
GetLocalTime( &sys1 );
8
int iCount = 0;
9
10
std::srand(sys1.wSecond);
11
12
for(int iL1 = 1; iL1 < 17; iL1 += 6)
13
{
14
for(int iL2 = 1; iL2 < 17; iL2 ++)
15
{
16
if(iCount < 4)
17
{
18
p[iL1][iL2] = rand() % 2;
19
if(p[iL1][iL2] == 1)
20
iCount ++;
21
}else
22
{
23
p[iL1][iL2] = 0;
24
}
25
}
26
}
27
28
iCount = 0;
29
for(int iL1 = 2; iL1 < 17; iL1 += 6)
30
{
31
for(int iL2 = 1; iL2 < 17; iL2 ++)
32
{
33
if(iCount < 8)
34
{
35
p[iL1][iL2] = rand() % 2;
36
if(p[iL1][iL2] == 1)
37
iCount ++;
38
}else
39
{
40
p[iL1][iL2] = 0;
41
}
42
}
43
}
44
45
iCount = 0;
46
for(int iL1 = 3; iL1 < 17; iL1 += 6)
47
{
48
for(int iL2 = 1; iL2 < 9; iL2 ++)
49
{
50
if(iCount < 20)
51
{
52
p[iL1][iL2] = rand() % 2;
53
if(p[iL1][iL2] == 1)
54
iCount ++;
55
}else
56
{
57
p[iL1][iL2] = 0;
58
}
59
}
60
}
61
62
63
iCount = 0;
64
for(int iL1 = 4; iL1 < 17; iL1 += 6)
65
{
66
for(int iL2 = 1; iL2 < 7; iL2 ++)
67
{
68
if(iCount < 30)
69
{
70
p[iL1][iL2] = rand() % 2;
71
if(p[iL1][iL2] == 1)
72
iCount ++;
73
}else
74
{
75
p[iL1][iL2] = 0;
76
}
77
}
78
}
79
80
81
iCount = 0;
82
for(int iL1 = 5; iL1 < 17; iL1 += 6)
83
{
84
for(int iL2 = 1; iL2 < 7; iL2 ++)
85
{
86
if(iCount < 10)
87
{
88
p[iL1][iL2] = rand() % 2;
89
if(p[iL1][iL2] == 1)
90
iCount ++;
91
}else
92
{
93
p[iL1][iL2] = 0;
94
}
95
}
96
}
97
98
99
iCount = 0;
100
for(int iL1 = 6; iL1 < 17; iL1 += 6)
101
{
102
for(int iL2 = 1; iL2 < 7; iL2 ++)
103
{
104
if(iCount < 10)
105
{
106
p[iL1][iL2] = rand() % 2;
107
if(p[iL1][iL2] == 1)
108
iCount ++;
109
}else
110
{
111
p[iL1][iL2] = 0;
112
}
113
}
114
}
115
116
for(int iL1 = 0; iL1 < 18; iL1 ++)
117
{
118
p[0][iL1] = 0;
119
p[iL1][0] = 0;
120
p[17][iL1] = 0;
121
p[iL1][17] = 0;
122
}
123
}
124
125
//这个函数计算每个点周围有几个炸弹,q数组保存了结果,
126
//p数组是我们上面初始化的炸弹布局图,初始化q只需计算它周围的8个区域是否为炸弹区,
127
//如果是则计数加一,最后的数值就是q[i][j]的值, 0 <= i , j < 16
128
void init_count_map(int p[][18], int q[][16])
129

{
130
for(int iL1 = 0; iL1 < 16; iL1 ++)
131
{
132
for(int iL2 = 0; iL2 < 16; iL2 ++)
133
{
134
q[iL1][iL2] = 0;
135
if(p[iL1 + 1][iL2 + 1] == 0)
136
{
137
for(int iL3 = iL1; iL3 < iL1 + 3; iL3 ++)
138
{
139
for(int iL4 = iL2; iL4 < iL2 + 3; iL4 ++)
140
{
141
if(p[iL3][iL4] == 1)
142
{
143
q[iL1][iL2] ++;
144
}
145
}
146
}
147
148
}else
149
{
150
render_engin::pCell[iL1][iL2]->m_is_bomb = true;
151
}
152
153
}
154
}
155
156
}
157
158
159
//当左键按下时,需要检查当前点是否为雷区,及是否已经被点过,
160
//如果是雷区,而且没检查过,那么就触雷了,
161
//如果不是雷区,则要显示这点的数字,同时要查看这点周围是否全部的雷都已找到,
162
//如果找到,则进行自动展开,这是个递归程序
163
void check_map(int p[][16], render_engin::cell* pcell)
164

{
165
int x = pcell->m_x;
166
int y = pcell->m_y;
167
int iCount = 0;
168
169
for(int iL1 = x- 1; iL1 <= x + 1; iL1 ++)
170
{
171
if(iL1 >= 0 && iL1 <= 15)
172
{
173
for(int iL2 = y - 1; iL2 <= y + 1; iL2 ++)
174
{
175
if(iL2 >= 0 && iL2 <= 15)
176
{
177
if(render_engin::pCell[iL1][iL2]->m_checked == true &&
178
render_engin::pCell[iL1][iL2]->m_is_bomb == true)
179
{
180
iCount ++;
181
}
182
}
183
}
184
}
185
186
}
187
188
if(iCount == p[x][y])
189
{
190
for(int iL1 = x -1; iL1 <= x + 1; iL1 ++ )
191
{
192
if(iL1 >= 0 && iL1 <= 15)
193
{
194
for(int iL2 = y - 1; iL2 <= y + 1; iL2 ++)
195
{
196
if(iL2 >= 0 && iL2 <= 15)
197
{
198
agg::gsv_text t;
199
char buf[20] = "";
200
t.size( 12.0);
201
t.flip(true);
202
203
agg::conv_stroke<agg::gsv_text> ts(t);
204
ts.width(1.6);
205
ts.line_cap(agg::round_cap);
206
if(render_engin::pCell[iL1][iL2]->m_checked == false)
207
{
208
iCount_num ++;
209
render_engin::pCell[iL1][iL2]->m_checked = true;
210
211
sprintf_s(buf, 2, "%d", p[iL1][iL2] );
212
t.start_point((iL1 + 0.3)* 32 , ( iL2 + 0.8) * 32);
213
t.text(buf);
214
rh.ras.add_path(ts);
215
rh.ren.color(agg::rgba8(0, 0, 0));
216
if(iL1 != x && iL2 != y)
217
{
218
check_map(p, render_engin::pCell[iL1][iL2]);
219
}
220
}
221
222
223
224
225
agg::render_scanlines(rh.ras, rh.sl, rh.ren);
226
if( SDL_BlitSurface(sdl_surface, NULL, sdl_screen, NULL) < 0)
227
return ;
228
SDL_UpdateRect(sdl_screen, 0,0,0,0);
229
230
231
}
232
233
}
234
}
235
236
}
237
}
238
}
239
在Main函数中,去掉了Windows的消息循环,用SDL的窗口系统代替,代码如下:
Code
1
int APIENTRY _tWinMain(HINSTANCE hInstance,
2
HINSTANCE hPrevInstance,
3
LPTSTR lpCmdLine,
4
int nCmdShow)
5

{
6
if (!InitInstance ())
7
{
8
return FALSE;
9
}
10
11
12
if( SDL_BlitSurface(sdl_surface, NULL, sdl_screen, NULL) < 0)
13
return false;
14
SDL_UpdateRect(sdl_screen, 0, 0, 0, 0);
15
16
bool quit = false;
17
18
agg::rgba8 t_color(0, 0, 0);
19
render_engin::cell* pcurrent_cell;
20
int x = 0;
21
int y = 0;
22
int prev_x = -1;
23
int prev_y = -1;
24
bool m_init = false;
25
26
27
while(SDL_WaitEvent(&sdl_event) && !quit)
28
{
29
switch(sdl_event.type)
30
{
31
case SDL_MOUSEBUTTONUP:
32
{
33
bool left_down = (sdl_event.button.button == SDL_BUTTON_LEFT);
34
bool right_down = (sdl_event.button.button == SDL_BUTTON_RIGHT);
35
36
if(m_init == false)
37
{
38
m_init = true;
39
init_map(map);
40
map[x + 1][y + 1] = 0;
41
init_count_map(map, count_map);
42
}
43
44
//字体对象,本质是一个0101这样的位图,保存于数组
45
//顺便讲一下,字体有两种,一种是设备相关的,一种是设备无关的
46
//另外一种分法就是位图字体与矢量字体
47
agg::gsv_text t;
48
char buf[20] = "";
49
t.size( 12.0);
50
t.flip(true);
51
52
//conv代表conversion,在agg里面 最开始的东西可能只是一个顶点信息,路径信息。
53
//经过matrix平移缩放旋转之后,生成的屏幕坐标就称为conv_*,再经过裁剪 光栅化之后,
54
//生成像素值还是称为conv,conv就是一个转换的意思,
55
//agg里面非常喜欢一层套一层
56
//agg::rendering_buffer rbuf;
57
//agg::pixfmt_rgba32 pixfmt;
58
//agg::renderer_base<agg::pixfmt_rgba32> renb;
59
//这样做其实是这么回事,rbuf用一个attach方法绑定一块裸的内存区。
60
//这么做得实质是rbuf类对象(也就是rendering_buffer类)内有个 char* m_data;变量
61
//只需要将m_data = 裸的内存区,然后rendering_buffer内封装了一些方法,属性,比如返回内存区的长度,宽度啊
62
//等信息,pixfmt就是多封装了一个像素格式,可以存取每个点的颜色值 rgba分量
63
//所以一层一层的套,说明白了就是针对一快内存区,不断的提供一些写好的方法,
64
//每多套一层,方法越多,封装越复杂,agg给我们提供了不同层次的封装,像是一些进口车零件
65
//cairo windows GDI等则相当与一台破的国产车,虽然好用,但是低效,agg内的算法则高明的多
66
agg::conv_stroke<agg::gsv_text> ts(t);
67
ts.width(1.6);
68
ts.line_cap(agg::round_cap);//这里是设置线的拐角处为圆
69
70
if(iCount_num == 256)
71
{
72
::MessageBoxA(NULL,"Yeah, you win!",NULL,MB_OK);;
73
}
74
75
if(left_down) // 单击左键
76
{
77
if(pcurrent_cell->m_checked == false) //如果这个点还没有被扫过
78
{
79
iCount_num ++;
80
pcurrent_cell->m_checked = true;
81
if(map[x + 1][y + 1] == 0) //当前点不是炸弹
82
{
83
sprintf_s(buf, 2, "%d", count_map[x][y] );
84
t.start_point((x + 0.3)* 32 , ( y + 0.8) * 32);
85
t.text(buf);
86
rh.ras.add_path(ts);
87
rh.ren.color(agg::rgba8(0, 0, 0));
88
check_map(count_map, pcurrent_cell); //做检查,看看是否需要连环展开,并标记当前点周围的炸弹数
89
}
90
else //当前点为炸弹
91
{
92
//this place is a bomb
93
pcurrent_cell->m_is_bomb = true;
94
agg::ellipse ec(x * 32 + 16, (y + 0.5) * 32, 16, 16, 20);
95
rh.ras.add_path(ec);
96
rh.ren.color(agg::rgba8(0, 0, 0));
97
SDL_WM_SetCaption("Sorry you lose your game!", NULL);
98
99
//展开剩下的炸弹
100
for(int iL1 = 0; iL1 < 16; iL1 ++)
101
{
102
for(int iL2 = 0; iL2 < 16; iL2 ++)
103
{
104
if(render_engin::pCell[iL1][iL2]->m_checked == false)
105
{
106
render_engin::pCell[iL1][iL2]->m_checked = true;
107
if(map[iL1 + 1][iL2 + 1] != 0)
108
{
109
pcurrent_cell->m_is_bomb = true;
110
agg::ellipse ec(iL1 * 32 + 16, (iL2 + 0.5) * 32, 16, 16, 20);
111
rh.ras.add_path(ec);
112
rh.ren.color(agg::rgba8(0, 0, 0));
113
}
114
else
115
{
116
sprintf_s(buf, 2, "%d", count_map[iL1][iL2] );
117
t.start_point((iL1 + 0.3)* 32 , ( iL2 + 0.8) * 32);
118
t.text(buf);
119
rh.ras.add_path(ts);
120
rh.ren.color(agg::rgba8(0, 0, 0));
121
}
122
agg::render_scanlines(rh.ras, rh.sl, rh.ren);
123
if( SDL_BlitSurface(sdl_surface, NULL, sdl_screen, NULL) < 0)
124
return false;
125
SDL_UpdateRect(sdl_screen, 0,0,0,0);
126
}
127
}
128
}
129
GetLocalTime(&sys2);
130
int minute = sys2.wMinute - sys1.wMinute;
131
int second = sys2.wSecond - sys1.wSecond;
132
::MessageBoxA(NULL,"sorry you lose your game!",NULL,MB_OK);;
133
}
134
}
135
136
137
}else if(right_down) //标记炸弹,
138
{
139
if(pcurrent_cell->m_checked == false)//没被检查,
140
{
141
142
pcurrent_cell->m_checked = true;
143
if(map[x + 1][y + 1] != 0) //确实是炸弹
144
{
145
iCount_num ++;
146
pcurrent_cell->m_is_bomb = true;//确实是炸弹,则将是炸弹设为真
147
}
148
agg::ellipse ec(x * 32 + 16, (y + 0.5) * 32, 16, 16, 20);
149
rh.ras.add_path(ec);
150
rh.ren.color(agg::rgba8(255, 255, 0));
151
}
152
else//已经检查过,此时有回退功能,将已经检查的地方重新设为盲区
153
{ //这里有点小问题,本来是应该只有我们假定是雷的区域才能回退,这里数字也退了
154
//没做判断,扫雷真的比较麻烦,呵呵
155
iCount_num --;
156
pcurrent_cell->m_checked = false;
157
158
if(y % 2 == 0 && x % 2 == 1)
159
{
160
pcurrent_cell->Draw_Cell(agg::rgba8(200, 122, 50));
161
}
162
else if(y % 2 == 1 && x % 2 == 0)
163
{
164
pcurrent_cell->Draw_Cell(agg::rgba8(232, 0, 210));
165
}
166
else if(y % 2 == 0 && x % 2 == 0)
167
{
168
pcurrent_cell->Draw_Cell(agg::rgba8(132, 110, 210));
169
}
170
else if(y % 2 == 1 && x % 2 == 1)
171
{
172
pcurrent_cell->Draw_Cell(agg::rgba8(0, 232, 210));
173
}
174
175
rh.render_cell(*pcurrent_cell);
176
}
177
178
179
}
180
181
agg::render_scanlines(rh.ras, rh.sl, rh.ren);
182
if( SDL_BlitSurface(sdl_surface, NULL, sdl_screen, NULL) < 0)
183
return false;
184
SDL_UpdateRect(sdl_screen, 0,0,0,0);
185
186
break;
187
}
188
case SDL_MOUSEBUTTONDOWN:
189
{
190
191
192
break;
193
}
194
case SDL_MOUSEMOTION:
195
{
196
//这里获取x y值,本来不必要在这里获取的,只是我想做鼠标移动的特效,
197
//后来把特效撤消了,所以在这里保存了x y 值
198
x = sdl_event.motion.x / render_engin::cell_width;
199
y = sdl_event.motion.y / render_engin::cell_height;
200
pcurrent_cell = render_engin::pCell[x][y];
201
202
prev_x = x;
203
prev_y = y;
204
205
206
207
208
break;
209
}
210
211
case SDL_QUIT:
212
quit = true;
213
break;
214
215
default:
216
break;
217
}
218
}
219
220
return 0;
221
}
这个程序做得并不好 ,只是简单的做了些功能进去,当时只是为了熟悉Agg随便做着玩的,好了 最后上一张游戏GameOver的图。
