東海大學
3D賽車遊戲之設計
(Design of an 3D Automobile Racing Game)
學生:陳柏翰 陳信益
學 號 :s952956 s942863
指導教授:林祝興老師
日期:99/12/31
目錄
第一章緒論
1.1 摘要.....................................................................p.3
1.2 研究動機.........................................................................p.3
第二章技術背景和概念
2.1 XNA和C# 介紹..................................................p.4
2.2硬體設備的概述....................................................p.5
第三章架構和流程圖
3.1 XNA 基本架構.....................................................p.6
3.2流程圖......................................................................p.11
第四章實作Crazy Racer Game遊戲
4.1 遊戲程式的設計...................................................p.13
4.2 概念圖.....................................................................p.23
4.3賽車遊戲實作截圖..................................................p.25
第五章結論
5.1 心得...........................................................................p.30
5.2 實作困難....................................................................p.32
第六章參考文獻
參考網頁和參考書籍
第一章緒論
1.1 摘要
在這個資訊發達的時代,電子遊戲是日新月異,從早期的2D遊戲只能做平面的上下左右的移動,到現代的3D單機甚至網路遊戲,可以上下左右在加入前後全視角的移動,可說讓遊戲是越做越逼真和真實,也讓玩家們是越玩越起勁。
近十幾年結合網路的迅速發達,把原本只能單人對機件或多人使用同一台機件的單機遊戲,拓展到多人在網際網路或區域網路內共同交互賞玩的網路線上遊戲,把遊戲加入了互動,讓玩家在遊戲中,不僅能享受玩遊戲的娛樂,也能互相交流,認識彼此。
遊戲發展到目前為止已有各式各樣不同玩法和類型的遊戲,可分為動作遊戲、格鬥遊戲、冒險遊戲、模擬遊戲、角色扮演、戰略遊戲、射擊遊戲、競速遊戲、體育遊戲、音樂遊戲和益智遊戲等,而我從小就有在玩EA Sports這家遊戲公司出的遊戲,對體育遊戲和競速遊戲就非常有興趣,在玩遊戲時,都會很羡慕它的場景製作和程式設計,很希望自己也能瞭解製作一套遊戲的整個過程,所以想藉由專題研究的機會,來嘗試著寫一個小的賽車遊戲。
1.2 研究動機
我會想要做賽車遊戲這個主題,原因之一是看到上一屆學長們做的MAYA專題,覺得學習3D動畫還蠻好玩的,所以也想要用一套3D動畫的軟體來製作專題,後來決定挑選3D MAX來研究。一開始想說來製作一部賽車和一些場景(例如:房子、路面等),然後運用時間軸的方式讓賽車在場景中環繞,後來得知老師要求資工專題一定要有程式的部分,我經過幾天的網路和書本查詢和思考要如何把3D MAX和程式結合在一起,最終想用XNA平台寫一個賽車小遊戲並可以用3D MAX建好的賽車模型匯入到XNA平台中,恰好XNA平台是用C#語言所撰寫的,此語言也剛好在大三才學到,所以可說是現學現用。
第二章技術背景
2.1 XNA和C# 介紹
XNA的全名稱為【XNA Game Studio】,是有Microsoft公司所開發的一個跨平台次世代的遊戲開發平台,此遊戲開發平台提供了一個免費的遊戲開發環境。Microsoft公司從2006年年底到2008年底總共開發的四個XNA的版本:
日期 | XNA版本 | 遊戲平台 | 搭配的開發工具 |
2006年12月 | XNA Game Studio Express 1.0 | Visual Studio C# Express 2005 | PC Window、Xbox 360 |
2007年04月 | XNA Game Studio Express 1.0 Refresh | Visual Studio 2005、Visual Studio C# Express 2005 | PC Window、Xbox 360 |
2007年12月 | XNA Game Studio2.0 | Visual Studio 2005、Visual Studio C# Express 2005 | PC Window、Xbox 360 |
2008年10月 | XNA Game Studio3.0 | Visual Studio 2008、Visual Studio C# Express 2008 | PC Window、Xbox 360、Zune |
XNA目前只能使用Microsoft Visual Studio C# Express版本來做為遊戲唯一
標準開發語言的程式,如果使用其他Microsoft Visual Studio版本或是Borland C++ Builder等開發程式,將無發使用這些比較喜歡或熟悉的環境來開發XNA遊戲,不過由於C# Express是免費的開發環境和軟體,而且功能也相當齊全,只要下載即可使用。
XNA以.Net Framework為基礎,並且加入支援遊戲應用需要的函式庫(XNA Framework),由於.Net遊戲開發環境具有很大的優勢,可整合Microsoft目前支持平台整合為一,包含PC Window 、Xbox360遊戲平台,甚至到了2008年出的XNA3.0版本中,多加了一個Zune的遊戲平台。所以使用XNA也可以直接開發Xbox360電視遊樂器的遊戲,並藉由XNA開發者俱樂部來分享給其他擁有Xbox360主機的會員者娛樂試玩。
C#是Microsoft公司為.Net平台設計的程式語言。顧名思義,它也就是擷取了C或C++的物件導向的功能,並且提供類似Visual Basic一樣簡易的使用特性和新的.Net平台自動提供記憶體管理與安全性的優點。
以前一般談到C#,大多把它用在.Net平台上處理做商用行業的一種程式語言。很多實際在遊戲界工作的程式設計師,比較不把它當作遊戲開發主要的程式語言。因為遊戲軟體對效能的需求非常高,需要是兼具高效率與高階語言特性的C或C++語言,才能讓遊戲軟體充分讓電腦使用到每一分效率的支援。但這個傳統的觀念,也因為兩種主要原因而逐漸的被顛覆。
第一,資訊科技的進步,使遊戲越做愈逼真也越寫愈大,而全部的遊戲如果都使用C或C++來開發,其實是很耗費時間和人力的。
第二,程式撰寫到後期越寫越大,超過十萬行C或C++遊戲程式,只要更動一個小地方,可能就要重新編譯一次程式,這個過程是相當浪費時間的。
因此現代的專業遊戲程式開發,大部分是取主要需要速度的程式模組才使用C或C++撰寫,而其他不是以最高執行速度為主的程式模組,就可以改用比C或C++更簡易的「描述語言(script language)」的程式語言來撰寫。
C#正是一個在個人電腦上,可以使用簡化的程式語言,它是經過C和C++的改良與簡化,所以撰寫起來更為容易,也較易被習慣C或C++語言的程式設計師採用。在來是因為個人電腦的硬體進步,在CPU速度越來越快的時代,一款遊戲所有程式模組,已經不需要全部都使用最有效率的C或C++語言開發,只要不是屬於極端需要以速度為主的程式碼,使用C#來開發並不會導致遊戲執行速度的變慢,又可以方便程式設計師撰寫或修改程式。
2.2硬體設備和概述
XNA
顯示卡具有支援Shader Model 1.1(最好是Shader Model 2.0)或3D加速顯示繪圖晶卡
至少1Ghz以上的CPU
至少192MB的記憶卡
作業系統為Window XP或Window Vista
.Net Framework 2.0或.Net Framework 3.5
DirectX 9.0c或更新的版本
Visual Studio Express 2005
第三章架構和流程圖
3.1 XNA 基本架構
撰寫XNA的基本架構:
在設計和撰寫XNA Studio開發遊戲的程式,很重要的兩個觀念是「擴充」和「繼承」:
「擴充」:在寫遊戲程式,是要去擴充XNA Framework的功能,而不是自己把遊戲程式從頭到尾寫一次。XNAFramework是由XNA開發環境所提供的一組事先寫好的程式碼,它提供了一些在開發遊戲過程中,幾乎每次都會用到和最底層的功能,這樣可以簡化開發遊戲軟體的複雜性,就像是提供了一個空的平台,讓程式設計者把專注力著重在遊戲的內容,並加入自己想做的遊戲內容的處理程式,把它擴充成我們自己的遊戲。
「繼承」:當我們在撰寫一些步驟相似和可重複使用的程式碼,都可以將它撰寫成C#的「抽象類別」,然後讓需要用的遊戲類別去繼承它,把抽象類別的行為修改成符合遊戲的需求。
首先介紹XNA遊戲程式的流程。一開始執行遊戲程式的第一畫面是Program.cs程式:
using System;
namespace WindowGame1
{
staticclassProgram
{
staticvoid Main(string[] args)
{
using (Game1 game = newGame1())
{
game.Run();
}
}
}
}
這個程式是由一個靜態類別Program所開始的,類別內是由一個Main( )的靜態方法和兩行程式構成的,第一行Game1 game=new Game1( ),這裡產生一個Game1的物件(此命名要配合下一個要連結的類別檔案名稱來定),然後將其位址放到變數game中,也就是game是Game1的物件參照。第二行game.Run( )是呼叫Game1物件的Run( )方法,讓Run( )方法開始進入XNA程式的流程。
#region Using Statements
using System;
using Microsoft.Xna.Framework; //和XNA架構相關的型別
using Microsoft.Xna.Framework.Audio; //和XNA聲音相關的型別
using Microsoft.Xna.Framework.Content; //和XNA內容輸出入相關的型別
using Microsoft.Xna.Framework.GamerSerivice; //和XNA玩家許可權相關的型別
using Microsoft.Xna.Framework.Graphics; //和XNA繪圖相關的型別
using Microsoft.Xna.Framework.Input; //和XNA輸出操控相關的型別
using Microsoft.Xna.Framework.Storage; //和XNA儲存相關的型別
using Microsoft.Xna.Framework.Media; //和XNA多媒體相關的型別
using Microsoft.Xna.Framework.Net; //和XNA網路相關的型別
#endregion
namespace WindowsGame1
{
publicclassGame1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
ContentManager content;
public Game1()
{
graphics = newGraphicsDeviceManager(this);
content = newContentManager(Services);
}
protectedoverridevoid Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
protectedoverridevoid LoadGraphicsContent(bool loadAllContent)
{
if (loadAllContent)
{
// TODO: Load any ResourceManagementMode.Automatic content
}
// TODO: Load any ResourceManagementMode.Manual content
}
protectedoverridevoid UnloadGraphicsContent(bool unloadAllContent)
{
if (unloadAllContent)
{
// TODO: Unload any ResourceManagementMode.Automatic content
content.Unload();
}
// TODO: Unload any ResourceManagementMode.Manual content
}
protectedoverridevoid Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
base.Update(gameTime);
}
protectedoverridevoid Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
base.Draw(gameTime);
}
}
}
以上是XNA一開始的程式畫面,此程式有三個重要的部分:
在微軟提供的XNA專屬程式中,引用了九個(Microsoft.Xna.Framework)的命名空間,且使用了C#的using命名敍述,這些命名空間都是有特定功能群組用來匯入定義中的型別所組成的。
Game1類別繼承自Microsoft.Xna.Framework.Game類別,Game類別是XNA平台幫程式設計師將視窗的產生、繪圖、聲音和輸入的初始化、遊戲的流程等等的細節寫好隱藏包裹起來,讓程式設計師可以不必去困擾這部分的程式。
XNA提供了基本的六個函數:Game1( )、Initialize( )、LoadGraphicContent( )、UnloadGraphicContent( )、Update( )和Draw( )。
Game1( ):這個函數是一個特別的函數,且跟類別名稱相同,我們把它稱為建構者函數;此函數是當這個類別在生成一個物件時,會呼叫這個函數。在撰寫程式時,可在這個函數中設定一些屬性的初始值。
Initialize( ):在初始化函數中,我們會將一些遊戲程式的系統設定和一進入遊戲就要有的初始值,寫入此區段。在此區段的最後一行為base. Initialize( ),此行會呼叫父類別的Initialize( )函數,這是說明當在其他的類別中還有Initialize( )函數,在執行整個遊戲程式時,會在該函數中一一呼叫已加入成子組件(Components)的GameComponents物件的初始化函數;所以這樣一來,所有的子元件都會被初始化。
LoadGraphicContent( ):這個函數是用來上載程式中需要的2D圖型、3D模型、音效等資源。通常會在執行程式前,把所需要的資源預先行上載,這時候就可以將上載的資源寫在LoadGraphicContent( )區段中。
UnloadGraphicContent( ):當程式要中止結束前,Game1物件Run( )方法離開了遊戲迴圈,並且會呼叫UnloadGraphicContent( )函數,這個函數的作用是為了釋放所有被資源佔據的記憶體空間。在C++的程式裡,此觀念是非常重要的,但在C#程式裡,這個程式區段並沒有很必要,因為C#已經使用了類似Java語言的垃圾回收機制(Garbage Collector),所以在程式中止前,所有的在記憶體內資源會自動被清除。
Update( ):XNA程式大部分的執行期都會落在遊戲迴圈中,也就是會輪流呼叫Update(GameTime gameTime)函數和Draw(GameTime gameTime) 函數;在遊戲執行時,這兩個函數是被持續呼叫的,它是用GameTime的參數來控制一次迴圈前後呼叫的時間間隔。
Game類別的運作流程是以「固定時間更新」為內定(每秒更新60次),也就是每隔六十分之一秒呼叫Update( )一次來獲得使用者的輸入和執行邏輯的更新,並且在每次執行完Update( )後,隨即呼叫Draw( )來更新整個畫面。在Update(GameTime gameTime )函數的最後一行的base.Update( )與Initialize( )函數一樣,最後都會呼叫父類別Update( )函數,如果Game1物件中有子元件而且也是GameComponents物件,就會一併被更新。
Draw( ):這個函數是用來繪製出2D圖型和3D模型,在此區段GameTime和base.Draw的觀念,都跟Update( )和Initialize( )函數一樣,所以請看上面介紹。
3.2流程圖
一般遊戲的流程圖
初始化繪圖卡 |
載入資源(2D圖型、3D模型、音效檔等) |
得 |
執行必要的邏輯更新(移動、碰撞、AI、物理引擎、結束等) |
繪出(圖形的產生、聲音等) |
關閉繪圖卡 |
釋放資源 |
一般遊戲程式的執行流程
X
NA遊戲的流程圖
遊戲初始化 |
載入資源(2D圖型、3D模型、音效檔等) |
LoadGraphicContent( )
得 |
執行必要的邏輯更新(移動、碰撞、AI、結束等) |
繪出(圖形的產生、聲音等) |
釋放資源 |
Game1類別內遊戲程式的流程
當靜態類別Program中的Game1物件產生時,Game1( ) 函數會被呼叫,在這個函數內,程式設計師會完成一般的初始化的動作,然後Game1物件會呼叫Run( )方法,然後才會進入XNA程式:
第四章實作CrazyRacer Game遊戲
4.1 遊戲程式的設計
Crazy Racer Game遊戲程式中,我們可以分為主要控制遊戲顯示畫面的類別和遊戲引擎裡的類別。
在控制遊戲顯示畫面的類別中,又可分成Crazy Racer Game、MainMenu和GamePlay三個類別,分別是一個負責控制兩個畫面的切換,包括進入比賽的畫面、比賽的過程和結束,還有負責一些整體變數或物件的建立與設定;另外兩個類別是在顯示一個2D主選單畫面和一個3D場景管理玩家實際控制比賽過程的畫面。
在說明這個遊戲的SuperEngine遊戲引擎裡的類別前,我先介紹一下什麼是遊戲引擎?
我們可以把遊戲的引擎比作賽車的引擎,大家都知道,引擎是賽車的心臟,決定著賽車的性能和穩定性,賽車的速度、操縱感,這些都直接跟車手的駕駛有相關,並都是建立在引擎的基礎上的。
遊戲也是如此,簡單的說,遊戲引擎是指一些已編寫好的可編輯遊戲系統或者一些互交式即時圖像應用程式的核心元件,玩家所體驗到的劇情、關卡、美工、音樂、操作等內容都是由遊戲引擎直接控制的,它扮演著核心底層發動機的角色,把遊戲中的所有元素結合在一起,在後台指揮它們同時並有序地工作,這些都是遊戲引擎為遊戲設計者提供了各種編寫遊戲所需的各種工具,目的是讓遊戲設計者能容易和快速地做出遊戲程式而不用從零開始,就像之前在第三章一開始說明的「擴充」的概念一樣。
遊戲引擎運用的範圍非常廣泛,無論是2D遊戲還是3D遊戲,無論單機遊戲或者網路遊戲,無論是角色扮演遊戲、即時策略遊戲、冒險解謎遊戲或是動作射擊遊戲,甚至是一個只有幾百MB(Mega Byte)的小遊戲,都有這樣一段控制作用的代碼。
經過遊戲科技的不斷進化,如今的遊戲引擎已經發展為一套由多個子系統共同構成的複雜系統,從建模、動畫到光影、粒子特效,從物理系統、碰撞檢測到檔管理、網路特性,還有專業的編輯工具,幾乎涵蓋了開發過程中的所有重要環節。以下就對遊戲引擎的一些關鍵的概念和SuperEngine引擎一起做介紹:
光影效果:遊戲中的場景光源對處理其中的人和物的影響,折射、反射等的基本光源的光學原理,以及動態光源、彩色光源等的高級效果都是經過引擎的不同編輯程式的技術所控制實現的。
XNA程式實作上,將光影效果分成光源、材質和著色。
光源:在光源屬性裡可分為光源位置、照射方向、光源顏色、光源種類、照射範圍、亮度衰減程度等等。使用這些不同光源屬性的組合,基本上最常用到三大類光源,點光源、平行光源與聚光燈光源。
點光源:點光源是朝四面八方均勻的照射,例如:電燈泡。
平行光源:平行光源有點像是一個在無限遠處的點光源,像是太陽光就是一種平行光。
聚光燈光源:聚光燈與點光源不同的地方是在它的照射範圍非常集中,就像拿著手電筒照射物體實產生的光束一樣。
材質:這裡介紹的材質指的是材料(Material),不是貼圖(Texture),說明物體反射光線的特性。在日常生活中,我們能看到物體是因為物體將光線反射到我們眼睛中。
材質的屬性很多,有反射光的反應強度、漫射光反射屬性(diffuse light)、環境光的反射屬性(ambient light)、自發光(emission)、炫光強度(specular highlight)等屬性。而漫射光、環境光、炫光強度和原始不受光這四種屬性在各種材質屬性中是最常見的。
著色打光:如果沒有著色打光的步驟,物件看起來是像2D平面的。著色會讓對象看起來有立體感。打光會使構成球體表面頂點的法向量、光源的照射方向、眼睛的觀看的位置來計算物體表面反射光源的強度、炫光以及其他的擴散光線。這些因素都是透過物理計算後產生在螢幕像點將繪出的顏色。而這些著色打光的物理計算就是用Shader程式所撰寫的。
在程式裡,XNA已經有幫程式設計者寫好一個基本Shader的程式稱作BasicEffect類別,要使用BasicEffect的類別只要在程式中加入以下程式碼,就可顯示出來。
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.World = transforms[mesh.ParentBone.Index] * world;
effect.View = view;
effect.Projection = projection;
mesh.Draw();
}
動畫:目前由系所採用的遊戲動畫系統可分為骨骼動畫系統與模型動畫系統,前者用內置的骨骼帶動物體產生運動是比較常見,後者則是在模型的基礎上直接進行變形。引擎把這兩種動畫系統預先植入遊戲,方便動畫設計師為角色設計出豐富的動作造型。XNA是用骨骼動畫系統來編寫的。
XNA程式在實作上,提供一個類別Model用來載入3D模型,支援3D模型檔案格式有.x和. fbx 3D檔案。3D模型是一群數值資料,記錄一個3D物件的形狀,而一個3D模型可能是由好幾個子物件組成的,像CityRacerGame中的賽車模型,它就是由車身、輪子、車燈、窗戶等子物件所組成;這些子物件都有自己的「模型網格(ModelMesh)」,也就是一群三角面組合起來的外觀形狀。
首先介紹Model、ModelMesh、ModelMeshPart和Effect之間的關係。Model內部的結構是非常複雜和嚴謹的,一般來說,Model內部可以有多個模型網格(ModelMesh),就像我上一段舉例的CityRacerGame賽車模型,每個網格又可以包含多個網格零件(ModelMeshPart),每個網格零件裡又可以有一個對應的效果(Effect),用來設定要呈現的製作效果。
3D模型、網格、網格零件和效果的關係
把上述的模型網格的觀念套用到車子的模型來說明它們之間的關係,舉例來說,如果把車體當成主要的模型網格,把車窗、車燈、輪子、車的鏡子等當成子物件就相當於網格零件,而像車窗會有反光的效果就是車窗這個網格零件所對應的Effect效果。
在製作模型時,3D建模軟體會紀錄每個網格零件和車體的相對位置,而且這些相對位置是不變的,所以車子在移動時,所有的子物件也會跟著移動,不會因為車子的移動而就因此解體了。
接下來說明骨骼動畫系統。在上一段講述的車子在移動過程,不會因為前進或轉彎而就因此解體,也可以假想成在賽車裡有一根看不見的「軸」連結著它們,這根軸稱為「骨骼」(Bone);而連結這些模型網格的所有骨骼的模型稱作「骨架」(Skeleton);這些受骨骼帶動的模型網格稱為「表皮」(Skin)。
在XNA中,這些骨骼動畫系統都會從FBX或X模型檔案中載入,並用矩陣來存取車身的每個相對位置,接著把車身的各部分的骨骼矩陣與它的上一層的矩陣相乘,最後連結到它的最上層World矩陣,就能得到矩陣在3D世界中賽車各個部分的正確位置和旋轉方向。所以我們只要在程式中加入以下兩行程式和上述在光影效果的程式便可繪出賽車模型。
//把賽車物件的骨骼資訊全部拷貝到transforms矩陣陣列
Matrix[] transforms = new Matrix[car.Bones.Count];
car.CopyAbsoluteBoneTransformsTo(transforms);
只要有所有的模型網格的骨骼資料後,要計算每個模型網格在3D世界中的位置的步驟,就只要把它的骨骼矩陣乘上它的上一層的矩陣,以這個賽車遊戲為例,就是把它的四個輪子的矩陣乘上車提的World矩陣,才能得到它們在3D世界中正確的位置和旋轉方向。它的方法是用模型網格的ParentBone屬性的Index屬性取得上一層的矩陣(父親物件)矩陣索引,利用索引可以從transforms陣列找出要使用的矩陣。
// 把賽車的每個部分都畫出來
foreach (ModelMesh mesh in car.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
// 設定內定的打光方法,所以螢幕才不會一片漆黑
effect.EnableDefaultLighting();
// 數學座標轉換運算
effect.World = transforms[mesh.ParentBone.Index] * world;
effect.View = view;
effect.Projection = projection;
// 實際把賽車模型畫到正確的地方
mesh.Draw();
}
}
遊戲引擎:遊戲引擎是在設計引擎遊戲時,把一些都會用到基本架構都寫在裡面,之後要撰寫其他遊戲時,可以直接拿來使用,並且可以擴充此架構或是利用以寫好的遊戲引擎去做一些遊戲技術的運用,就不必每次要去設計一個遊戲時,都要去撰寫遊戲引擎。
遊戲引擎可分為兩大類:第一類是專門為了這個由系所設計的,這些都是和遊戲本身內容架構有關聯,譬如主選單的按鈕有幾個、換物件的元素有幾種,像賽車遊戲主選單中的輪胎更換與車殼顏色的更換的程式等。另一類是不僅只用於一個遊戲,它還可用在其他遊戲的類別檔案,例如:按鈕的撰寫、音效的播放、按鍵的讀取、畫面的繪製等程式,有時可以讓未來的遊戲開發者可以重複使用,所以在撰寫此類的程式時,可以建構一個程式庫,將來如果有要撰寫此程式時,可以直接拿來使用並做一個繼續擴充的運用。
在Crazy
Racer
Game中,我們撰寫了一個遊戲引擎為SuperEngine,此引擎是架構在XNA
Framework平台上,此遊戲引擎與XNA
Framework之間的關係圖SuperEngine這個物理引擎大致上可分為六大類別:
Game:模組處理遊戲的基本過程,這個類別包括資料的載入與整個 遊戲主迴圈的更新。
Renderer:這個模組是負責處理繪圖相關控制。
Input:負責除理遊戲中的輸入操作,包括滑鼠與鍵盤。
ODEPhysics:處理遊戲中需要用到的模擬物件與ODE物理引擎的溝
AIAction:這個模組是負責處理遊戲中電腦控制物件或角色的行為。
Sound:負責處理遊戲中的音效輸出播放。
SuperEngine會按照下列的流程執行
在SuperEngine遊戲引擎的類別中,設計邏輯是把那些所有步驟相似並且可以重複使用得程式碼都撰寫程C#的抽象類別,然後讓遊戲本身的類別去繼承它,這樣的技術方法可以使程式撰寫類別起來更精簡,執行起來更有效率。
在遊戲引擎的功能中,可分為三大類:
物理系統
物理系統,這可以使物體的運動遵循固定的規律,例如,當角色跳起的時候,系統內定的重力值將決定他能跳多高,以及他下落的速度有多快,子彈的飛行軌跡、車輛的顛簸方式也都是由物理系統決定的。
其中碰撞探測是物理系統的核心部分,它可以探測遊戲中各物體的物理邊緣。當兩個3D物體撞在一起的時候,這種技術可以防止它們相互穿過,這就確保了當你撞在牆上的時候,不會穿牆而過,也不會把牆撞倒,因為碰撞探測會根據你和牆之間的特性確定兩者的位置和相互的作用關係。
在SuperEngine中,我們把重點著重在
如何與ODE物理引擎溝通
ODE是一個遊戲引擎中的ㄧ種物理引擎,ODE物理引擎需要建立一個 物理專用的虛擬世界,用來模擬與計算這個是屆中所有物件的物理效果,它和螢幕上所看到真實世界物件是不同的,物理引擎的世界中,通場只會用簡單的幾何圖形體來做物理效果的計算。
計算物理反應
在遊戲中所看到的作用力、速度、加速度與碰撞後的反應,都是由物理引擎去計算的。我們要做的就是物理引擎模擬計算完成後,從物理世界中取出這些簡化物件的旋轉與移位矩陣,然後設定回遊戲場景中相對應的遊戲組件。
如何取回物理模擬的結果給遊戲使用
物理世界(Physical World)
物理世界是一個不可見的空間,在SuperEngine裡,我們設定這個物理世界的三個基本屬性:Gravity,ERP,CFM。
Gravity表示這個物理世界的重力向量(通常是往下) 。
ERP這個值告訴ODE在每次進行計算時要做多少程度的誤差修正,內定是0.2。
CFM是限制柔性程度(Constraint Force Mixing )的縮寫,如果CFM的值為0,就表示這個關節的限制是硬性的,完全沒有彈性。
區間(Space)
一個物理世界可能包含成千上萬個幾何物件,如果全部都要計算他們彼此之間的碰撞,是浪費時間的。所以我們會把那些有可能需要計算碰撞的物件歸入同一個區間。
幾何物件(Geom)
所有用來判斷碰撞的幾何形體都稱為Geom,在這裡我們使用了三個幾何形體,平面、長方體、球體,分別代表場景物件、車體、輪胎。
身體(Body)
表示一個有體積可以發生碰撞的剛體幾何物件,它可以包含如位置、線性移動速度、轉動角速度與質量等等屬性。
關節(Joint)
關節是兩個物件之間的連結關係。
接觸點(Anchor)
兩個身體接觸的點稱為接觸點,通常是使用一個向量(x , y , z)來表示。
軸向(Axis)
軸向是介於兩個身體之間,用來限制旋轉方向。
渲染
當3D模型製作完畢之後,美工會按照不同的面把材質貼圖賦予模型,這相當於為骨骼蒙上皮膚,最後再通過渲染引擎把模型、動畫、光影、特效等所有效果即時計算出來並展示在螢幕上。渲染引擎在引擎的所有部件當中是最複雜的,它的強大與否直接決定著最終的輸出品質。
City Racer Game在撰寫此部分是用運3D Max來實作City場景,並把3D 圖檔導入到XNA程式中。
輸入與輸出(IO:Input and Output)
輸入與輸出是負責玩家與電腦之間的溝通,處理來自鍵盤、滑鼠、搖杆和其他外設的信號。如果遊戲支援聯網特性的話,網路代碼也會被集成在引擎中,用於管理用戶端與伺服器之間的通信。
Crazy Racer Game在輸入和輸出中,是使用鍵盤操控、滑鼠操控和音效播放。
鍵盤操控
設計處裡鍵盤操控的類別GameKeyboard。由於XNA平台會替我們處理按鍵狀態的接收,所以我們不需要自己撰寫如何從系統讀取按鍵狀態的程式。需要使用的是XNA提供的Microsofot.Xna.framework.Input.GetState()函數,便可執行。
函數查詢按鍵狀態
IsKeyDown()
詢問某個特定按鍵是否被按下
IsKeyUp()
詢問某個特定按鍵是否被按下
IsKeyHit()
詢問某個按鍵是否被按下又放開
滑鼠操控
設計處裡鍵盤操控的類別GameMouse。由於XNA平台會替我們處理按鍵狀態的接收,所以我們不需要自己撰寫如何從系統讀取按鍵狀態的程式。需要使用的是XNA提供的Microsofot.Xna.framework.Input.GetState()函數,便可執行。
音效的播放
步驟
使用XACT編輯工具建立你的音效播放引擎。
撰寫程式碼來建立音效系統,我們把這個類別稱為GameSound。
在遊戲中播放聲音。
AudioEngine
這個類別是用來表示音效引擎
WaveBank
這個類別是用來存放那些要載入的音效檔案
SoundBank
這個類別是用來存放那些要播放的音效
Cue
這個類別用來管理音效的播放
4.2 概念圖
ㄧ.GamePhysic物理物件都繼承自PhObj物件
二.鍵盤操控UML設計圖
三.滑鼠操控UML設計圖
四.音效UML設計圖
五..整體遊戲流程狀態架構
4.3賽車遊戲實作截圖
六.進入遊戲City Racer Game
MainMenu主選單平面的圖形
GamePlay 3D場景賽車場地
直線賽車狀態
賽車轉彎狀態
撞到牆壁反彈
翻車狀態
3D飛行鏡頭狀態
倒數計時
第五章結論
5.1 心得
陳信益的心得
因為自己是轉學生而且原本也不是唸資工系,所以在程式方面的能力很弱,只能從基礎學起,也就沒辦法和同屆的同學一起上課,所以在選擇專題方向的時候就很困擾,因為看過別人的專題內容,都是需要分工合作,像是摸索需要用到的程式語言,如果不是課堂上學過的C或java,那麼有沒有同伴可以互相討論對學習新語言的效率就差很多,因此,在經過一段時間的思考過後,決定往遊戲製作的方向走,因為自己本身比較有興趣,至少就比較有動力去學習。
既然決定好專題方向,接下來就是具體內容:要做什麼遊戲、用什麼軟體做,在網路上查詢後發現有XNA這套開發軟體,而且是用自己有學過的C#語言來寫,還可以寫給XBOX 360跑,對於想購入XBOX 360的我來說這真是最好的選擇。
有了大概的目標之後就是開始學習實作,雖然XNA這套軟體幾年前就已經公佈,而且也都有在持續更新版本,可是有關的中文教學書籍很少,雖然原文書的選擇比較多,但是比較貴,圖書館也借不到,網路上也很難找到,大概都是片斷章節,只能祈禱有好心人上傳電子檔,才能學到較完整的內容。
在摸索的過程中,也學著試看看做一些小遊戲來,只是都是很陽春的東西,想要拿來當專題發表實為不可能,但是在"想要做完整的遊戲"這個目標下努力之後,發現了自己的致命傷:不會做3D美術物件,連精美一點的2D圖型介面都做不出來,實在沒有美術方面的能力,但是遊戲並不是只有寫寫程式就好,還要配合圖片、物件來呈現出一個遊戲世界才行。在找老師討論這問題時,剛好遇到柏翰,知道他也是做XNA遊戲開發,而且會3Dsmax,所以乾脆合併成一組,比較能夠互相討論問題。
陳柏翰的心得
我一開始本來是在兩年前跟吳欣欣與張菀純益起製作專題,因為開刀的關係,修學了一學年,而因為修學階段行走非常不便,再加上要經常和她們討論,還有要與老師在一個月開會報告一次,總總得不便與考量下,後來在去年九月決定拆組變成我自己一個人一組。
這個XNA XBOX賽車遊戲的主題,本來是我在去年暑假想出來的題材,在當時我們還是同一組,所以當下也經過討論,決定要製作這個主題;一開始我們有討論過分工的部分,最後討論出她們要製作場景的部分,而我來負責賽車的部分。
在3D MAX方面,我在學校的圖書館和台北市立圖書館都有去尋找書籍,甚至還到中國大陸去尋找相關書籍,我發現對岸的這方面書籍比我們台灣不管在種類和多樣化都比我們還又多上幾十倍,我還記得當時我去它們書城還真是被嚇一跳阿,後來我在那邊找到了兩本製作賽車的書籍,分別是<法拉力的產品設計>和<BMW跑車的建模設計>,想說賺到了回去按照書籍參考一定能做出賽車模型。
在製作3D Max賽車模型時,我發現並沒有我想像的那麼容易,因為這兩本書籍的教學製作過程都是非常精細的製作,它都是拿一種叫作Plane(平面)的建模材質一片片貼出來的,而且在教學修建上,都是很細微的修改,所以我建了車體的三分之一,就感覺眼睛快要脫窗了,又想到後面還要寫賽車的程式,所以就暫時得先放棄這個製作,改為選擇去網站上收尋看有沒有3D Max的模型可以下載來去運用它;經過一翻的收尋,瀏覽到兩個大陸的網站可以讓我下載模型,所以覺得模型部分因該是只要把它下載下來,加以調整一下賽車在場景中的座標位置就沒問題了。
之後我就把重心著重在XNA的賽車程式上,因為XNA的教學和應用在中文書和翻譯版中,真是少之又少,所以我一開始就去網路上收尋,找到一本XNA PC/Xbox 360 C#遊戲程式設計的書籍並把它買回來作學習,剛好這本書又是在寫如何使用XNA平台撰寫一個賽車遊戲,於是我就開始參考它如何撰寫,並且想說之後在把網上的3D MAX的法拉力賽車給套用上去,再去改一些設定,大致上就有一個基本款的,然後再去想進階的撰寫設計。
在閱讀此書籍時,因為這本書不是從初始開始教導如何去撰寫一些最初的設定,導致我在閱讀那本書時,有一些基礎上的設定,像整麼把2D的模型放到3D世界中,整麼樣把3D MAX中的模型的位置和程式撰寫中的設定位置能夠作一個相符合的設定等教學,在加上我在製作次專題碰到技術上困難時,根本也沒有專業人員例如:老師或住叫可以詢問,所以我也只能盡量參考並學習。
在今年我復學後,拿到了她們去年製作的專題報告,仔細看了去年的報告,才發現她們也把我要製作的賽車模型和一些相關得程式碼一成不變的貼了上去,讓我覺得當下很生氣,因為我們知前本來就有討論好,我製作賽車的部分,她們製作場景的部分,所以我覺得她們不因該把我的車子的部分也貼上去,在加上我前面就有提到過XNA的中文書籍在台灣是非常少,所已能參考和發揮的部分實在是有限。
在這學期評鑑只剩下一個多月,我正在困擾要如何把此專題遊戲,作出讓它至少有一兩種遊戲技術上的變化時,在有一堂計算機結構的課下課時,讓我遇到一個轉同學,他也是只有一個人在製作專題並且也碰到一些技術上的問題,後來我就去找他聊一下專題的情形,發現他也是在做遊戲製作的專題,所以我就跟他說明我也是在做賽車遊戲的專題,最後他同意要跟我一組繼續製作專題並且也經過兩個專題老師同意下,做最後一個月的討論與努力,而完成此專題。
5.2 實作困難
陳信益的實作問題
雖然都是要做遊戲,但是我沒有特別想做的題材(像是rpg,act...,之類的) ,而柏翰因為是復學的關係,已經有具體的內容了,就是做一個賽車遊戲.
但是做賽車遊戲,第一步就是要做出(至少)一台車子來,柏翰原本想自己做,但是發現自己一張一張貼圖並修改貼圖大小實在太慢,可能就要花掉幾個月的時間,所以只好在網路上下載人家做好的模型物件,然後把它修改成合適的車子。
比如說有些車子輪胎是和底盤連在一起的,必須把它們各別分開才能寫程式,讓每個輪胎都能和物理引擎結合,這樣車子才能呈現加速度之類的功能,這就是一個大問題,因為輪胎物件不是自己做的,所以在寫程式方面就很麻煩,必須配合對方做的物件才行。所以,我認為必須要有一個人負責做3D物件,包括車子、跑道、場景等,並不需要做得很豪華,但是要配合寫程式的同學所需要的規格才行。
第2個問題是:賽車比賽的介面,比如顯示圈數、秒數、儀錶、即時更新最佳成績之類的,這方面最好也是一個同學專門負責,因為遊戲畫面顯示的並不是數字,而是字串或圖片。顯示字串比較簡單,但視覺效果相當薄弱,如果要用圖片來顯示數字及文字(英文字母,xna不支援非英文語言) ,那也是一門學問,你必須先把圖檔做好載入程式,再定好每個數字,字母,符號對應的圖片位置,並且寫好程式,當程式的數字更新時,螢幕上也要即時更新畫出圖片才行。
接下來的問題就比較容易一點,就是說把上面提到的內容做個整合,比如各個遊戲畫面的聯結(遊戲主視窗可以選擇開始遊戲,或是進入option視窗來調整細部選項,像是音樂的大小、鍵盤滑鼠甚至是360手把的操作設定、還有分數排行榜之類的各種視窗、要讓它們可以實際作用。)然後還有設定物理引擎,也就是車子的加速度,你也可以設定車子的重量、地心引力、空氣阻力等等的,這方面可以用人家寫好的引擎,但是效果較差,而且也會受到限制,你必須配合引擎來寫程式讓引擎和車子的各個物件結合才行,而你想自己寫的話,請確認自己的物理學得如何。所以在這方面大概需要1~2個人負責,寫程式問題不大,問題是要有人負責把各個美術物件照規格做出來才容易寫程式來控制。
做這個專題後,我想嘗試做遊戲的心態並沒有因為碰到困難而減少,但是我不會再去做賽車之類的遊戲,因為光是各個3D物件就很難做出來,做出來還要設定它們,比如車子和賽道之間比須設定好碰撞框,不然車子會直接穿牆而過,以及撞到牆壁後以碰撞的強度大小來決定車子的各種反應狀態:像是會稍微減速或是整個停止之類的。一個"完整的3D賽車遊戲"大概至少要四個人才能做出來,而且重點是美術人員,所以我之後大概會往"雷電"之類的小飛機射擊遊戲或是2D角色扮演遊戲的方向走吧。
陳柏翰的實作問題
硬體上的問題:
因為要製作3D動畫需要高CPU和顯示器的電腦,而在老師的實驗室,只有一台這種配備,而且跑3D動畫的過程中也非常勉強,所以就花了三萬三千多塊去買了一台16吋型的筆記型電腦。
在3D MAX製作中,覺得16吋型的筆記型電腦建模上,還是非常吃力,而且在微調模型時,感覺製作到眼睛快要脫窗了,所以又去光華商場美了22吋螢幕。
3D MAX上的問題:
在台灣找相關的賽車模型的書籍,實在是很少,而且在教學上都不是很完全,所以還跑到中國大陸去尋找,後來找到兩本專門教學賽車模型並把它買下來。可是在製作中,發現有非常多得不便,所以還是先把建模部分暫時放棄,改為上網收尋,並下載下來。
在3D MAX的軟體轉換到XNA平台時,賽車一直出現四個輪胎與車體之間解體的狀況,因為在製作過程中,要把輪胎與其他零件分開來,這樣在執行時,輪胎才能自然轉動,經過我四五個小時的調整,還是沒辦法調出正確的賽車模型。
在場景的部分,我也試著想把原來場景添加一些物件進去,但在填加完物件並存成(.fbx)的副檔名,整個場景在載入XNA平台執行時,就會發生場景的材質貼圖完全都沒有匯入,我花了也是四五個鐘頭並且看得書上的說明,還是無法解決這個問題,所以去年他們的場景呈現執行時,也無法把貼圖儲存匯入到XNA平台中執行顯現。
XNA上的問題:
這類的中文和翻譯書籍少之又少,中文網站也不多,所以只能參考英文資源。
我身邊的專業或者懂這個領域的人員根本沒有,所以只能靠自己摸索。
第六章參考文獻
參考書籍
Visual C# 2008 2D與3D遊戲設計 | 江家杰 | 碁峰 | 2008年12月 |
Visual C# 2005程式設計經典 | 林義証 | 碁峰 | 2007年3月 |
2D/3D遊戲程式設計入門 | 何振揚 | 統一元企 | 2009年2月 |
XNA 3.0實戰手冊 | Aaron Reed | 精誠 | 2009年7月 |
XNA PC/Xbox 360 C#遊戲程式設計 | 葉思義 | 碁峰 | 2007年10月 |
參考網頁
http://www.3dcool.net/(3D Max模型瀏覽下載)
http://www.huanyiba.cn/soft/sort080/list80_1.html(3D Max模型瀏覽下載)