摘要: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類,核心代碼如下:
1class 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類實現了每一個小格子的相關屬性信息及實現,
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,主要代碼如下:
1namespace render_engin{
2
3bool 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 函數中,如下:
1BOOL 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
18bool 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
39namespace render_engin{
40
41
42int width = 512;
43int height = 512;
44render_engin::cell* pCell[16][16];
45
46class render_handler{
47public:
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
97public:
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位激活,下次自動檢測時可以將此位歸爲一個雷。如果第二次點擊,則將標誌位都歸爲,重新給區域畫上背景色。給人一個悔過的機會。這部分代碼在鼠標事件處。
1//初始化地圖,假設炸彈去爲16 * 16,那麼我們的地圖去設爲18*18
2//這樣做得好處是在計算每個16*16的每個點周圍有幾個炸彈,
3//邊界點我們可以在18 * 18的地圖內設爲0
4void 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
128void 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//如果找到,則進行自動展開,這是個遞歸程序
163void 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的窗口系統代替,代碼如下:
1int 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的圖。