赛车游戏的2D 编程(VC++)

本文介绍了使用VC++进行2D赛车游戏编程的详细过程,涵盖了DirectX的DDraw、DSound、DInput和DPlay的使用,包括游戏初始化、用户输入处理、声音管理和网络联机功能。文章通过cApplication、cWindow、cInputDevice、cSurface、cSprite、cSound等类的实现,展示了游戏框架和关键功能的细节。
摘要由CSDN通过智能技术生成

                          赛车游戏的2D 编程

转载请注明出处

本文章的下载地址,请单击此链接

 

         赛车是一个简单的游戏,可是麻雀虽小,五脏具全。它用DDraw实现了精灵的绘制,用DSound

实现游戏音效,用DInput 实现了键盘和鼠标接口,用DPlay实现了联网。

游戏运行的初始界面如图3.18 所示,游戏的竞赛场面如图3.19 所示。

这个游戏使用基础库cMain.libcMain.lib库是打包的DirectX库。在编译这个工程前,要确保自

己的计算机上安装了DirectX SDK 8.0或者9.0(注意是DirectX SDK,不是运行库)。如果已经安装了

SDK,编译仍有问题,那么请检查一下DXincludelibrary路径是否已经包括在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 个很重要的虚函数,它们是AppInitializedExitApp

DoIdle 函数。

当应用程序开始启动的时候需要调用AppInitialized函数。当退出游戏的时候,需要调用ExitApp

它负责销毁AppInitialized 创建时分配的内存和其他资源。当没有任何窗口消息需要处理的时候,

cApplication 类将调用DoIdle虚函数,从而允许用户处理自己的游戏。

_ cWindow

如果注意cApplication 类的声明,会看到它定义了一个cWindow 类成员变量。cWindow类负责在

游戏中创建主窗口。这个类只在库内部使用,所以没有必要去修改它的属性。

_ cInputDevicecKeyboardcMouse

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类的成员变量和相关精灵的信息。通过这个

类,可以自动的使精灵走动,而不用担心源页面的位置和大小。

_ cSoundInterfacecSoundcWavFile

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 类声明如下:

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值