基于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的图。

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值