| 導購 | 订阅 | 在线投稿
分享
 
 
當前位置: 王朝網路 >> c/c++ >> C++跨平台遊戲開發之ClanLibSDK
 

C++跨平台遊戲開發之ClanLibSDK

2008-06-01 02:08:08  編輯來源:互聯網  简体版  手機版  評論  字體: ||
 
 
  一、 簡介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技術,實現了勝人一籌的經典街機遊戲。

C++跨平台遊戲開發之ClanLibSDK


  圖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)。這個盒子遊戲包含一些格子點,在任意兩點間玩家都可以畫線。誰用最後一條線畫成一個封裝的矩形,誰就得一分,並進入到下一輪中。

C++跨平台遊戲開發之ClanLibSDK


  圖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

  ClanLib的一個非凡突出的方面是它避開傳統型應用于許多框架中的回調模型,而引入了"信號和槽"模型。這種模型廣泛應用于Boost C++庫中,並在QT中得到實現。信號代表具有多個目標的回調函數,又在一些類似的系統中稱作"出版者"或者"事件"。信號被連接到一些槽上,它們是回調函數接收器(也稱作事件目標或者訂戶),當信號被"發出"時即被調用。信號具有類型安全的優點,它們避開了在傳統型的框架中的不可避免的cast操作。

  信號和槽被統一治理。在信號和槽中(或者更准確些說是,作爲槽的一部分出現的對象)跟蹤所有的連接,並當任何其一被破壞時能夠自動地斷開信號/槽連接。這能夠使用戶建立信號/槽連接而不需要花費多大的代價來治理那些連接以及所有包含于其中的對象的生命周期。在行105中,你只要捕捉所有的鍵擊("down")事件並確保使用了你自己的inputHandler()(見行168-216)。

  105 CL_Slot keyPRess =

  CL_Keyboard::sig_key_down().connect(this,

  &Boxes::inputHandler);

  現在,你將開始初始化程序的音樂部分。首先,你用一個.wav格式的("binary")音樂文件裝載一個CL_SoundBuffer,然後預備一個會話句柄以爲玩遊戲之用。下一步,你應用一個淡入淡出過濾器來異步地調整音量-在五秒(行 108-112)內把音量從零變化到最大音量的百分之六十。

  106 CL_SoundBuffer *music = new CL_SoundBuffer("linemusic.ogg");

  107 CL_SoundBuffer_session session = music->prepare();

  108 CL_FadeFilter *fade = new CL_FadeFilter(0.0f);

  109 session.add_filter(fade);

  110 session.set_looping(true);

  111 session.play();

  112 fade->fade_to_volume(0.6f, 5000);

  113 }

  drawBoard()方法繪制線段所在的點畫格子圖案,如,每個玩家贏得的紅色的西紅柿和藍色的矢車菊框出的方格,還有模擬的光標。而最重要的代碼行是第165行。CL_Display::flip()交換前後台緩沖區。後台緩沖區是在該幀中你繪制所有圖形的地方,而前台緩沖區是顯示在屏幕上的內容。

  115 void Boxes::drawBoard()

  116 {

  117 CL_Display::clear(redturn ? CL_Color::red : CL_Color::blue);

  118 CL_Display::fill_rect(CL_Rect(border/2, border/2,

  119 winsize - border/2, winsize - border/2),CL_Color::black);

  120

  121 //畫方框

  122 for (int x = 0; x < boardsize - 1; x++)

  123 for (int y = 0; y < boardsize - 1; y++) {

  124 if (squares[x][y] == red) {

  125 CL_Display::fill_rect(CL_Rect(x * spacing + border,y * spacing + border, x * spacing + border +

  spacing,

  127 y * spacing + border + spacing),CL_Gradient(CL_Color::red,

  128 CL_Color::red, CL_Color::tomato, CL_Color::tomato));

  129 redpict->draw(x * spacing + border + spacing / 2,

  130 y * spacing + border + spacing / 2);

  131 }

  132 else if (squares[x][y] == blue) {

  133 CL_Display::fill_rect(CL_Rect(x * spacing + border,

  134 y * spacing + border,x * spacing + border +spacing,

  135 y * spacing + border +spacing),CL_Gradient(CL_Color::blue,

  136 CL_Color::blue, CL_Color::cornflowerblue,CL_Color::cornflowerblue));

  137 bluepict->draw(x * spacing + border + spacing / 2,y * spacing + border + spacing / 2);

  139 }

  140 }

  141

  142 //畫線

  

   143 for (int x = 0; x < boardsize; x++) {

  144 for (int y = 0; y < boardsize - 1; y++) {

  145 if (ver[x][y]) CL_Display::draw_line(x * spacing + border,

  146 y * spacing + border,x * spacing + border,

  147 y * spacing + border+ spacing,CL_Color::yellow);

  148 if (hor[y][x]) CL_Display::draw_line(y * spacing + border,

  149 x * spacing + border,y * spacing + border+ spacing,x * spacing + border,CL_Color::yellow);

  151 }

  152 }

  153

  154 //畫格子

  155 for (int x = 0; x < boardsize; x++)

  156 for (int y = 0; y < boardsize; y++)

  157 CL_Display::draw_rect(CL_Rect(x * spacing + border,

  158 y * spacing + border,x * spacing + border + 2,159 y * spacing + border + 2),CL_Color::white);

  160

  161 //畫光標

  162 if (curs.vert) cursimg->draw((curs.x - 1) * spacing + border,int((curs.y - 0.5) * spacing + border));

  163 else cursimg->draw(int((curs.x - 0.5) * spacing + border),(curs.y - 1) * spacing + border);

  164

  165 CL_Display::flip();

  166 }

  你安裝的inputHandler()函數用于觀察在行105的按鍵信號。這個函數負責處理細節問題-把鍵擊變成遊戲運動,還有最重要的空格或者回車鍵-用于指示當前玩家的一個選擇(行200-210)。然後,你要檢查一下是否已完成了一個"方形"並把控制返回到原來的玩家。

  168 void Boxes::inputHandler(const CL_InputEvent &i)

  169 {

  170 if (redturn) {

  171 switch(i.id) {

  172 case CL_KEY_LEFT:

  173 case CL_KEY_G:

  174 if (curs.x > 1) curs.x--;

  175 break;

  176 case CL_KEY_RIGHT:

  177 case CL_KEY_J:

  178 if (curs.x < boardsize) curs.x++;

  179 break;

  180 case CL_KEY_UP:

  181 case CL_KEY_Y:

  182 if (!curs.vert && curs.y > 1) {

  183 curs.y--;

  184 curs.vert = !curs.vert;

  185 }

  186 else if (curs.vert) curs.vert = false;

  187 break;

  188 case CL_KEY_DOWN:

  189 case CL_KEY_H:

  190 if (curs.vert && curs.y < boardsize) {

  191 curs.y++;

  192 curs.vert = !curs.vert;

  193 }

  194 else if (!curs.vert) curs.vert = true;

  195 break;

  196 }

  197 if (curs.x == boardsize && !curs.vert) curs.x--;

  198 if (curs.y == boardsize && curs.vert)

  curs.vert = false;

  199

  200 if (i.id == CL_KEY_SPACE i.id == CL_KEY_ENTER) {

  201 if (curs.vert) {

  202 if (!ver[curs.x-1][curs.y-1]) {

  203 ver[curs.x-1][curs.y-1] = true;

  204 if (!findsquares()) redturn = !redturn;

  205 }

  206 }

  207 else {

  208 if (!hor[curs.x-1][curs.y-1]) {

  209 hor[curs.x-1][curs.y-1] = true;

  210 if (!findsquares()) redturn = !redturn;

  211 }

  212 }

  213 }

  214 }

  215 }

  最後,由endOfGame()方法計算最後的得分。記住遊戲還沒有結束,直到板子滿了爲止(見行48)或者某人通過按下ESC鍵(見行46)退出。最後,你用大約1秒的時間把音量淡出到0。

  217 void Boxes::endOfGame()

  218 {

  219 // 計數得分

  220 int redscore, bluescore;

  221 redscore = bluescore = 0;

  222 for (int x = 0; x < boardsize - 1; x++)

  223 for (int y = 0; y < boardsize - 1; y++) {

  

   224 if (squares[x][y] == red) redscore++;

  225 else if (squares[x][y] == blue) bluescore++;

  226 }

  227

  228 cout << "Red: " << redscore << "\nBlue: " << bluescore << endl;

  229 if (bluescore != redscore)

  230 cout << (bluescore > redscore ? "Blue" : "Red") << " player wins\n";

  231 else cout << "It was a tie\n";

  232

  233 if (fullup) {

  234 fade->fade_to_volume(0.0f, 1000);

  235 CL_System::sleep(1000);

  236 }

  237 }
 
 
 
上一篇《淺談C/C++內存泄漏及其檢測工具》
下一篇《用VSTS代碼驗證工具捕捉C/C++錯誤》
 
 
 
 
 
 
日版寵物情人插曲《Winding Road》歌詞

日版寵物情人2017的插曲,很帶節奏感,日語的,女生唱的。 最後聽見是在第8集的時候女主手割傷了,然後男主用嘴幫她吸了一下,插曲就出來了。 歌手:Def...

兄弟共妻,我成了他們夜裏的美食

老鍾家的兩個兒子很特別,就是跟其他的人不太一樣,魔一般的執著。兄弟倆都到了要結婚的年齡了,不管自家老爹怎麽磨破嘴皮子,兄弟倆說不娶就不娶,老父母爲兄弟兩操碎了心...

如何磨出破洞牛仔褲?牛仔褲怎麽剪破洞?

把牛仔褲磨出有線的破洞 1、具體工具就是磨腳石,下面墊一個硬物,然後用磨腳石一直磨一直磨,到把那塊磨薄了,用手撕開就好了。出來的洞啊很自然的。需要貓須的話調幾...

我就是掃描下圖得到了敬業福和愛國福

先來看下敬業福和愛國福 今年春節,支付寶再次推出了“五福紅包”活動,表示要“把欠大家的敬業福都還給大家”。 今天該活動正式啓動,和去年一樣,需要收集“五福”...

冰箱異味産生的原因和臭味去除的方法

有時候我們打開冰箱就會聞到一股異味,冰箱裏的這種異味是因爲一些物質發出的氣味的混合體,聞起來讓人惡心。 産生這些異味的主要原因有以下幾點。 1、很多人有這種習...

《極品家丁》1-31集大結局分集劇情介紹

簡介 《極品家丁》講述了現代白領林晚榮無意回到古代金陵,並追隨蕭二小姐化名“林三”進入蕭府,不料卻陰差陽錯上演了一出低級家丁拼搏上位的“林三升職記”。...

李溪芮《極品家丁》片尾曲《你就是我最愛的寶寶》歌詞

你就是我最愛的寶寶 - 李溪芮 (電視劇《極品家丁》片尾曲) 作詞:常馨內 作曲:常馨內 你的眉 又鬼馬的挑 你的嘴 又壞壞的笑 上一秒吵鬧 下...

烏梅的功效與作用以及烏梅的食用禁忌有哪些?

烏梅,又稱春梅,中醫認爲,烏梅味酸,性溫,無毒,具有安心、除熱、下氣、祛痰、止渴調中、殺蟲的功效,治肢體痛、肺痨病。烏梅泡水喝能治傷寒煩熱、止吐瀉,與幹姜一起制...

什麽是脂肪粒?如何消除臉部脂肪粒?

什麽是脂肪粒 在我們的臉上總會長一個個像脂肪的小顆粒,弄也弄不掉,而且顔色還是白白的。它既不是粉刺也不是其他的任何痘痘,它就是脂肪粒。 脂肪粒雖然也是由油脂...

網絡安全治理:國家安全保障的主要方向是打擊犯罪,而不是處置和懲罰受害者

來源:中國青年報 新的攻擊方法不斷湧現,黑客幾乎永遠占據網絡攻擊的上風,我們不可能通過技術手段杜絕網絡攻擊。國家安全保障的主要方向是打擊犯罪,而不是處置和懲罰...

河南夫妻在溫嶺網絡直播“造人”內容涉黃被刑事拘留

夫妻網絡直播“造人”爆紅   1月9日,溫嶺城北派出所接到南京警方的協查通告,他們近期打掉了一個涉黃直播APP平台。而根據掌握的線索,其中有一對涉案的夫妻主播...

如何防止牆紙老化?牆紙變舊變黃怎麽辦?

如何防止牆紙老化? (1)選擇透氣性好的牆紙 市場上牆紙的材質分無紡布的、木纖維的、PVC的、玻璃纖維基材的、布面的等,相對而言,PVC材質的牆紙最不透氣...

鮮肌之謎非日本生産VS鮮肌之謎假日貨是謠言

觀點一:破日本銷售量的“鮮肌之謎” 非日本生産 近一段時間,淘寶上架了一款名爲“鮮肌之謎的” 鲑魚卵巢美容液,號稱是最近日本的一款推出的全新護膚品,産品本身所...

中國最美古詩詞精選摘抄

系腰裙(北宋詞人 張先) 惜霜蟾照夜雲天,朦胧影、畫勾闌。人情縱似長情月,算一年年。又能得、幾番圓。 欲寄西江題葉字,流不到、五亭前。東池始有荷新綠,尚小如...

關于女人的經典語句

關于女人的經典語句1、【做一個獨立的女人】 思想獨立:有主見、有自己的人生觀、價值觀。有上進心,永遠不放棄自己的理想,做一份自己喜愛的事業,擁有快樂和成就...

未來我們可以和性愛機器人結婚嗎?

你想體驗機器人性愛嗎?你想和性愛機器人結婚嗎?如果你想,機器人有拒絕你的權利嗎? 近日,第二屆“國際人類-機器人性愛研討會”大會在倫敦金史密斯大學落下帷幕。而...

全球最變態的十個地方

10.土耳其地下洞穴城市 變態指數:★★☆☆☆ 這是土耳其卡帕多西亞的一個著名景點,傳說是當年基督教徒們爲了躲避戰爭而在此修建。裏面曾住著20000人,...

科學家稱,人類死亡後意識將在另外一個宇宙中繼續存活

據英國《每日快報》報道,一位科學家兼理論家Robert Lanza博士宣稱,世界上並不存在人類死亡,死亡的只是身體。他認爲我們的意識借助我們體內的能量生存,而且...

《屏裏狐》片頭曲《我愛狐狸精》歌詞是什麽?

《我愛狐狸精》 - 劉馨棋   (電視劇《屏裏狐》主題曲)   作詞:金十三&李旦   作曲:劉嘉   狐狸精 狐狸仙   千年修...

 
 
 
一、 簡介 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技術,實現了勝人一籌的經典街機遊戲。 [url=/bbs/detail_1785417.html][img]http://image.wangchao.net.cn/it/1323423490174.jpg[/img][/url] 圖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)。這個盒子遊戲包含一些格子點,在任意兩點間玩家都可以畫線。誰用最後一條線畫成一個封裝的矩形,誰就得一分,並進入到下一輪中。 [url=/bbs/detail_1785417.html][img]http://image.wangchao.net.cn/it/1323423490343.jpg[/img][/url] 圖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   ClanLib的一個非凡突出的方面是它避開傳統型應用于許多框架中的回調模型,而引入了"信號和槽"模型。這種模型廣泛應用于Boost C++庫中,並在QT中得到實現。信號代表具有多個目標的回調函數,又在一些類似的系統中稱作"出版者"或者"事件"。信號被連接到一些槽上,它們是回調函數接收器(也稱作事件目標或者訂戶),當信號被"發出"時即被調用。信號具有類型安全的優點,它們避開了在傳統型的框架中的不可避免的cast操作。   信號和槽被統一治理。在信號和槽中(或者更准確些說是,作爲槽的一部分出現的對象)跟蹤所有的連接,並當任何其一被破壞時能夠自動地斷開信號/槽連接。這能夠使用戶建立信號/槽連接而不需要花費多大的代價來治理那些連接以及所有包含于其中的對象的生命周期。在行105中,你只要捕捉所有的鍵擊("down")事件並確保使用了你自己的inputHandler()(見行168-216)。 105 CL_Slot keyPRess = CL_Keyboard::sig_key_down().connect(this, &Boxes::inputHandler);   現在,你將開始初始化程序的音樂部分。首先,你用一個.wav格式的("binary")音樂文件裝載一個CL_SoundBuffer,然後預備一個會話句柄以爲玩遊戲之用。下一步,你應用一個淡入淡出過濾器來異步地調整音量-在五秒(行 108-112)內把音量從零變化到最大音量的百分之六十。 106 CL_SoundBuffer *music = new CL_SoundBuffer("linemusic.ogg"); 107 CL_SoundBuffer_session session = music->prepare(); 108 CL_FadeFilter *fade = new CL_FadeFilter(0.0f); 109 session.add_filter(fade); 110 session.set_looping(true); 111 session.play(); 112 fade->fade_to_volume(0.6f, 5000); 113 }   drawBoard()方法繪制線段所在的點畫格子圖案,如,每個玩家贏得的紅色的西紅柿和藍色的矢車菊框出的方格,還有模擬的光標。而最重要的代碼行是第165行。CL_Display::flip()交換前後台緩沖區。後台緩沖區是在該幀中你繪制所有圖形的地方,而前台緩沖區是顯示在屏幕上的內容。 115 void Boxes::drawBoard() 116 { 117  CL_Display::clear(redturn ? CL_Color::red : CL_Color::blue); 118  CL_Display::fill_rect(CL_Rect(border/2, border/2, 119    winsize - border/2, winsize - border/2),CL_Color::black); 120 121  //畫方框 122  for (int x = 0; x < boardsize - 1; x++) 123   for (int y = 0; y < boardsize - 1; y++) { 124    if (squares[x][y] == red) { 125     CL_Display::fill_rect(CL_Rect(x * spacing + border,y * spacing + border, x * spacing + border +         spacing, 127       y * spacing + border + spacing),CL_Gradient(CL_Color::red, 128       CL_Color::red, CL_Color::tomato, CL_Color::tomato)); 129     redpict->draw(x * spacing + border + spacing / 2, 130        y * spacing + border + spacing / 2); 131    } 132    else if (squares[x][y] == blue) { 133      CL_Display::fill_rect(CL_Rect(x * spacing + border, 134      y * spacing + border,x * spacing + border +spacing, 135        y * spacing + border +spacing),CL_Gradient(CL_Color::blue, 136        CL_Color::blue, CL_Color::cornflowerblue,CL_Color::cornflowerblue)); 137      bluepict->draw(x * spacing + border + spacing / 2,y * spacing + border + spacing / 2); 139    } 140   } 141 142   //畫線 143   for (int x = 0; x < boardsize; x++) { 144    for (int y = 0; y < boardsize - 1; y++) { 145     if (ver[x][y]) CL_Display::draw_line(x * spacing + border, 146       y * spacing + border,x * spacing + border, 147       y * spacing + border+ spacing,CL_Color::yellow); 148     if (hor[y][x]) CL_Display::draw_line(y * spacing + border, 149       x * spacing + border,y * spacing + border+ spacing,x * spacing + border,CL_Color::yellow); 151     } 152   } 153 154   //畫格子 155   for (int x = 0; x < boardsize; x++) 156    for (int y = 0; y < boardsize; y++) 157     CL_Display::draw_rect(CL_Rect(x * spacing + border, 158       y * spacing + border,x * spacing + border + 2,159 y * spacing + border + 2),CL_Color::white); 160 161     //畫光標 162     if (curs.vert) cursimg->draw((curs.x - 1) * spacing + border,int((curs.y - 0.5) * spacing + border)); 163     else cursimg->draw(int((curs.x - 0.5) * spacing + border),(curs.y - 1) * spacing + border); 164 165      CL_Display::flip(); 166    }   你安裝的inputHandler()函數用于觀察在行105的按鍵信號。這個函數負責處理細節問題-把鍵擊變成遊戲運動,還有最重要的空格或者回車鍵-用于指示當前玩家的一個選擇(行200-210)。然後,你要檢查一下是否已完成了一個"方形"並把控制返回到原來的玩家。 168 void Boxes::inputHandler(const CL_InputEvent &i) 169 { 170  if (redturn) { 171   switch(i.id) { 172    case CL_KEY_LEFT: 173    case CL_KEY_G: 174     if (curs.x > 1) curs.x--; 175     break; 176    case CL_KEY_RIGHT: 177    case CL_KEY_J: 178     if (curs.x < boardsize) curs.x++; 179     break; 180    case CL_KEY_UP: 181    case CL_KEY_Y: 182     if (!curs.vert && curs.y > 1) { 183      curs.y--; 184      curs.vert = !curs.vert; 185     } 186     else if (curs.vert) curs.vert = false; 187     break; 188    case CL_KEY_DOWN: 189    case CL_KEY_H: 190     if (curs.vert && curs.y < boardsize) { 191      curs.y++; 192      curs.vert = !curs.vert; 193     } 194     else if (!curs.vert) curs.vert = true; 195     break; 196    } 197    if (curs.x == boardsize && !curs.vert) curs.x--; 198    if (curs.y == boardsize && curs.vert)       curs.vert = false; 199 200    if (i.id == CL_KEY_SPACE i.id == CL_KEY_ENTER) { 201     if (curs.vert) { 202      if (!ver[curs.x-1][curs.y-1]) { 203       ver[curs.x-1][curs.y-1] = true; 204       if (!findsquares()) redturn = !redturn; 205      } 206    } 207    else { 208     if (!hor[curs.x-1][curs.y-1]) { 209      hor[curs.x-1][curs.y-1] = true; 210      if (!findsquares()) redturn = !redturn; 211     } 212    } 213   } 214  } 215 }   最後,由endOfGame()方法計算最後的得分。記住遊戲還沒有結束,直到板子滿了爲止(見行48)或者某人通過按下ESC鍵(見行46)退出。最後,你用大約1秒的時間把音量淡出到0。 217 void Boxes::endOfGame() 218 { 219  // 計數得分 220  int redscore, bluescore; 221  redscore = bluescore = 0; 222  for (int x = 0; x < boardsize - 1; x++) 223   for (int y = 0; y < boardsize - 1; y++) { 224    if (squares[x][y] == red) redscore++; 225    else if (squares[x][y] == blue) bluescore++; 226   } 227 228  cout << "Red: " << redscore << "\nBlue: " << bluescore << endl; 229  if (bluescore != redscore) 230   cout << (bluescore > redscore ? "Blue" : "Red") << " player wins\n"; 231  else cout << "It was a tie\n"; 232 233  if (fullup) { 234   fade->fade_to_volume(0.0f, 1000); 235   CL_System::sleep(1000); 236  } 237 }
󰈣󰈤
 
 
 
  免責聲明:本文僅代表作者個人觀點,與王朝網路無關。王朝網路登載此文出於傳遞更多信息之目的,並不意味著贊同其觀點或證實其描述,其原創性以及文中陳述文字和內容未經本站證實,對本文以及其中全部或者部分內容、文字的真實性、完整性、及時性本站不作任何保證或承諾,請讀者僅作參考,並請自行核實相關內容。
 
 
高清美女攝影(8)
高清美女攝影(7)
高清美女攝影(6)
高清美女攝影(5)
痞子的甘南日記
疑是銀河落九天
雪域壩上四——純美色
冬日戀歌——西城楊柳弄輕柔
 
>>返回首頁<<
 
 熱帖排行
 
 
 
 
© 2005- 王朝網路 版權所有