C++游戏引擎设计与实现含源文件.docx
《C++游戏引擎设计与实现含源文件.docx》由会员分享,可在线阅读,更多相关《C++游戏引擎设计与实现含源文件.docx(55页珍藏版)》请在冰豆网上搜索。
C++游戏引擎设计与实现含源文件
石家庄职业技术学院
游戏引擎设计与实现
学生姓名:
________
学号:
_______
指导教师:
_________
系别:
____信息工程系____
专业:
_____软件技术______
年级:
_______________
论文提交时间:
评阅人:
___________________
年月日:
____________________
《游戏引擎设计与实现》
摘要
目前,视频游戏依靠流行影片的成功而获得成功已经是司空见惯的事了。
但是一个哪怕是简单的可供万人同时上线的网络游戏开发也不是十分容易的,更别说早已风靡全球的3D游戏《魔兽世界》,而它的开发周期是十年。
而我们的开发本着简单,理解和融汇的态度去尝试开发一个2D游戏《SpaceWar》。
游戏会设计和开发自己的引擎,并扩展引擎功能试着去开发一个有图形,有音乐,有交互的简单人性化的休闲娱乐小游戏。
同时综合利用C++语言进行程序设计的能力以及设计并运用游戏引擎开发游戏,主要是学习和思考如何用引擎来做我们想做的事进而产生我们想要的游戏效果。
使软件可以应用于平时工作劳累之余的休闲娱乐,缓解一下大脑疲劳。
关键词:
C++游戏引擎,游戏开发
第1章概述
§1-1游戏功能概述
1-1-1游戏采用了彩色矢量图
游戏中背景、外星人、以及玩家控制的小汽车均是位图图像。
他们的加入受控于游戏引擎自己的图形类。
1-1-2运用了闪屏以提供图形化开戏
有一些电影的片头字幕很有创意,用来介绍和宣传电影再好不过。
与其类似,视频游戏中的闪屏也具有传达游戏主题思想的作用。
不管闪屏在游戏中的内容是多是少,重要的是,至少要现实游戏的名称以及游戏的相关信息,如版权等。
目前,许多商业游戏不仅包括闪屏,还包括了介绍性的动画或者视频片段等。
像这样的“闪动”比简单的闪屏更吸引人,但是增添乐趣的同时也意味着要付出更多的编程技术和工作量。
1-1-3运用了演示模式展示游戏
演示模式就是说,在还没有进行游戏的时候,先显示一个动画片段,它演示了游戏的玩法。
演示模式背后的思路是,它要优于闪屏,不仅仅是显示一个名称或者一幅静态的游戏图像。
它试图演示游戏的实际玩法,或者至少演示游戏中一些运动的主要角色,与在游戏中看到的一样。
与闪屏不同的是,演示模式不只是在游戏开始出现,结束时就消失。
相反,演示模式贯穿于整个游戏,利用来自游戏的有趣的动画来帮助填充游戏之间的空隙。
因此,在游戏结束时,因该有个短暂的延迟,以便于玩家在这段时间里意识到游戏已结束,然后游戏返回演示模式。
当然,游戏也是在演示模式中展开的。
这样,演示模式就替代了游戏的闪屏,并且比闪屏的作用更进一步。
演示模式与闪屏的区别在于它涉及演示游戏,意味着必须允许子画面到处移动。
所以为了创建游戏演示模式的一种简单的方式是仅仅显示游戏中的角色是如何到处应移动的,而不是试图模拟游戏中的真实玩家。
因为演示模式的整体目标就是展示游戏,使之看起来更吸引人。
1-1-4记录玩家得分
这个功能是一个存储在磁盘上并且可以在游戏之间保留的高分列表。
§1-2游戏的运行环境
1-2-1硬件环境
运行本游戏要求处理器在奔腾3以上,内存在256MB以上的计算机。
1-2-2软件环境
本游戏开发的操作系统:
WindowsXP。
本游戏的开发工具:
VC++6.0
1-2-3条件与限制
人员有限,开发时间紧迫,使用VC++6.0进行软件编程。
第二章技术背景介绍
§2-1游戏引擎简介
2-1-1什么是游戏引擎
几个不同的游戏,尝试想一下它们的内部是如何设计的。
重要的是,看能否找到适用于所有游戏的任何公共的部分设计元素。
例如,所有游戏都有背景,片头屏幕、地形图和背景音乐……如果是,那么他们很可能是围绕游戏引擎的概念设计的。
如果你要创建多个游戏,而又不想每次都重复同样的工作,游戏引擎就特别有用。
游戏引擎对于Wwindows游戏的另一个重要的好处在于,它允许隐藏针对Windows而游戏无关的繁杂代码。
相对于通过剪切和粘贴多次的常规代码来创建游戏,将其隐藏于引擎中更有优势,以后就不必再管他们了。
我们知道它们在哪里,但是不必查看他们,可以有更多时间去关注游戏代码更重要的且更有趣的部分。
游戏引擎很好的组织了游戏代码,这样常规的应用程序任务就与游戏特有的任务分离开立,有点类似种代码分离技术。
它为游戏开发人员带来的好处是可以为向游戏引擎中添加能够在以后的游戏中重用的特性。
此外,引擎还可以简化代码,将注意力集中于重要的游戏代码上。
事实上,大多数商业游戏开发人员都有自己定制的游戏引擎,这是他们在多年来学习大多数游戏所需的公共特性的过程中积累开发出来的。
在设计和开发要求更高的游戏时,自己的游戏引擎可能会在这些过程建立起来,从而开始自己的游戏人生。
2-1-2游戏引擎的作用
游戏引擎负责处理各种琐碎事务:
组织游戏、确保它正确运行以及关闭它。
虽然这些任务确实任何游戏所需要的,但是初始化、运行以及在游戏结束进行清理等工作的某些方面确实是游戏所特有的。
因此,重要的是,引擎可以满足游戏独特的需求,并帮助程序员使围绕游戏引擎开发游戏的过程中尽可能简单和直接。
有一个好的游戏引擎,你会发现,开发游戏所需要的时间比不使用游戏引擎少得多。
游戏引擎的思想是一次性开发某些核心游戏程序,将其粘贴在游戏引擎中,然后只有在绝对必要的时候才再次处理它们。
例如:
在编写了加载图像并在屏幕上绘制它的代码之后,就没有什么必要重新编写这种代码了。
因为加载和绘制图像是所有游戏引擎都需要的一个基本功能。
§2-2视频游戏简介
首先,有必要指出一点,视频游戏并不是一直像今天这样受到尊重,被视为一种合法的娱乐形式。
以前,视频游戏行业是一个很不受重视的很小的娱乐行当,但现在他已经成为了全球商业的一个很重要的分支。
现在,视频游戏的资金和规模可以和好莱坞的电影相比,并且他们经常涉及到著名的男演员、女演员、编剧家、音乐家以及其他娱乐家。
而事实上,视频游戏的制作在许多方面与电影的拍摄相似。
仅仅为了使游戏获得投资,就要确定游戏的基调、编写剧情和进行市场调查。
一旦进入了游戏的制作阶段,就要走设计组、动画组和程序员组(更不用说其他各种有能力的个人和公司了)共同投入来使之得以完成。
再多说一点,为什么视频游戏为这么多人所吸引?
那么请你想一下电影在现代文化中总是多么的流行。
我们之中很少有人不会想象在看一部大片时自己在某个时刻正处于某个场景。
视屏游戏使我们超越了观众的较色,成为交互式故事中的一个参与者。
事实是,几乎所有的视频游戏都是你步入一个世界并参与进去,即使那个世界只有一个外太空背景和几个外星人(譬如SpaceWar)。
当你走进视频游戏的街道上那个,每一个场景仿佛是进入另一种现实的窗户,它在恳请你走入其中,看看里面发生事情。
通俗的说,这就是游戏。
将一个游戏从画板上转到键盘上的第一步是你要明确你的游戏到底是什么样的。
不是说列出包括所有屏幕、生物及细节交互操作的项目列表,不过,根据所想的最终游戏建立一些小的基本的小规则是必要的。
一般游戏的整体概念应有一下几个要素:
2-3-1基本思想
在开发游戏时,最重要的设计步骤就是确定游戏背后的基本思想。
它是一个射击游戏、迷宫游戏、角色扮演(RPG)、驾驶游戏、智力游戏,还是这些游戏中的某种结合?
考虑这些的同时别忘了,无论你的游戏设计思想如何,都要把游戏的趣味性放在首位,在有了一个基本的游戏设计思想并决定不惜一切代价使之有趣味性之后,下一步就可以开始创作剧情了。
2-3-2剧情
剧情不是仅用在电影和复杂的游戏制作中的。
即使一个很简单的动作游戏,创作剧情也有助于确定那个游戏的情绪和风情,并随之设计出生活在游戏世界中国的生物。
将游戏放在一个故事情节中会使玩家更贴近你的世界。
2-3-3图形
虽然游戏没有漂亮的图形也能够很有趣,但是使用图形可以很大程度的改进任何游戏。
选定一个与设计目标和资源一致的图形级别十分重要。
这个在以前,还要考虑计算机的图形能力,而今,即使低档的计算机也足以处理中等复杂程度的游戏。
对于大多数游戏而言,屏幕分辨率是一个很重要的考虑因素。
如果第一次启动一个商业游戏时,屏幕闪烁并且显示器发出奇怪的噪声,那么你是否知道这个游戏正在转入一个与正在使用的分辨率不同的分辨率。
目前。
对于WindowsPC来说,最常见的是800x600的分辨率,它表示屏幕在水平方向有800个像素,垂直方向有600个像素点。
而分辨率的重要性在于它直接影响图形的大小。
结合现实中的游戏画面,另一值得考虑的设计决策是游戏中玩家的角度。
即游戏是2D还3D,还是这两者的某种结合,例如国产大型网游《梦幻西游》、《大话西游》、《问道》等等都是2.5D。
2-3-4声音
声音这种元素看起来可能没有图形那么重要,但是,一旦尝试在一个没有声音的情况下玩一个游戏时,情况就会不同。
想像一下,哪怕你不是在玩游戏,一个喜欢在音乐氛围中创作的人如果突然听不到给他带来灵感的旋律,他会是怎样?
所以尽可能的使用音乐是很重要的,声音效果是最低的要求,如果确实要开发某种好的游戏,则要考虑使用某种与之特定的音乐声轨。
同时,要考虑声音在游戏中的质量怎样,这对有内存需求和游戏的整体性能有极大的影响。
对于声音效果,将处理采样平率,它们均采用wav文件的形式。
必须选定一个采样频率,是单声道还是立体声以及声音是使用8位还是16位来存储各个样本。
在游戏中,音乐的处理形式通常与音效不同。
虽然可以将音乐录制为一个采样的声音,但是这样做会占用很大的内存。
因此,取代采样的是使用以各种更好的形式MIDI(MusicalInstrumentDigitalInterface音乐设备数字接口),它是在计算机上整理和播放音乐作品的标准。
2-3-5控制
主要用来在游戏中与玩家进行交互,这部分极其重要,不应该忽视它们。
支持尽可能多的输入设备(键盘、鼠标、操作杆)很重要,这样偏好某种设备的玩家就得到了满足。
总之,这个设计是多多易善。
不管怎样,至少要考虑鼠标和键盘。
这个是底线。
缺少它们我想目前为大部分游戏是无法正常运行的。
2-3-6游戏模式
对于一个完整的游戏而言,最要要考虑的因素就是游戏模式。
即单人游戏、双人游戏还是网络游戏?
§2-4面向对象的编程和游戏
首先要明白什么是面向对象,因为《SpaceWar》是C++编写的,其思想就是面相对象(Object-orientedprogramming,OOP)是一种将程序中的各个部分视为对象(与程序代码块相对)的编写技术。
因为把游戏划分为各个对象实际上会更易于理解,所以OOP在游戏中尤为有用。
因此,像C++这样语言是十分适合于游戏开发的。
下边简单再说下OOP.
OOP背后的思想是,使编程更类似于人们的思考方式而不是计算机的思考方式。
人们往往根据有意思的事情(对象)来思考。
例如:
如果要描述一个篮球游戏,那么可能会谈及球场、球员、篮筐及裁判等。
从计算机的角度而言,计算机篮球游戏与其他程序没有任何区别——它仅仅是连串的0和1。
程序语言允许程序员不必再以0和1的方式思考。
OOP语言更进一步,允许基于对象进行思考。
对象的类构成了OOP的一个重要部分。
类是对象的种类。
另一种说法是对象是类的一个实例。
如果正在创建计算机篮球游戏,那么可能创建一个单独的篮球球员类,游戏中真正的球员是这个类的实例。
2-4-1游戏中应用OOP
为了理解OOP对游戏开发的好处,将游戏视为一种抽象的模拟会有所帮助。
如果看到过或玩过大型游戏,可以发现,要想出一个没有模拟任何东西的游戏几乎不可能。
所有冒险游戏和体育游戏显然都是模拟,就连最新颖的太空游戏也模拟了存在于某种虚拟世界中的对象。
知道了游戏就是世界的模型之后,就可以将游戏中的大多数事物(地形、生物等)于这些世界中的事物对应起来;一旦能到将一个游戏分解为事物的集合,因为很容易将事物转换为OOP环境中的对象,所以这时就可以将OOP技术应用到设计中去了。
OOP对于游戏开发的好处就在于,一旦一切准备就绪,游戏至少就可以运行了。
换句话说,各个对象负责处理它自己的事物,因此游戏本身不必考虑太多各个对象所做的事情。
游戏只是提供一个对象所处的框架。
这个框架主要包括一个绘制对象的游戏屏幕和一个主游戏循环或更新循环(通知对象经历了一段时间)。
对于生物来说,这种更新需要决定移动方向以及它们是攻击还是跑动。
对于主角色来说,更新涉及根据用户输入执行一个动作。
时刻清楚,对象是独立的实体,它们基本上知道如何照顾自己。
在游戏中使用OOP设计的一个更为实际的好处与重用代码有关。
例如我们已事先有了一个外太空的游戏,现在要创建一个与之类似的游戏。
我们就不必从开头开始创建,可以使用为第一个游戏开发的对象并在这个新游戏中重用他们。
当然做一些修改是有必要的,但是更多的更改可以通过创建新的子类来完成,而不必重新编写原始的类。
代码重用是在游戏开发中使用OOP方法的最大益处之一。
§2-5研究相关工具
在开始任何游戏开发项目之前,收集一套用来开发游戏的工具非常重要。
虽然在开发复杂游戏时可以考虑各种不同的工具,但是最关键的工具有以下几种:
2-5-1编译器和开发环境
无论使用何种程序语言来开发游戏,都需要一个编译器将程序转换为可执行的游戏应用程序。
因为《SpaceWar》使用C++语言开发Windows游戏所以需要一个可以使用Win32API(ApplicationProgrammingInterface,应用程序编程接口)创建Windows应用程序的C++编译器。
C++编译器有很多,从功能强大的商业开发环境(如:
MicrosoftVisualStudio.Net和BorlandC++BuilderX)到免费的编译器(如:
BloodshedDev-C++和DJGPP)。
2-5-2图形工具
这个有很多选择,Paint是Windows内置的标准图像编辑器,它对于创建和编辑基本的游戏图像非常有用。
高端工具是图形专家用来在图形上实现多样化特殊效果的工具。
如:
AdobePhotoshop。
2-5-3声音和音乐工具
游戏中使用的声音效果通常是采样的,这就意味着使用麦克风或者一张音频CD录制声音。
计算机的声卡上有一个线路输入端口和一个麦克风端口,这两者都可以对声音进行采样。
可以使用Windows内置的SoundRecoder应用程序对声音进行采样。
第3章游戏的程序设计
§3-1游戏引擎设计
好了,说了很多了,现在开始设计游戏引擎。
开始游戏引擎的第一步是创建与游戏事件相对应的处理程序。
游戏中发生一个事件时,就会调用相应的事件处理程序,是游戏做相应的事件响应。
《SpaceWar》的基本游戏事件响应函数如下:
BOOLGameInitialize(HINSTANCEhInstance);//游戏初始化
voidGameStart(HWNDhWindow);//游戏开始
voidGameEnd();//游戏结束
voidGameActivate(HWNDhWindow);//激活游戏
voidGameDeactivate(HWNDhWindow);//游戏暂停
voidGamePaint(HDChDC);//绘制游戏图形
voidGameCycle();//游戏循环
GameEngine类
//-----------------------------------------------------------------
//GameEngineClass
//-----------------------------------------------------------------
classGameEngine
{
protected:
//MemberVariables
staticGameEngine*m_pGameEngine;
HINSTANCEm_hInstance;
HWNDm_hWindow;
TCHARm_szWindowClass[32];
TCHARm_szTitle[32];
WORDm_wIcon,m_wSmallIcon;
intm_iWidth,m_iHeight;
intm_iFrameDelay;//帧延迟
BOOLm_bSleep;
public:
//Constructor(s)/Destructor
GameEngine(HINSTANCEhInstance,
LPTSTRszWindowClass,
LPTSTRszTitle,
WORDwIcon,
WORDwSmallIcon,
intiWidth=640,
IntiHeight=480);
virtual~GameEngine();
//GeneralMethods
staticGameEngine*GetEngine(){returnm_pGameEngine;};
BOOLInitialize(intiCmdShow);
LRESULTHandleEvent(HWNDhWindow,
UINTmsg,
WPARAMwParam,
LPARAMlParam);
//AccessorMethods
HINSTANCEGetInstance(){returnm_hInstance;};
HWNDGetWindow(){returnm_hWindow;};
voidSetWindow(HWNDhWindow){m_hWindow=hWindow;};
LPTSTRGetTitle(){returnm_szTitle;};
WORDGetIcon(){returnm_wIcon;};
WORDGetSmallIcon(){returnm_wSmallIcon;};
intGetWidth(){returnm_iWidth;};
intGetHeight(){returnm_iHeight;};
intGetFrameDelay(){returnm_iFrameDelay;};
voidSetFrameRate(intiFrameRate){m_iFrameDelay=1000/
iFrameRate;};
BOOLGetSleep(){returnm_bSleep;};
voidSetSleep(BOOLbSleep){m_bSleep=bSleep;};
};
游戏引擎中的WinMain()函数调用游戏引擎的函数和方法,提供了一个从游戏代码中分离标准的Windows程序代码的巧妙方法
//-----------------------------------------------------------------
//Windowsfunction
//-----------------------------------------------------------------
intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,
LPSTRszCmdLine,intiCmdShow)
{
MSGmsg;
staticintiTickTrigger=0;//滴答触发器
intiTickCount;//滴答计数器
if(GameInitialize(hInstance))
{
//InitializeGameEngine
if(!
GameEngine:
:
GetEngine()->Initialize(iCmdShow))
returnFALSE;
//Enterthemaincycle
while(true)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
//Dealmessages
if(msg.message==WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
//EnsuretheGameEnginenotsleeping
if(!
GameEngine:
:
GetEngine()->GetSleep())
{
//chektickCountifoversagameperiod(周期)
iTickCount=GetTickCount();
if(iTickCount>iTickTrigger)
{
iTickTrigger=iTickCount+
GameEngine:
:
GetEngine()->GetFrameDelay();
GameCycle();//gamecyclecalled
}
}
}
}/*endwhile*/
return(int)msg.wParam;
}/*endif*/
//Gameover
GameEnd();
returnTRUE;
}
GameEngine:
:
GameEngine()函数负责初始化游戏引擎的成员变量,而析构函数保持为空,以备将来使用
//-----------------------------------------------------------------
//GameEngineConstructor(s)/Destructor
//-----------------------------------------------------------------
GameEngine:
:
GameEngine(HINSTANCEhInstance,LPTSTRszWindowClass,
LPTSTRszTitle,WORDwIcon,WORDwSmallIcon,intiWidth,intiHeight)
{
//Setthemembervariablesforthegameengine
m_pGameEngine=this;
m_hInstance=hInstance;
m_hWindow=NULL;
if(lstrlen(szWindowClass)>0)
lstrcpy(m_szWindowClass,szWindowClass);
if(lstrlen(szTitle)>0)
lstrcpy(m_szTitle,szTitle);
m_wIcon=wIcon;
m_wSmallIcon=wSmallIcon;
m_iWidth=iWidth;
m_iHeight=iHeight;
m_iF