vc++游戏编程指南(34页).doc
《vc++游戏编程指南(34页).doc》由会员分享,可在线阅读,更多相关《vc++游戏编程指南(34页).doc(34页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、-vc+游戏编程指南-第 34 页第七章 我没有想好名字如果你只靠上面几章所讲述的知识编了个游戏,喜欢的人恐怕会不多J,为什么?因为没有人会玩一个控制不流畅而且声音效果不佳的游戏。为了在游戏中更好地管理各种输入设备,我们需要使用DirectInput。而通过使用DirectX Audio可以在游戏中实现各种更逼真的音乐效果。它们都是DirectX的重要组成部分。使用DirectInput前我们需要#include 并在工程中加入dinput8.lib和dxguid.lib,而使用DirectX Audio前我们需要#include 并在工程中加入dsound.lib和dxguid.lib。7.
2、1 读取键盘数据首先,我们必须创建一个DirectInput8对象Audio做多大改动),就像这样:LPDIRECTINPUT8 pInput; DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,IID_IDirectInput8,(void*)&pInput,NULL); 然后,我们需要创建一个DirectInput设备:LPDIRECTINPUTDEVICE8 pDev;pInput-CreateDevice(GUID_SysKeyboard, &pDev, NULL); 设置好它的数据格式:pDev-SetData
3、Format(&c_dfDIKeyboard); 设置它的协作级,这里设为独占设备+前台:pDev-SetCooperativeLevel(hwnd,DISCL_EXCLUSIVE|DISCL_FOREGROUND);获取设备:pDev-Acquire();像上面那样初始化后,我们就已经把Windows对键盘的控制权剥夺了,以后的键盘消息将不会被送入消息循环,我们可以把消息循环中处理键盘消息的语句拿掉了。当然,这时我们需要在程序的适当地方,比如说在刷新游戏时,加入对键盘数据进行读取和处理的语句,就像下面的一段程序:#define KEYDOWN(key) (bufferkey & 0x80)
4、/定义一个宏,方便处理键盘数据char buffer256; /键盘数据pDev-GetDeviceState(sizeof(buffer),(LPVOID)&buffer); /得到键盘数据if (KEYDOWN(DIK_XXX) /如果XXX键被按下(请参阅附录二) /处理之 /处理其它键哈哈,真是挺方便的。有时候真的有点怀疑DirectX是不是一种回到遥远的可爱的DOS时代的“倒退”。因为无论是DirectInput还是DirectDraw都是太像DOS下的做法了。7.2 读取鼠标数据读取鼠标数据和读取键盘数据的步骤差不多,首先也是要创建设备:pInput-CreateDevice(GU
5、ID_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
6、是一个DIMOUSESTATE类型的结构,它有四个成员:lX,lY,lZ和rgbButtons4。其中lX、lY和lZ分别是自上次调用此函数以来鼠标在X轴、Y轴和Z轴(滚轮)方向上移动的距离,而不是鼠标此时的坐标;其距离单位不是像素,但你完全可以把它看做以像素为单位。所以,我们需要定义两个变量mousex=0和mousey=0,然后把lX和lY累加上去即可。这样做的好处是鼠标坐标不再受屏幕的制约,而且屏幕中心的mousex和mousey值可以永远是0,不随屏幕分辨率而改变。rgbButtons是一个存储哪些鼠标键被按下的数组,我们可以这样做来读取它:/定义一个宏,方便处理鼠标数据#define
7、 MOUSEBUTTONDOWN(b) (mouse_stat.rgbButtonsb&0x80)if (MOUSEBUTTONDOWN(0) /如果左键被按下 /处理之 /处理右键(1)和中键(2)7.3 恢复和关闭DirectInput 恢复DirectInput设备就像在DirectDraw中那样,使用DirectInput的程序被最小化时DirectInput设备会出现丢失现象。恢复的办法很干脆:先关闭DirectInput再重新初始化即可。 关闭DirectInput关闭DirectInput也是非常简单的(SAFE_RELEASE的定义在4.8节):pDev-Unacquire(
8、);SAFE_RELEASE(pDev);SAFE_RELEASE(pInput);7.4 初始化和关闭DirectX Audio 初始化DirectX Audio使用DirectX Audio前,按规矩还是要先初始化。在下面的这段初始化程序中要用到三个DXAudio提供的对象:IDirectMusicLoader8、IDirectMusicPerformance8和IDirectMusicSegment8。IDirectMusicLoader8顾名思义是用来调入音乐的,IDirectMusicPerformance8可以认为是音频设备,而IDirectMusicSegment8就是代表音乐。
9、#include IDirectMusicLoader8* pLoader= NULL;IDirectMusicPerformance8*pPerf = NULL;IDirectMusicSegment8* pSeg = NULL;CoInitialize(NULL); /初始化COMCoCreateInstance(CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC, IID_IDirectMusicLoader8, (void*)&pLoader); /创建pLoader对象CoCreateInstance(CLSID_DirectMusicPerfo
10、rmance, 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 /可以指
11、向一个DMUS_AUDIOPARAMS对象,更详细地说明各种参数 关闭DirectX Audio关闭DXAudio还是老思路,先按节的办法停止音乐,然后Release即可:pPerf-CloseDown(); /关闭SAFE_RELEASE(pLoader); /释放对象SAFE_RELEASE(pPerf);SAFE_RELEASE(pSeg);CoUninitialize(); /停止使用COM7.5 播放MIDI和WAV音乐MIDI音乐和WAV音乐在游戏编程中经常用到。其中前者一般是用作背景音乐,而后者多是用在各种音效方面,如发射导弹等等。虽然我们可以用节的方法,但使用DXAudio可以
12、更充分地利用硬件资源,从而实现更少的CPU占用率。方法如下: 调入MIDI和WAV文件在播放音乐之前,第一步当然是调入音乐文件:CHAR strSoundPathMAX_PATH; /存储音乐所在路径GetCurrentDirectory(MAX_PATH, strSoundPath); /得到程序所在路径strcat(strSoundPath, Sounds); /这里设置音乐在程序路径下的Sounds子目录WCHAR wstrSoundPathMAX_PATH; /存储UNICODE形式的路径/将路径转为UNICODE形式MultiByteToWideChar(CP_ACP, 0,strS
13、oundPath, -1, wstrSoundPath, MAX_PATH);pLoader-SetSearchDirectory(GUID_DirectMusicAllTypes, /搜索所有支持的格式wstrSoundPath,FALSEWCHAR wstrFileNameMAX_PATH; /存储UNICODE形式的文件名/将文件名转为UNICODE形式MultiByteToWideChar(CP_ACP, 0, a.mid, -1, wstrFileName, MAX_PATH);pLoader-LoadObjectFromFile( CLSID_DirectMusicSegment,
14、 /文件类型 IID_IDirectMusicSegment8, /目标对象类型 wstrFileName, /文件名,同样应为UNICODE形式 (LPVOID*) &pSeg /目标对象 播放MIDI和WAV文件调入完音乐之后,在适当的时候可以开始播放音乐:pSeg-SetRepeats(音乐要重复的次数); /DMUS_SEG_REPEAT_INFINITE为无限次pSeg-Download( pPerf ); /将音乐数据传给pPerfpPerf-PlaySegmentEx( pSeg, /要播放的音乐 NULL, /现在只能是NULL NULL, 0, 0, NULL, NULL,
15、NULL /Audiopath,现在先不要管它是什么 停止播放停止播放音乐也是非常简单的:pPerf-Stop( NULL, /停止哪个通道,NULL代表所有通道 NULL, 0, /经过多少时间才停止播放 07.6 在3D空间中播放音乐我们的下一个问题是如何使音乐更逼真,最好能使音乐3D化,这将大大加强真实性。要实现这个其实也不难,首先我们要设定所谓的AudioPath,它可以指定音乐的播放方式。IDirectMusicAudioPath8* pPath; /AudioPathpPerf-CreateStandardAudioPath( /创建AudioPathDMUS_APATH_DYNA
16、MIC_3D, /3D的64, /通道数TRUE, /是否立即激活AudioPath&pPath /要创建的AudioPath然后,我们要从AudioPath中得到一个3D缓存,它将存储音乐的播放位置等信息。IDirectSound3DBuffer8* pBuffer; /3D缓存pPath-GetObjectInPath(DMUS_PCHANNEL_ALL, /搜索全部通道DMUS_PATH_BUFFER, /为DirectSound 缓存0, GUID_NULL,0,IID_IDirectSound3DBuffer8, /缓存类型 (LPVOID*) &pBuffer /要创建的缓存下一步
17、是设定音乐在3D空间的何处播放。例如:pBuffer-SetPosition( , , , DS3D_IMMEDIATE );这条指令把音乐的播放位置设为(-0.1f, 0.0f, 0.0f),由于默认的听众位置在坐标(0, 0, 0)处,脸朝着Z轴的正方向,头朝着Y轴正方向,所以其效果将是听众的右耳听得到声音但左耳听不到声音,就像音乐是从自己的正右方发出。如果把最后一个参数设为DS3D_DEFERRED,此操作将被挂起直到调用IDirectSound3DListener8 : CommitDeferredSettings( )为止,这样可以一次处理多个设定防止反复计算。我们还可以设置音乐源的
18、速度及其播放角度:pBuffer-SetVelocity(vx,vy,vz,DS3D_IMMEDIATE);/设置在x,y,z轴方向的速度/设置播放角度大小(度),inncone为内角度,outcone为外角度/音乐在内角度范围内不衰减,在内外角度之间慢慢衰减,超出外角度时消失pBuffer-SetConeAngles(inncone, outcone, DS3D_IMMEDIATE);pBuffer-SetConeOrientation(x, y, z, DS3D_IMMEDIATE); /设置朝哪个方向播放那么我们如何设定听众的位置呢?可以这样:IDirectSound3DListener
19、8* pListener;pPath-GetObjectInPath( /创建听众0,DMUS_PATH_PRIMARY_BUFFER,0, GUID_NULL,0,IID_IDirectSound3DListener8, (LPVOID*) &pListener/设置听众面向(x1,y1,z1),头朝着(x2,y2,z2)pListener-SetOrientation(x1,y1,z1,x2,y2,z2,DS3D_IMMEDIATE);pListener-SetPosition(x,y,z,DS3D_IMMEDIATE); /听众位置pListener-SetVelocity(vx,vy,
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- vc 游戏 编程 指南 34
限制150内