摘要: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(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
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};
程序的逻辑比较简单,就是有点麻烦,因为天色已晚,剩下的部分留作下一篇再介绍,今天先发个扫雷的界面截图上来,