一、 简介
ClanLib是一个主要针对游戏开发者的跨平台C++框架。尽管API主要为游戏开发设计,你照样可以容易地使用ClanLib来开发一个科学的3D可视化工具或多媒体应用程序(例如Gecko多媒体系统)。
ClanLib拥有各种API-2D和3D图形,声音,网络,I/O,输入,GUI以及资源管理。它还提供透明的OpenGL支持,因此你可以使用本机OpenGL命令而让ClanLib处理依赖于操作系统的窗口管理和其它一切事情。ClanLib通过DirectX或简单的Direct Media Layer(一平台独立的多媒体库)生成2D图形。ClanLib游戏主页上列举了约50多个开发非常成功的游戏,包括以2D和3D形式完成的难题、策略以及射手类游戏。例如,Asteroid Arena(见图1)使用了ClanLib和OpenGL技术,实现了胜人一筹的经典街机游戏。
 图1.Asteroid Arena屏幕快照 |
ClanLib可以工作在Windows,Linux和MacOS操作系统之上,并且提供源码级的zip或tar文件支持。Windows开发者可以使用微软Visual Studio,Borland C++或者MinGW(小型GNU for Windows)编译器和环境。第三方的对于Ruby和Perl语言的绑定支持也是可用的。可选的特效程序包括一个Lua插件(流行的小脚本编程语言)和FreeType(一个免费的TrueType字体库)。
二、 ClanLib特征集
在具体使用API之前,让我们看一下ClanLib的主要特征:
·基本跨平台运行时刻库(GUI,多线程,文件I/O,等等)
·基于模板的C++信号/槽库(类型安全的回调/代理)
·综合的资源管理
·声音混合器支持。WAV文件,Ogg Vorbis,以及由MikMod库(MOD,S3M,XM,等等)支持的任何类型文件
·文档对象模型(DOM)XML分析器支持
·高级2D图形API,支持OpenGL,DirectX和SDL作为着色目标
·高性能的批量着色引擎,当用OpenGL着色2D时
·2D碰撞检测
·2D精灵动画支持
·高度可定制的GUI框架
·从低级到高级的网络库接口
三、 ClanLib基本的游戏模型
现在,让我们仔细分析一下ClanLib API模型。我发现最好的教程是一个完全自解释的示例程序。具体地,让我们分析一下Luke Worth的盒子游戏,这是一个有两个玩家的纸和铅笔游戏(见图2)。这个盒子游戏包含一些格子点,在任意两点间玩家都可以画线。谁用最后一条线画成一个封装的矩形,谁就得一分,并进入到下一轮中。
 图2.一个进行中的盒子游戏,得分情况是蓝8/红3 |
我特意使程序的main函数尽可能简短,这样我们可能集中注意力于高亮处的"游戏循环":
1 #include <iostream> 2 #include <ClanLib/application.h> 3 #include <ClanLib/core.h> 4 #include <ClanLib/display.h> 5 #include <ClanLib/gl.h> 6 #include <ClanLib/sound.h> 7 #include <ClanLib/vorbis.h> 8 9 const int boardsize = 6, spacing = 50, border = 20; 10 const int numsquares = int(pow(float(boardsize - 1), 2)); 11 12 enum coloursquare { off, blue, red }; 13 struct cursor { 14 int x, y; 15 bool vert; 16 }; 17 18 class Boxes: public CL_ClanApplication { 19 bool ver[boardsize][boardsize - 1]; 20 bool hor[boardsize - 1][boardsize]; 21 coloursquare squares[boardsize - 1][boardsize - 1]; 22 bool redturn; 23 bool fullup; 24 cursor curs; 25 26 void inputHandler(const CL_InputEvent &i); 27 bool findsquares(void); 28 inline int numaroundsquare(int x, int y); 29 void init(); 30 void drawBoard(); 31 void endOfGame(); 32 33 public: 34 virtual int Boxes::main(int, char **); 35 } app; 36 37 using namespace std; 40 41 int Boxes::main(int, char **) 42 { 43 int winsize = spacing * (boardsize - 1) + border * 2; 44 try { 45 Boxes::init(); 46 while (!CL_Keyboard::get_keycode(CL_KEY_ESCAPE)) { 47 Boxes::drawBoard(); 48 if (fullup) break; 49 CL_System::keep_alive(20); 50 } 51 Boxes::endOfGame(); 52 53 CL_SetupVorbis::deinit(); 54 CL_SetupSound::deinit(); 55 CL_SetupGL::deinit(); 56 CL_SetupDisplay::deinit(); 57 CL_SetupCore::deinit(); 58 } 59 catch (CL_Error err) { 60 std::cout << "Exception caught: "<< err.message.c_str() << std::endl; 61 } 62 63 return 0; 64 } |
关于这个应用程序,应注意的第一事情是main()函数(见行41)并不是一个最顶层的函数,而是嵌入到一个从CL_ClanApplication派生的对象中。该对象封装了不少难以避免的平台依赖性-这可能包含一个传统的::main()实现(例如在Win32应用程序中必须使用WinMain())。
而且还应注意,事实上所有的可执行的代码(行43-58)被封装在一个try{}/catch{}异常处理器块中。如果需要的话,ClanLib将引发异常,你可以重启一游戏,等等。基本上,所有的游戏逻辑包含在init(),drawBoard(),endOfGame()和inputHandler()这几个方法中。如果board不再移动(fullup==true),则退出游戏循环(行48)。CL_System::keep_alive()更新所有的输入和系统事件(象关闭窗口或者移动它)。这在老式的Win16 API ::Yield()或者Linux上的sleep()中将会释放CPU周期。
66 void Boxes::init() 67 { 68 CL_SetupCore::init(); 69 CL_SetupDisplay::init(); 70 CL_SetupGL::init(); 71 CL_SetupSound::init(); 72 CL_SetupVorbis::init(); 73 74 CL_DisplayWindow window("Boxes", winsize, winsize); 75 CL_SoundOutput output(44100); //选择44Khz采样 76 77 CL_Surface *cursimg = new CL_Surface("cursor.tga"); 78 cursimg->set_alignment(origin_center); 79 CL_Surface *redpict = new CL_Surface("handtransp.tga"); 80 redpict->set_alignment(origin_center); 81 redpict->set_scale(float(spacing)/float(redpict->get_width()), 82 float(spacing)/float(redpict->get_height())); 83 CL_Surface *bluepict = new CL_Surface("circlehandtransp.tga"); 84 bluepict->set_alignment(origin_center); 85 bluepict->set_scale(float(spacing) / float(bluepict->get_width()), 86 float(spacing) / float(bluepict->get_height())); 87 |
这里的init()方法完成大部分的游戏初始化工作。当然,在此需要ClanLib子系统以用于处理图形和声音(行68-72),然后构建一个窗口用于显示所有的图形(行75)。
CL_Surface(行77-87)是一个2D位图类,用于绘制光标,用蓝色填充的方格和用红色填充的方格。
TGA文件是一种位图文件格式。ClanLib有一个集成的PNG库,因此它可以读写最流行的位图文件格式化。
下一步,你必须把板子初始化成一个空状态(行87-103)并执行类似的其它的清理工作以实现新的游戏计数器。
89 90 redturn = true; 91 curs.vert = false; 92 fullup = false; 93 curs.x = curs.y = 1; 94 95 srand(CL_System::get_time()); //启动随机数字生成器 96 97 for (int x = 0; x < boardsize - 1; x++) { 98 for (int y = 0; y < boardsize; y++) 99 hor[x][y] = ver[y][x] = false; 100 101 for (int y = 0; y < boardsize - 1; y++) 102 squares[x][y] = off; 103 104 |
<  
1/2 1 2 下一页 尾页 |