本文主要是介绍赛车游戏的2D 编程(VC++),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
赛车游戏的2D 编程
转载请注明出处
本文章的下载地址,请单击此链接
赛车是一个简单的游戏,可是麻雀虽小,五脏具全。它用DDraw实现了精灵的绘制,用DSound
实现游戏音效,用DInput 实现了键盘和鼠标接口,用DPlay实现了联网。
游戏运行的初始界面如图3.18 所示,游戏的竞赛场面如图3.19 所示。
这个游戏使用基础库cMain.lib。cMain.lib库是打包的DirectX库。在编译这个工程前,要确保自
己的计算机上安装了DirectX SDK 8.0或者9.0(注意是DirectX SDK,不是运行库)。如果已经安装了
SDK,编译仍有问题,那么请检查一下DX的include和library路径是否已经包括在VC++的Option
列表中。
图3.18赛车游戏初始运行图
图3.19赛车游戏运行图
3.8.1 cMain 游戏库
打开工程文件(.dsw)的时候会发现该工程中包括了两个项目。一个项目是运行程序,它调用了
cMain 库。而另一个项目是就DirectX的打包库cMain,这个打包库几乎包括了游戏可能需要的所有功
能。这个库包含了14 个类。下面就来介绍这些类。
_ cApplication 类
classcApplication
{
protected:
LPSTRm_lpszAppName;
LPSTRm_lpszwndClassName;
DWORDm_ColorDepth;
DWORDm_ScreenHeight;
DWORDm_ScreenWidth;
public:
BOOLm_bActive;
voidPreventFlip();
boolm_bDontFlip;
HWNDGetMainWnd();
LPDIRECTDRAW7GetDirectDraw();
LPDIRECTDRAW7m_pDD;
LPDIRECTDRAWSURFACE7m_pFrontBuffer;
LPDIRECTDRAWSURFACE7m_pBackBuffer;
cApplication();
~cApplication();
staticHINSTANCE m_hInst;
staticHINSTANCE GetInstHandle() { return m_hInst; };
BOOLInitApplication();
BOOLRunApplication();
BOOLInitDirectX();
virtualvoid ExitApp();
virtualvoid DoIdle();
virtualvoid AppInitialized();
private:
cWindowm_pWindow;
};
cApplication 类是一个简单的Win 32程序框架的封装。既然要用DirectX,那么这个类就负责为
DirectDraw 创建基本的框架。在cMain库中,会发现一个全局函数CreateApplication(),它就负责这项工
作。CreateApplication()是一个虚函数,它需要在游戏自身的项目中创建而且需要返回应用程序的实例。
在游戏创建过程中,cApplication 类中有3 个很重要的虚函数,它们是AppInitialized、ExitApp和
DoIdle 函数。
当应用程序开始启动的时候需要调用AppInitialized函数。当退出游戏的时候,需要调用ExitApp,
它负责销毁AppInitialized 创建时分配的内存和其他资源。当没有任何窗口消息需要处理的时候,
cApplication 类将调用DoIdle虚函数,从而允许用户处理自己的游戏。
_ cWindow 类
如果注意cApplication 类的声明,会看到它定义了一个cWindow 类成员变量。cWindow类负责在
游戏中创建主窗口。这个类只在库内部使用,所以没有必要去修改它的属性。
_ cInputDevice,cKeyboard和cMouse类
cInputDevice 类代码如下所示:
classcInputDevice
{
private:
staticint m_iRefCount;
protected:
staticLPDIRECTINPUT8 m_lpDI;
public:
cInputDevice();
virtual~cInputDevice();
BOOLCreate()
{
HRESULThRet;
if(!m_lpDI)
{
hRet=DirectInput8Create(GetMainApp()->GetInstHandle(),DIRECTINPUT_VERSION,
IID_IDirectInput8,(void**)&m_lpDI, NULL);
ifFAILED(hRet)
returnFALSE;
}
//引用计数递增
m_iRefCount++;
returnTRUE;
}
voidDestroy()
{
142 Visual C++游戏开发技术与实例
m_iRefCount--;
if(m_iRefCount== 0)
{
if(m_lpDI!= NULL){
m_lpDI->Release();
m_lpDI= NULL;
}
}
}
};
cKeyboard 类代码如下所示:
classcKeyboard : cInputDevice
{
private:
staticLPDIRECTINPUTDEVICE8 m_lpDIKeyboard;
staticchar* m_KbdBuffer;
public:
BOOLCheckKey(const int cKey);
voidProcess();
voidDestroy();
BOOLCreate();
cKeyboard();
virtual~cKeyboard();
};
cMouse 类代码如下所示:
classcMouse : cInputDevice
{
public:
cMouse();
virtual~cMouse();
private:
longm_lXPos;
longm_lYPos;
DWORDm_bButton0;
DWORDm_bButton1;
staticLPDIRECTINPUTDEVICE8 m_lpDIMouse;
HANDLEm_hMouseEvent;
public:
DWORDGetX() { return m_lXPos; };
DWORDGetY() { return m_lYPos; };
BOOLGetRightButton() { return m_bButton1; };
BOOLGetLeftButton() { return m_bButton0; };
voidProcess();
voidDestroy();
BOOLCreate();
};
这3 个类主要处理用户在游戏中的输入信息。既然鼠标和键盘的处理依赖于DirectInput框架,所
第3 章2D 游戏开发143
以需要一个类用来初始化DirectInput 主对象,这就是cInputDevice 类。
在cInputDevice 类中有一个指向DirectInput接口的指针和引用计数。引用计数用来确定当前使用
DirectInput 主接口的类有多少个。注意引用计数和接口指针都是静态变量。cMouse类和cKeyboard类
都是从cInputDevice 类继承而来,使用同样的DirectInput 主对象。
cKeyboard 类关心键盘的输入。它有一个静态的变量,用来缓冲每个键值的状态。由于这个缓冲
是静态的,它允许在代码中任意一个地方创建cKeyboard对象,而使用同一块buffer。
cMouse 类关心鼠标的输入,它的工作原理和cKeyboard类类似。每次调用Process()函数的时候,
它改变内部变量从而反映鼠标在当前屏幕的位置和状态。
_ cSurface 类和cSprite类
cSurface 类声明如下:
struct SURFACE_SOURCE_INFO
{
HINSTANCE m_hInstance;
UINT m_nResource;
int m_iX;
int m_iY;
int m_iWidth;
int m_iHeight;
};
class cSurface
{
public:
SURFACE_SOURCE_INFO m_srcInfo;
void Restore();
LPDIRECTDRAWSURFACE7 GetSurface();
UINT Width();
UINT Height();
void Destroy();
COLORREF m_ColorKey;
BOOL Draw(LPDIRECTDRAWSURFACE7 lpDest, int iDestX= 0, int iDestY = 0, int iSrcX
= 0, int iSrcY = 0, int nWidth = 0, int nHeight =0);
BOOL Create(int nWidth, int nHeight, COLORREFdwColorKey = -1);
BOOL LoadBitmap(HINSTANCE hInst, UINT nRes, intnX = 0, int nY = 0, int nWidth =
0, int nHeight = 0);
cSurface(HINSTANCE hInst, UINT nResource, intnWidth, int nHeight, COLORREF
dwColorKey = -1);
cSurface();
virtual ~cSurface();
protected:
UINT m_Height;
UINT m_Width;
LPDIRECTDRAWSURFACE7 m_pSurface;
};
cSprite 类声明如下:
class cSprite
144 Visual C++游戏开发技术与实例
{
public:
void Rewind();
BOOL IsBegin();
BOOL IsEnd();
int m_iSpriteHeight;
int m_iSpriteWidth;
void Previous();
void Next();
int m_iRows;
int m_iCols;
int m_iAbsolutePosition;
BOOL Create(HINSTANCE hInst, UINT nResource, intiTileWidth, int iTileHeight,
COLORREF dwColorKey, int iSpriteWidth,intiSpriteHeight);
BOOL Draw(LPDIRECTDRAWSURFACE7 lpDest, intiDestX, int iDestY, BOOL bAdvance = TRUE,
int iSrcX=0, int iSrcY=0, int iWidth = -1, intiHeight = -1);
void Destroy();
cSurface m_surfTile;
cSprite();
virtual ~cSprite();
};
页面类cSurface 是DirectX页面对象的打包。cSurface是一个结构,在显存中它拥有游戏中所用到
的图形,这样在游戏的每次循环中都可以轻松地重新绘制屏幕。
cSprite 类是处理精灵的打包类。它拥有一个cSurface类的成员变量和相关精灵的信息。通过这个
类,可以自动的使精灵走动,而不用担心源页面的位置和大小。
_ cSoundInterface,cSound和cWavFile类
cSoundInterface 类声明如下:
class cSoundInterface
{
protected:
static LPDIRECTSOUND8 m_pDS;
static LPDIRECTSOUNDBUFFER m_pDSBPrimary;
public:
void SetListernerPosition(float fX, float fY,float fZ);
void Destroy();
LPDIRECTSOUND8 GetDirectSound();
cSoundInterface();
HRESULT Initialize( HWND hWnd, DWORD dwCoopLevel,DWORD dwPrimaryChannels = 2,
DWORD dwPrimaryFreq = 22050, DWORDdwPrimaryBitRate = 16);
HRESULT SetPrimaryBufferFormat(DWORDdwPrimaryChannels, DWORD dwPrimaryFreq, DWORD
dwPrimaryBitRate );
virtual ~cSoundInterface();
};
cSound 类声明如下:
class cSound
{
private:
第3 章2D 游戏开发145
DWORD m_dwDSBufferSize;
cWavFile* m_pWaveFile;
public:
void Destroy();
void SetVelocity(float fX, float fY, float fZ);
void SetPosition(float fX, float fY, float fZ);
LPTSTR m_sFileName;
HRESULT Stop(BOOL bOverride = FALSE);
BOOL m_bIsPlaying;
LPDIRECTSOUND3DBUFFER Get3DInterface();
HRESULT RestoreBuffer(BOOL *bRestored);
HRESULT Play(DWORD dwPriority = 0, DWORD dwFlags= 0);
LPDIRECTSOUNDBUFFER m_pSoundBuffer;
LPDIRECTSOUND3DBUFFER m_p3DInterface;
HRESULT Create(LPTSTR lpszFileName,DWORDdwCreationFlags,GUID guid3DAlgorithm);
cSound();
virtual ~cSound();
protected:
HRESULT FillBuffer();
};
cWavFile 类声明如下:
class cWavFile
{
public:
WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEXstructure
HMMIO m_hmmio; // MM I/O handle for the WAVE
MMCKINFO m_ck; // Multimedia RIFF chunk
MMCKINFO m_ckRiff; // Use in opening a WAVE file
DWORD m_dwSize; // The size of the wave file
MMIOINFO m_mmioinfoOut;
DWORD m_dwFlags;
BOOL m_bIsReadingFromMemory;
BYTE* m_pbData;
BYTE* m_pbDataCur;
ULONG m_ulDataSize;
CHAR* m_pResourceBuffer;
protected:
HRESULT ReadMMIO();
HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest );
public:
cWavFile();
~cWavFile();
HRESULT Open( LPTSTR strFileName, WAVEFORMATEX*pwfx, DWORD dwFlags );
HRESULT OpenFromMemory( BYTE* pbData, ULONGulDataSize, WAVEFORMATEX* pwfx, DWORD
dwFlags );
HRESULT Close();
146 Visual C++游戏开发技术与实例
HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead,DWORD* pdwSizeRead );
HRESULT Write( UINT nSizeToWrite, BYTE* pbData,UINT* pnSizeWrote );
DWORD GetSize();
HRESULT ResetFile();
WAVEFORMATEX* GetFormat() { return m_pwfx; };
};
这3 个类主要负责游戏中声音的处理。cSoundInterface创建DirectSound主对象,从而创建了游戏
中的声音缓冲。推荐在cApplication 类中的AppInitializad 虚函数中初始化这个类,这样就可以在游戏
开始之前初始化声音接口。
cSound 类拥有游戏中声音缓冲。它兼容了DirectSound缓冲的所有普通属性,例如频率、3D声音
和重复。cSound 类使用cWavFile对象从资源或从文件中导入声音。这是一个波形文件的导入类。
_ cMultiplayer 和cMessageHandler类
cMultiplayer 类声明如下:
这篇关于赛车游戏的2D 编程(VC++)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!