发布时间 : 星期日 文章vc++游戏编程指南更新完毕开始阅读479513671ed9ad51f01df2a1
第八章 支撑游戏的基石 1
第七章 我没有想好名字
如果你只靠上面几章所讲述的知识编了个游戏,喜欢的人恐怕会不多?,为什么?因为没有人会玩一个控制不流畅而且声音效果不佳的游戏。为了在游戏中更好地管理各种输入设备,我们需要使用DirectInput。而通过使用DirectX Audio可以在游戏中实现各种更逼真的音乐效果。它们都是DirectX的重要组成部分。使用DirectInput前我们需要#include
7.1 读取键盘数据
首先,我们必须创建一个DirectInput8对象(DirectX 9.0并没有对DInput和DAudio做多大改动),就像这样:
LPDIRECTINPUT8 pInput;
DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&pInput, NULL);
然后,我们需要创建一个DirectInput设备:
LPDIRECTINPUTDEVICE8 pDev;
pInput->CreateDevice(GUID_SysKeyboard, &pDev, NULL);
设置好它的数据格式:
pDev->SetDataFormat(&c_dfDIKeyboard);
设置它的协作级,这里设为独占设备+前台:
pDev->SetCooperativeLevel(hwnd,DISCL_EXCLUSIVE|DISCL_FOREGROUND);
获取设备:
pDev->Acquire();
像上面那样初始化后,我们就已经把Windows对键盘的控制权剥夺了,以后的键盘消息将不会被送入消息循环,我们可以把消息循环中处理键盘消息的语句拿掉了。当然,这时我们需要在程序的适当地方,比如说在刷新游戏时,加入对键盘数据进行读取和处理的语句,就像下面的一段程序:
第八章 支撑游戏的基石 2
#define KEYDOWN(key) (buffer[key] & 0x80) //定义一个宏,方便处理键盘数据 char buffer[256]; //键盘数据
pDev->GetDeviceState(sizeof(buffer),(LPVOID)&buffer); //得到键盘数据 if (KEYDOWN(DIK_XXX)) //如果XXX键被按下…(请参阅附录二) { }
哈哈,真是挺方便的。有时候真的有点怀疑DirectX是不是一种回到遥远的可爱的DOS时…… //处理其它键
…… //处理之
代的“倒退”。因为无论是DirectInput还是DirectDraw都是太像DOS下的做法了。
7.2 读取鼠标数据
读取鼠标数据和读取键盘数据的步骤差不多,首先也是要创建设备:
pInput->CreateDevice(GUID_SysMouse, &pDev, NULL); pDev->SetDataFormat(&c_dfDIMouse);
设置数据格式:
设置协作级:
pDev->SetCooperativeLevel(hwnd,DISCL_EXCLUSIVE | DISCL_FOREGROUND);
获取设备:
pDev->Acquire();
那么怎样读取鼠标数据呢?如果要取得鼠标的当前状态,这样即可: DIMOUSESTATE mouse_stat; //鼠标状态 //得到鼠标状态
pDev->GetDeviceState(sizeof(DIMOUSESTATE),(LPVOID)&mouse_stat); 得到的mouse_stat是一个DIMOUSESTATE类型的结构,它有四个成员:lX,lY,lZ和rgbButtons[4]。其中lX、lY和lZ分别是自上次调用此函数以来鼠标在X轴、Y轴和Z轴(滚轮)方向上移动的距离,而不是鼠标此时的坐标;其距离单位不是像素,但你完全可以把它看做以像素为单位。所以,我们需要定义两个变量mousex=0和mousey=0,然后把lX和lY累加上去即可。这样做的好处是鼠标坐标不再受屏幕的制约,而且屏幕中心的mousex和mousey值可以永远是0,不随屏幕分辨率而改变。rgbButtons是一个存储哪些鼠标键被按下的数组,我们可以这样做来读取它:
//定义一个宏,方便处理鼠标数据
第八章 支撑游戏的基石 3
#define MOUSEBUTTONDOWN(b) (mouse_stat.rgbButtons[b]&0x80)
if (MOUSEBUTTONDOWN(0)) //如果左键被按下… { }
…… //处理右键(1)和中键(2)
…… //处理之
7.3 恢复和关闭DirectInput
7.3.1 恢复DirectInput设备
就像在DirectDraw中那样,使用DirectInput的程序被最小化时DirectInput设备会出现\丢失\现象。恢复的办法很干脆:先关闭DirectInput再重新初始化即可。
7.3.2 关闭DirectInput
关闭DirectInput也是非常简单的(SAFE_RELEASE的定义在4.8节): pDev->Unacquire( ); SAFE_RELEASE(pDev); SAFE_RELEASE(pInput);
7.4 初始化和关闭DirectX Audio
7.4.1 初始化DirectX Audio
使用DirectX Audio前,按规矩还是要先初始化。在下面的这段初始化程序中要用到三个DXAudio提供的对象:IDirectMusicLoader8、IDirectMusicPerformance8和IDirectMusicSegment8。IDirectMusicLoader8顾名思义是用来调入音乐的,IDirectMusicPerformance8可以认为是音频设备,而IDirectMusicSegment8就是代表音乐。
#include
pLoader= NULL;
pPerf = NULL; pSeg = NULL;
IDirectMusicPerformance8* IDirectMusicSegment8*
CoInitialize(NULL); //初始化COM
第八章 支撑游戏的基石 4
CoCreateInstance(CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC, IID_IDirectMusicLoader8, (void**)&pLoader); //创建pLoader对象
CoCreateInstance(CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC, IID_IDirectMusicPerformance8, (void**)&pPerf ); //创建pPerf对象 pPerf->InitAudio(
NULL, //这里可以是一个指向IDirectMusic*对象的指针 NULL, //这里可以是一个指向IDirectSound*对象的指针 hwnd, //窗口句柄
DMUS_APATH_SHARED_STEREOPLUSREVERB, //AudioPath类型
//这里打开了立体声及混响,效果很不错
64, //音乐通道数
DMUS_AUDIOF_ALL, //使用声卡的所有特性
NULL //可以指向一个DMUS_AUDIOPARAMS对象,更详细地说明各种参数 );
7.4.2 关闭DirectX Audio
关闭DXAudio还是老思路,先按7.5.3节的办法停止音乐,然后Release即可:
pPerf->CloseDown(); //关闭
SAFE_RELEASE(pLoader); //释放对象 SAFE_RELEASE(pPerf); SAFE_RELEASE(pSeg);
CoUninitialize(); //停止使用COM
7.5 播放MIDI和WAV音乐
MIDI音乐和WAV音乐在游戏编程中经常用到。其中前者一般是用作背景音乐,而后者多是用在各种音效方面,如发射导弹等等。虽然我们可以用3.4.4节的方法,但使用DXAudio可以更充分地利用硬件资源,从而实现更少的CPU占用率。方法如下: