DxFramework

深度探索DxFramework 4-1

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 第4章 初始锋芒 剖析DemoA 4.1 Demo实现的功能点和整体架构 4.1.1 实现的功能点 4.1.2 Demo的整体架构 4.2 Demo实例类的定义和初始化 class C_DemoA : public C_GameState { public: C_DemoA(); virtual ~C_DemoA(); virtual void Input(); virtual void Update(); virtual void Render2D(); private: C_Sprite* p_Background; //背景图片 C_Sprite* p_Box; //用来演示的小方盒 // 各种dxfrramework支持的图片格式 C_Sprite* p_Bmp8; //8位bmp格式 C_Sprite* p_Bmp24; //24位bmp格式 C_Sprite* p_Png8; //8位png格式 C_Sprite* p_Png24; //24位png格式 C_Sprite* p_Png32; //32位png格式 DVECTOR2 translation; // box的屏幕坐标 int alpha; // box的透明度 static const int VELOCITY; // box的移动速度,为常量 static const int ANIMATION_SPEED; // box的动画变化速度,为常量 }; C_DemoA::C_DemoA() { alpha = 255; p_Background = new C_Sprite(_T("demoa_background.

深度探索DxFramework 3-2

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 第3章 步入二维游戏的世界 2 3.5 DxFramework对精灵的封装实现 3.5.1 什么是精灵 3.5.2 精灵的实现——C_Sprite类 3.6 游戏中的Game Object 3.6.1 game object的定义 3.6.2 二维的game object GameObject2D类

深度探索DxFramework 3-1

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 第3章 步入二维游戏的世界 1 3.1 二维动画的原理 在介绍计算机动画的原理之前,先谈谈大家都非常熟悉的电影的播放原理。播放电影的时候需要一大盘的电影胶片。胶片上面就是一帧一帧连续的静止图像。当播放的时候,把胶片按播放顺序,依次通过播放机的镜头,这样胶片上的图像将会逐帧投影到银幕上。因为人眼存在着视觉暂留的生理现象。当眼睛正在观察的物体突然消失的时候,被观察的物体还能在人眼中存留约1/24秒左右。因此,只要一系列本来就是连续的静止的图像,当以合适的速度逐个通过人眼的时候。便会产生连续的“会动”的视觉效果。 根据人的视觉存留时间可以知道,当电影胶片以每秒24帧的速度播放时,人们看到的就是和现实生活中速度相同的画面。当电影胶片以每秒大于24帧的速度播放时,画面中的各种动作将会变快,这就是俗称的“快镜头”。而如果电影胶片以每秒低于24帧的速度播放时,画面中的各种动作将会变慢,这就是俗称的“慢镜头”。 计算机动画的原理和播放电影的原理是类似的。举一个简单的二维动画例子:假如要做一个人物走动的二维动画,首先要研究人走路时身体各部位,如躯干、四肢移动摆动的位置。然后按相应时间相应的位置,把这些连续动作绘制成一副副的图。在计算机中就可以存储在一些图片文件中。这些“一副副的图”其实就是类似于电影胶片。把图从磁盘文件中载入到内存,然后按顺序将其逐帧在屏幕中绘制出来,就类似于播放电影的过程。当一组动作播放完成后,再从头从动作的第一帧播放,周而复始,就形成了连贯的动画。 三维动画和二维动画播放原理是一致的,也是一帧一帧地在屏幕中绘制。与二维动画类似,三维动画也可以分实时和非实时。我们玩的三维计算机游戏的游戏画面其实就可以认为是一种实时三维动画,这些画面都是在每一帧显示前由计算机实时地计算生成。非实时三维动画则用相关软件预先逐帧计算好并且存储在文件中,播放的时候从文件中逐帧读取数据显示即可。在本章中先讨论二维动画。 3.2 基础数学工具 接着介绍是vector2.h文件中的模板类和函数。VECTOR2定义了一个二维矢量的模板类。 #pragma once #include "globals.h" #include "error.h" //最小误差,意思是两浮点数之差为小于0.0001的时候, //就认为这两浮点数是相等的。 const XFLOAT VECTOR2_ZERO_TOLERANCE = 0.0001; /* MSVC6 cannot use the overloaded operators due to a compiler bug/feature */ #if _MSC_VER < 1300 #ifndef NO_TEMPLATE_SELECTION #define NO_TEMPLATE_SELECTION #endif #endif template< class T > class VECTOR2 { public: VECTOR2() {} VECTOR2(const T& x, const T& y) : x(x), y(y) {} //复制Direct3D的D3DXVECTOR2类型数据的内容 VECTOR2(const D3DXVECTOR2& v) : x((T)v.

深度探索DxFramework 2-2

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 第2章 DxFramework的架构剖析 2 2.3 DxFramework的内存泄漏检测机制 内存泄漏(memory leak)是使用C/C++等程序设计语言进行编程时常常见到的一个问题。内存泄漏给程序运行时带来的影响有很多。一般最后的结果要么是程序死掉;要么是提示系统内存不足。还有一种可能就是程序不会死掉,但是程序的响应速度会明显变慢。 2.3.1 内存泄漏的原因 产生内存泄漏的原因一般是如下几点: 动态分配了内存空间,在不需要时忘记释放。 动态分配了内存空间,在不需要时忘记释放。 对某些API函数的不正确使用,导致内存泄漏。 在编程时忘记释放不需要的内存空间是编程时很常见。动态分配的内存在使用完毕后,如若不需要了就一定要释放。如果不释放,那就会造成内存的泄漏。如果造成内存泄漏的代码经常被调用的话,那么内存泄漏的数目就会越来越多的。从而影响整个系统的运行。 如下面的代码段: void SomeOperation() { int* pBuffer = new int[32]; for( int i=0; i<32 ; ++i) { pBuffer[i] = i*2+1; } } 很明显,上述的局部变量pTemp指向了一段从堆(heap)空间中分配的内存空间,而在函数退出时没有作任何的释放操作。一旦调用此函数就将导致了内存泄漏。当这个函数被频繁调用的时候,堆空间的内存空间将会被消耗殆尽。 因为代码编写的问题,会导致某些动态分配的内存根本就无从回收,比如下面的代码段: void SomeOperation() { int* pBuffer1 = new int[32]; int* pBuffer2 = new int[32]; pBuffer1 = pBuffer2; if( pBuffer1 ) { delete [] pBuffer1; } } 这样,pBuffer1最初指向的那段内存空间的首地址就丢掉了,无法恢复了。这时候最初分配的那一段内存空间就无法释放掉。 Windows提供了一些特殊的API,如FormatMessage。如果给它参数传递的函数有FORMAT_MESSAGE_ALLOCATE_BUFFER,它会在函数内部动态分配一块内存缓冲区,返回给用户。但是这个内存缓冲区需要用户显式调用LocalFree来释放。如果用户忘了的话。也会产生内存泄漏。如下面的代码段: #include <windows.h> #include <iostream> using namespace std; void FormatAndPrintOneMessage(DWORD dwError) { HLOCAL hLocal = NULL; // 用来存储返回的描述错误信息的字符串的内存缓冲区 BOOL fOK = FormatMessage( // 指定标志,动态分配一块缓冲区 FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ALLOCATE_BUFFER , NULL , dwError , MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), // 返回动态分配的内存缓冲区 reinterpret_cast<LPTSTR>(&hLocal), 0 , NULL ); if( hLocal && fOK ) { cout<<"Error Message: "<<(reinterpret_cast<LPCTSTR> (LocalLock(hLocal)))<<endl; // 如果忘记了这一句,将会导致通过FormatMessage函数动态分配的 // 内存无法释放,从而导致内存泄漏 LocalFree(hLocal); } else { cout<<"Error number not found"<<endl; } } void main() { FormatAndPrintOneMessage(5); } 检查已经发布的程序是否存在内存泄漏实在是费时费力,所以我们要把内存泄漏扼杀在萌芽状态。在编码过程中就要时刻进行检查。

深度探索DxFramework 2-1

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 第2章 DxFramework的架构剖析 1 2.1 DxFramework的全局头文件 在开始着手分析DxFramework之前,我们有必要先弄懂DxFramework所定义的一些在其引擎代码内部中频繁使用的一些数据类型,宏,和全局函数。 众所周知,由于C++语言的灵活性和自由性;在不同的操作系统平台下,不同的编译器对同一关键字所指定的数据类型所占字节大小是不一致的——C++标准委员会对此也并没有做统一的要求。以int类型为例,C++标准委员会只是要求此类型的大小至少不小于16位。例如在Microsoft Win32平台下,Visual C++6编译器所实现的int是32位整形数据。而在DOS系统下,Borland C++ 3.1实现的int则只有16位。因此,为了代码的平台移植,或者是便于版本的数据类型升级和扩充,一般的大型软件系统都有其自定义的数据类型。以Microsoft定义的win32数据类型为例,就有诸如无符号双字类型,32位的DWORD;无符号单字类型,十六位的WORD;无符号的整形数据,UINT等等。DxFramework也不例外,它也有着它自身的预定义数据类型,它们定义在globals.h文件中,现在我们来逐个分析。代码如下: //globals.h #define WIN32_LEAN_AND_MEAN #define DIRECTINPUT_VERSION 0x0800 //指定使用的DInput版本 /* 忽略编号为4786的编译器警告 当变量标识符名字过长(超过255个字符)的时候,调试器无法调试变量标 识符号超过255个字符长度的代码。无法在调试器中查看、计算、更新或监视被截断的符号。调试器在调试过程中 将会把变量标识符“截短”至255个字符。有时在嵌套声明的变量名中,会出现一串长的警告,在使用STL 的时候, 这种警告会经常出现,使用此指令可以关掉此警告 */ #pragma warning(disable: 4786) //用来进行内存侦测的起到开关作用的宏 #ifdef _DEBUG #define _CRTDBG_MAP_ALLOC //定义此宏,使得CRT内存泄漏侦测函数可用,此宏在crtdbg.h中定义 #define _INC_MALLOC #define enw DEBUG_NEW #endif //定义使用UNICODE的宏 #define UNICODE //如果宏UNCODE定义了,则把宏_UNICODE也定义 #ifdef UNICODE #define _UNICODE #endif #define USE_DOUBLE_FLOAT_PRECISION /* 如果定义了USE_DOUBLE_FLOAT_PRECISION宏 XVECTOR2定义为用双精度浮点数类型实例化模板类 类型的DVECTOR2替代为,XFLOAT定义为如果没有定义的话,就把XVECTOR2定义为单精度浮点数 实例化的模板类类型FVECTOR2,XFLOAT定义为floatFVECTOR2,DVECTOR2类型在vector2.h中定义, 稍后详述 */ #ifdef USE_DOUBLE_FLOAT_PRECISION #define XVECTOR2 DVECTOR2 #define XFLOAT double #else #define XVECTOR2 FVECTOR2 #define XFLOAT float #endif //预包含engine所要使用的系统头文件 #include <tchar.

深度探索DxFramework 1

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 第1章 DxFramework工程简介 1.1 工程的来源和作者 DxFramework是由Corey于年月发起的。Corey 开发了项目中最初的2D游戏引擎。并且负责了游戏所需的艺术资源的相关工作。他创建了DxFramework的第一个版本。Corey现在在Maxis公司工作,不再是DxFramework的主要的开发者了。而随后加入的Jonathan现在已经是项目管理员。他在Laird教授的领导下参与了程序设计的很多方面的工作。还有一位重要的贡献者是David Yeung,作为DxFramework的重要组成部分的3D Framework和相关示例demo的最原始的版本正是由David Yeung所编写的。还有就是Nuttapong,Nuttapong在David Yeung之后对3D Framework部分做了大量的扩充,增加了许多的功能以及一些demo和sample。 另外还对DxFramework作出贡献的人员还有: Adam Tercala创建了world map demo的最初版本 Jeremy Lee创建了sound demo(DEMO C)的最初版本,并且撰写了C_Sound类 Evan Leung创建了最初的用户接口类(User Interface Object class C_UIObject)以及一系列继承自此类的其他类。 1.2 工程的配置 本书剖析的版本是0.93版本,这个版本是2004月8月16日发布的。也是在本书截稿为止的最新版本。在DxFramework的主页中所发布的是三个Zip格式的压缩包。它们分别是: DxFramework-binary-0.9.3.zip DxFramework-engine-0.9.3.zip DxFramework-0.9.3.zip DxFramework-binary-0.9.3.zip只是包含了DxFramework的所发布的可执行数据文件版本。没有相关的源代码。而DxFramework-engine-0.9.3.zip也只是包含了DxFramework的引擎框架代码,而没有示例的代码以及运行所需要的相关文件和数据。而DxFramework-0.9.3则两者兼备。如果是利用DxFramework来编写我们自己的游戏,那么当然选择基于DxFramework-engine-0.9.3,但是本书是通过剖析引擎和示例代码来学习游戏设计技术的,因此本书的剖析对象是DxFramework-0.9.3.zip的内容。 下载解压缩之根目录有如下的一些文件和目录,目录如下: 目录 内容 Data 存放示例demo"pic pac"所需的地图数据文件 Docs 存放DxFramework相关的文档 Images 存放DxFramework所需的一些艺术资源,比如一些示例程序所需要的图片等等 Resources 存放DxFramework所用到的图标文件,里面是big.ico和small.ico文件 Sounds 存放DxFramework使用到的一些声音文件,有wav,mp3,mid格式 Source 存放了DxFramework的引擎和示例的原代码,这里面的内容便是本书的重点部分 Frustum 点击鼠标将能绘制该视截体的轮廓,这样可以移开camera到别的位置去看看这个视截体像什么。悬浮在空中的球,当鼠标点击的时候,它会依据它在视截体内与否来决定是否改变其纹理。 Models Models Demo装载了MD2格式的模型和X格式的模型。MD2的动画可以循环播放 Seek and Hide 追踪和躲藏,演示一个简单的AI游戏 Simple Demo 本demo演示了如何使用DxFramework来开发一个3D游戏。这个demo的代码有很多的注释和演示。 Ray Tracking 这个demo演示了如何使用鼠标来点击选中不同的DxFramework图元。鼠标点击点将会变成一个会延伸扩展的球的球心。 LandScape and Billboard 本demo展示一个通过高度图生成的风景地貌。另外还展现了公告板技术。 Split 演示如何把一个基本图元切割成更小的基本图元 MD3 Demo 演示了使用ID Software定义了md3文件格式的模型 BSP 演示了使用二叉空间分割树(binary space partitation tree)对场景数据进行组织 文件如下:

深度探索DxFramework 0

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com #前言 这系列文章的面世,既可说是偶然,也可谓是必然。 在本世纪初的几年,中国的网络游戏业如同蛰伏着等待破茧而出的蝶蛹一样。看似平静,其实内部正蕴藏着巨大的商机和市场。那时我还在南京的校园里,在计算机前编织着游戏梦。作为一名理工科的学生,当时的我对日后如雨后春笋般的网络游戏所含的巨大利润没有太多的敏锐嗅觉。当时只是为了心目中的一种理想,一种爱好去编程,去学习设计自己的游戏。 无法忘记那段激情燃烧的岁月。在上大学之前没有接触过计算机的我,为了弥补先天的不足。在那一段时间里如同海绵吸水般从图书馆,从网络中吸取游戏设计相关的知识。也正是在那一段时间里,知道了享誉全球的John Carmack;知道了FreeMind、云风、softboy等一批国内的先行者;知道了他们在求知过程中所经历的酸甜苦辣。那时候网络才刚刚普及,费用奇高。我在学习过程中也时常感叹资料的匮乏和不系统性。四年的学习生涯很快过去,离开校园的我,顺理成章地进入了这个行业。 有谁能理解在一个身处起步阶段的游戏产业的业界人,从学校进入社会时所经过的各种各样的挫折,困惑和磨练呢?为了提升自我,程序员们往往需要不断地学习,学习,再学习。互联网的普及给程序员提升自我的水平带来了更大的便利和更广泛的知识来源。在一次偶然的机会,其实也是一种必然,互联网上的DxFramework项目引起了我的注意。通过阅读这个项目的源代码,我学到了很多游戏开发的知识,也写了很多阅读笔记和心得文档。然而因为工作的繁忙和需要,我也要花很多业余时间去从其他的开源项目中去学习,种种的原因使得我对DxFramework的学习也是时断时续,但也总算是一直都坚持了下来。 人生中总是有这样那样的挫折。工作的变动,使得我有机会去专心整理梳顺DxFramework的知识内容。也是一个可称为必然的偶然的机会,我萌生了对DxFramework项目写一本书的想法。相对充足的时间允许我去实现我的想法。作为一个对自己知识和经验的总结;也作为一种知识的传承吸纳;便诞生了这一系列文章。 这本书不是一本DirectX开发入门教程,也不是一本C++程序设计语言教程;更不是一本数学入门教程。本书的定位是:通过剖析一个完整的,开放源代码的游戏应用程序框架(game application framework),以及使用这框架开发的一些实例。从而掌握游戏程序设计基础知识和设计思维。 在阅读本书之前,或在阅读本书的同时,读者应首先对C++程序设计语言;Microsoft DirectX开发包;以及和3D图形程序设计相关的数学知识有一个大致的了解。“大致的”的了解意味着读者能基本理解Direct3D的工作方式,以及相关的基础知识。比如读者应该能对诸如“顶点”,“纹理”等基础概念有一个大概的认识。当然,DirectX/Direct3D是一个很大的体系,读者不可能也不必要事无巨细地穷经皓首面面俱到。要强调的是,尽管本书不是一本C++语言教程和DirectX教程,但是在剖析代码时所涉及到的C++语言,Direct3D,乃至3D数学的知识点,本书都将力求讲细讲透。 对于有一定C++程序设计语言和Direct3D基础知识,对游戏开发有浓厚兴趣,跃跃欲试想登堂入室的读者。本书将会是你很好的选择。