基於Agg的掃雷程序實現

基於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
 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(255255255255));
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
 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, 0x000x000x000xff<<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, 0000);
17
18    return true;
19
20}

21
22}
;
複製代碼

 程序的邏輯比較簡單,就是有點麻煩,因爲天色已晚,剩下的部分留作下一篇再介紹,今天先發個掃雷的界面截圖上來,

 

      初始化了雷盤之後,玩家開始點擊雷盤中的小格子,我們暫且稱之爲Cell,這時候初始化雷盤,要保證當前點擊的地方不爲炸彈,否則,一開始玩就被KO了。

      1、初始化雷盤。初始化代碼主要放在InitInstance 函數中,如下:

 

複製代碼
Code
  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, 0x000x000x000xff<<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, 0000);
 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(255255255255));
 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(20012250));    
 78                }

 79                else if(iL2 % 2 == 1 && iL1 % 2 == 0)
 80                {
 81                    pCell[iL1][iL2]->Draw_Cell(agg::rgba8(2320210));    
 82                }

 83                else if(iL2 % 2 == 0 && iL1 % 2 == 0)
 84                {
 85                    pCell[iL1][iL2]->Draw_Cell(agg::rgba8(132110210));    
 86                }

 87                else if(iL2 % 2 == 1 && iL1 % 2 == 1)
 88                {
 89                    pCell[iL1][iL2]->Draw_Cell(agg::rgba8(0232210));    
 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位激活,下次自動檢測時可以將此位歸爲一個雷。如果第二次點擊,則將標誌位都歸爲,重新給區域畫上背景色。給人一個悔過的機會。這部分代碼在鼠標事件處。

 

 

 

複製代碼
Code
  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(000));        
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
  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, 0000);
 15
 16    bool quit = false;
 17
 18    agg::rgba8 t_color(000);
 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(000));
 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* 32161620);
 95                            rh.ras.add_path(ec);
 96                            rh.ren.color(agg::rgba8(000));
 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* 32161620);
111                                            rh.ras.add_path(ec);
112                                            rh.ren.color(agg::rgba8(000));
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(000));
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* 32161620);
149                        rh.ras.add_path(ec);
150                        rh.ren.color(agg::rgba8(2552550));
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(20012250));    
161                        }

162                        else if(y % 2 == 1 && x % 2 == 0)
163                        {
164                            pcurrent_cell->Draw_Cell(agg::rgba8(2320210));    
165                        }

166                        else if(y % 2 == 0 && x % 2 == 0)
167                        {
168                            pcurrent_cell->Draw_Cell(agg::rgba8(132110210));    
169                        }

170                        else if(y % 2 == 1 && x % 2 == 1)
171                        {
172                            pcurrent_cell->Draw_Cell(agg::rgba8(0232210));    
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的圖。

 

 

發佈了20 篇原創文章 · 獲贊 13 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章