用C++實現跨平台遊戲開發之Allegro引擎

提要:本文重點討論開源遊戲開發庫Allegro(Allegro低級遊戲例程),同時涉及到一些深度技術並提供了一個簡單的示例程序,幫你進一步確定它是否是適合你的開發平台。

一、 一個適于多環境的引擎

Allegro最開始被研發于八十年代後期古老的Atari ST平台上,隨後被快速地移植到流行的DJGPP環境(一個在九十年代早期流行的32位的MS-DOS擴展程序)。此後,Allegro被移植到最爲流行的Windows C++開發環境中,包括VS,MinGW,Cygwin和Borland C++。另外的支持它的平台包括linux,BeOS,QNX,Mac OSX以及幾乎任何其它帶有X11庫的Unix平台上。

Allegro能著色到各種類型的位圖和硬件加速的環境中,例如DirectX,XWindows,SVGAlib,FreeBE/AF,CGDirectDisplay,QuickDraw,等等。Allegro並不想提供它自己的3D環境或模擬器,但是OpenGL可以被輕易地集成,這是通過使用AllegroGL庫-它提供了一個類似于GLUT的接口(包括擴展治理)-實現的。

二、 性能概要

在進一步使用API開發前,讓我們看一下Allegro提供的總體功能:

·具體到像素級的繪圖函數,包括平坦陰影,gouraud陰影,紋理貼圖,z緩沖的多邊形和圓繪制,填充,貝塞爾樣條曲線,圖案填充,精靈,blitting(位圖複制),位圖計算縮放和旋轉,半透明/光效果以及比例字體支持的文本輸出

·FLI/FLC(在計算機生成的動畫方面,這種格式比MPEG有更高的壓縮性能)動畫播放器

·播放後台MIDI音樂,可達64種同時的聲音效果,並能錄制樣本波形和MIDI輸入(聲音平台支持,包括WaveOut,DirectSound,OSS,ESD,CoreAudio和QuickTime,等等)

·輕易地存取鼠標,鍵盤,遊戲杆等設備,還支持高分辨率定時器中斷,包括一個DOS版本的垂直折回中斷模擬器

·讀/寫LZSS壓縮文件的例程

·數學函數,包括定點算術,表查找和3D矢量/矩陣/四元數操作

·GUI對話框治理器和文件選擇器

·內建地支持16位和UTF-8格式的Unicode字符

三、 使用引擎

使用Allegro進行開發,就象在許多其它遊戲場合下一樣,遊戲的總體結構都包括遊戲開始前的初始化,遊戲循環以及遊戲完成後的清理。初始化意味著既包含Allegro啓動代碼也包含在開始的位置實現基本地裝載或生成你的遊戲級別。在創建你的初始化代碼時,啓動Allegro基本上沒有什麽代價付出(見圖1).

假如你需要很多屏幕相關的真實性能,建議你首先禮貌地用get_gfx_mode_list()函數查詢一下最大可用方式:

#include <allegro.h> //必須放于系統頭文件的引用之後

set_color_depth(32); // 缺省情況下使用8位顔色

if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {

abort_on_error("Couldn’t set a 32 bit color resolution");

}

set_gfx_mode()的最後兩個參數用于指定虛擬緩沖區的大小-我們的圖形屏幕存儲于其中。這可以使創建一個卷邊遊戲-其中地形是連續移動的-變得輕易。例如,你可能要使虛擬緩沖區,比方說,寬出20%以留出足夠的空間來平滑卷動新的精靈和地形。

用C++實現跨平台遊戲開發之Allegro引擎
更多內容請看C/C++技術專題 C/C++相關文章 J2ME遊戲開發應用專題,或

四、 一個完整的Allegro實例

本教程將使用Kee-Yip Chan的SnookerClone演示程序,它是基于James Lohr的另一個具有相同名字的演示程序。圖1顯示了演示程序的基本屏幕快照。

用C++實現跨平台遊戲開發之Allegro引擎

圖1.Kee-Yip Chan的"SnookerClone"演示程序

這個工程向你展示了許多不同的Allegro技術,包括動畫,鍵盤輸入和鼠標輸入,碰撞和遊戲物理知識(例如重力)。它利用了三個主要的元素:一個有8個扶手的旋轉的車輪,一個用箭頭鍵來控制的大紅球,還有一些從頂部往下墜落的藍球。車輪以接觸方式推動紅球,而當紅球碰上藍球時,它們之間相互影響。

下列是完整的Allegro演示程序的代碼:

1 #include <allegro.h>

2 vector<Point> g_points; //aka球上點的列表

3 vector<Joint> g_joints; //物理對象列表,如車輪和緩沖器

4 kVec g_accControl;

6 int main(void)

7 {

8 allegro_init(); // 初始化allegro.

9 install_keyboard(); // 啓動鍵盤.

10install_mouse(); // 啓動鼠標.

11install_timer(); //過程show_mouse()所需要;

13// 創建一個800x600的非全屏窗口.

14set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0);

16set_window_title("Kee-Yip Chan’s Snooker Clone");

17text_mode(-1); // 文本將被畫在透明的背景之上

19BITMAP* buffer = create_bitmap(SCREEN_W, SCREEN_H);

//創建一張位圖用于雙緩沖.

21 // 初始化數據.

22 create_joints(g_joints); //注冊車輪、地板和緩沖器的硬編碼的屏幕位置

25 // 創建頂點以組成aka球: 玩家所用球和三個藍球

26 // 的位置, 速度, 大小和質量.

27 g_points.push_back(Point(kVec(100, 300),kVec(0, 0),16, 10));

// 玩家.

28 g_points.push_back(Point(kVec(50, 40), kVec(0, 0),12, 5));

// 中等的球.

29 g_points.push_back(Point(kVec(80, 40), kVec(0, 0) 12, 5));

//中等的球.

30 g_points.push_back(Point(kVec(110, 40),kVec(0, 0),6, 1));

// 小球.

32 //主循環,在按ESC鍵後退出

33 while(!key[KEY_ESC]) { //檢查輸入.

34 if(key[KEY_UP])

35 g_accControl.y = -0.07; //Jet pack.向上加速

36 if(key[KEY_LEFT])

37 g_accControl.x = -0.07; //左走.向左加速

38 if(key[KEY_RIGHT])

39 g_accControl.x = 0.07; //右走.向右加速

41 static bool leftMousePRessed = false,

rightMousePressed = false;

42 if(mouse_b & 1) { //鼠標左鍵按下

43 if(!leftMousePressed){

44 leftMousePressed = true; // 創建一個新球.

45 g_points.push_back(Point(kVec(mouse_x, mouse_y),kVec(0, 0), 12, 5));

46 }

47 }

48 if(!(mouse_b & 1))

49 //保證不重複鼠標按鍵

50 //否則,就會出現許多的新球

51 leftMousePressed = false;

52 if(mouse_b & 2) { //鼠標右鍵按下

53 if(!rightMousePressed){

54 rightMousePressed = true; // 創建一個新球

55 g_points.push_back(Point(kVec(mouse_x, mouse_y),kVec(0, 0), 6, 1));

56 }

57 }

58 if(!(mouse_b & 2))

59 //保證不重複鼠標按鍵

60 //否則,就會出現許多的新球.

61 rightMousePressed = false;

63 doPhysics();

65 // 著色:假如我們能再次使用緩沖區,則清除它;

//否則,舊圖像將滯留顯示

66 //用白色進行清除.

67 clear_to_color(buffer, makecol(255, 255, 255));

68 for(unsigned i = 0; i < g_points.size(); i++) {

//畫點.

69 //畫一個實心球

70 circlefill(buffer, //畫向緩沖區

71 g_points[i].position.x,g_points[i].position.y,// aka 球的中心點的位置

72 g_points[i].size, // 半徑.

73 (i == 0) ? makecol(255, 0, 0) : makecol(0, 0, 255)); //紅色假如是玩家;否則爲藍色

75 // 畫一個輪廓球.

76 circle(buffer, //畫向緩沖區

77 g_points[i].position.x,g_points[i].position.y, // aka 球的中心點的位置.

78 g_points[i].size, // 半徑.

79 makecol(0, 0, 0)); //紅色假如是玩家;否則爲藍色.

81 }

83 // 畫接合點

84 for (unsigned i = 0; i < g_joints.size(); i++)

85 line(buffer, //畫向緩沖區

86 g_joints[i].p1.x, g_joints[i].p1.y, // 點 1.

87 g_joints[i].p2.x, g_joints[i].p2.y, // 點 2.

88 makecol(0, 0, 0)); // 黑顔色.

89 );

91 // 打印指令.

92 textout(buffer, font, "Left Mouse Button - new big ball Right Mouse Button - new small ball",

93 125, 1, makecol(0, 0, 0));

95 textout(buffer, font, "Arrow Keys - move red ball",

96 300, 592, makecol(0, 0, 0));

98 show_mouse(buffer); // 畫鼠標光標.

100 draw_sprite(screen, buffer, 0, 0);// 把緩沖區中的數據畫向屏幕.

101 } // while循環結束

103 return 0;

105 }END_OF_MAIN();

33-101行包括了典型的遊戲編程循環模式。遊戲繼續進行直到玩家按下ESC鍵退出爲止。34-39行支持同時進行的鍵盤輸入,因爲你可以按下向上和向左箭頭鍵來獲取粗略的斜向運動。

在41-61行,鼠標動作被捕捉到全局變量mouse_b(用于按鈕),mouse_x和mouse_y。假如你一直在使用一滾輪鼠標,你還可以使用變量mouse_z。我們對反向彈跳邏輯進行了一點硬編碼以確保每次鼠標按下事件只有一個球下落。

第63行調用doPhysics(),其目的是旋轉車輪的線段,更新球位置,檢測球碰撞和適當地改變它們的方向矢量。這個模塊(350行的數學代碼)有點深入了些,但它確實是一個一流的實現,值得你深入研究。

余下的代碼,65-101行,開始著色,在典型的示例程序中這屬于常規實現部分。這裏的著色用典型的雙緩沖區技術,下一次屏幕變化被計算出來並進行脫屏繪制並在最的一毫秒進行緩沖交換(第100行)。這確保了視覺的連續性又減少了煩人的閃爍-對象看上去是隨機地繪制的。在著色代碼部分,對line()和circlefill()的調用是相當直接的:circlefill()以x,y,半徑和填充顔色作爲參數。

textout_ex()函數的功能稍強于textout()(示于92-96行),答應你指定前景和背景顔色。Allegro提供例程以直接從GRX格式.fnt文件,8x8或8x16 BIOS格式.fnt文件,位圖圖象以及數據文件格式中裝入字體。作爲選擇,你能導入一種大範圍的Unicode字體,這可以通過寫一個.txt腳本-它爲每一範圍的字符指定相應的不同的源文件-來實現。假如你想要支持TrueType,那麽你需要AllegroTTF或相同功能的插件。

最後,在第100行的draw_sprite()實現一個覆蓋性複制新生成的位圖到第14行創建的屏幕對象上。覆蓋性複制意指只有非透明的顔色像素被複制。在本例中,我確信它已被退化成一個"blit"(塊複制)轉儲。

五、 Allegro的音頻

這個snooker演示程序只涉及到了一些最基本的圖形和I/O函數,但是並沒有用到Allegro的音頻開發包。該包中的MIDI混頻,音響效果和錄音API,其效果達到或超過幾乎每一個我所見過的專業的聲音庫。Allegro音頻應用軟件大量存在,包括WinCab-一個mp3和OGG Vorbis音樂唱片機,還有LouTronic Rhythm Box-一個鼓聲生成合成器,它具有可全面融合到一起的snare鼓,低音鼓和hi hat的效果。下面我們簡單地回顧Allegro音頻API的一小部分。

每一個使用音頻的程序都應該調用reserve_voices()來指定數字和MIDI聲音驅動程序分別使用的聲音的數目。接下去,你能控制這些音頻軌道的混合.

你可以非常輕易地象下面這樣插入一個音軌:

MIDI *midFile = load_midi("myfile.mid’);

play_midi(midFile, TRUE);//連續循環

對于更複雜的需要,你可以安裝三個鈎子函數之一,它們可以使你攔截MIDI玩家事件。假如被設置爲非NULL,這些例程將在每次MIDI消息,元事件和系統獨占的數據塊中被分別調用。

Allegro的數字音頻系統被設計爲從最基本的配置到可高度擴展的。你能輕易安裝讀取器和寫入器來處理新的或者不同的音頻文件類型, 例如:

register_sample_file_type("mp3",load_mp3,NULL);//安裝MP3讀取器

當正播放數字音頻時,你可以隨時編輯它。下列代碼改變將在播放一個樣本參數時改變該樣本(用于操作循環播放的聲音):

void adjust_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop);

你能改變音量,平移音頻數據並清除循環標志,在下次執行到循環末尾時,這將停止該樣本。假如在播放相同樣本的好幾個副本,這會調整它碰到的第一個副本。假如該樣本沒有播放,對它沒有任何影響。

用C++實現跨平台遊戲開發之Allegro引擎
更多內容請看C/C++技術專題 C/C++相關文章 J2ME遊戲開發應用專題,或

J2ME遊戲開發中時鍾的簡單實現
  在遊戲開發中,有時候我們需要一個時鍾來記錄遊戲的時間,假如時間結束則結束遊戲。本文介紹如何在J2ME中使用Timer和TimerTask來實現這樣一個時鍾,並給出具體代碼實例。       幸運好時機,注冊贏手機  ...查看完整版>>J2ME遊戲開發中時鍾的簡單實現
 
開發經驗談:貪吃蛇遊戲的MIDP實現核心
  相信大家都玩過Nokia手機上的貪吃蛇遊戲。在該遊戲中,玩家操縱一條貪吃的蛇在迷宮裏行走,貪吃蛇按玩家所按的方向鍵折行,蛇頭吃到各種食物(比如大力丸)後,會有各種反應(比如蛇身變長),假如貪吃蛇碰上牆壁或者...查看完整版>>開發經驗談:貪吃蛇遊戲的MIDP實現核心
 
開發經驗談:貪吃蛇遊戲的MIDP實現核心
  相信大家都玩過Nokia手機上的貪吃蛇遊戲。在該遊戲中,玩家操縱一條貪吃的蛇在迷宮裏行走,貪吃蛇按玩家所按的方向鍵折行,蛇頭吃到各種食物(比如大力丸)後,會有各種反應(比如蛇身變長),如果貪吃蛇碰上牆壁或者...查看完整版>>開發經驗談:貪吃蛇遊戲的MIDP實現核心
 
J2ME遊戲開發中時鍾的簡單實現
  在遊戲開發中,有時候我們需要一個時鍾來記錄遊戲的時間,如果時間結束則結束遊戲。本文介紹如何在J2ME中使用Timer和TimerTask來實現這樣一個時鍾,並給出具體代碼實例。   在java.util包中有一個TimerTask類,...查看完整版>>J2ME遊戲開發中時鍾的簡單實現
 
教您如何利用Java Swing實現遊戲開發
  Java咖啡館已經開張不少時日了,如果你已經喜歡上了Java這杯咖啡的味道,那麽記得常來哦。這一次,我們爲大家准備了一大杯香濃的咖啡——將以開發一個“連連看”遊戲爲藍本,和大家共同學習Java中Swing的用法,當...查看完整版>>教您如何利用Java Swing實現遊戲開發
 
J2ME遊戲開發中時鍾的簡單實現
作者:mingjava 文章來源:在遊戲開發中,有時候我們需要一個時鍾來記錄遊戲的時間,如果時間結束則結束遊戲。本文介紹如何在J2ME中使用Timer和TimerTask來實現這樣一個時鍾,並給出具體代碼實例。 在java.u...查看完整版>>J2ME遊戲開發中時鍾的簡單實現
 
C++跨平台遊戲開發之ClanLibSDK
C++跨平台遊戲開發之ClanLibSDK
一、 簡介 ClanLib是一個主要針對遊戲開發者的跨平台C++框架。盡管API主要爲遊戲開發設計,你照樣可以輕易地使用ClanLib來開發一個科學的3D可視化工具或多媒體應用程序(例如Gecko多媒體系統)。 ClanLib擁有各種API...查看完整版>>C++跨平台遊戲開發之ClanLibSDK
 
跨平台的C/C++開發環境——Eclipse/CDT
跨平台的C/C++開發環境——Eclipse/CDT,它又往前邁出了一大步。最讓我贊賞或經常用到的特性:Ø 對編譯工具鏈的完美集成,特別是對GNU的C/C++編譯鏈。對于已有的項目,可以通過把它們導入爲...查看完整版>>跨平台的C/C++開發環境——Eclipse/CDT
 
3D遊戲引擎設計與實現(18)
這幾天已經封裝攝像機類,就可以自由地在地圖裏行走,目前只是添加了5個自由度的攝像機系統。可以向前,向後,向左,向右,向上,向下,X軸旋轉,Y軸旋轉等5個自由度。基本上,就用這個五個自由度,就可以在3D世界裏...查看完整版>>3D遊戲引擎設計與實現(18)
 
 
回到王朝網路移動版首頁