□ 游戏配乐
我相信很多人定同意音乐在游戏里面所占地位回想下国内RPG经典「仙剑奇侠传」剥掉音乐这个层面整个游戏将会逊色不少尤其适当场景搭配适当音乐更能让玩家融入剧情当中该哭时候哭该笑时候笑大概就很切中要领了RPG剩下音效部份并不特别突出大抵上知道砍人时候有挥剑声音就可以了所以在音效表现方面通常比较不那麽注重而即时战斗游戏着重在厮杀音效表现上大片人马片混杂声音这其中牵涉到混音部份我们底下也会探讨到读完这篇文章你会学习到什麽时候该用什麽样程式作法来表现游戏另个生命:音乐和音效
□ 从MIDI开始
早期DOS下音乐部份大多数采用声霸卡规格副档名为CMF者便是这种格式当然游戏通常不会让你看到真正作法但是内部采用这种格式居多是无庸置疑而WINDOW下游戏以光碟发行者居多为了充分达到空间利用阶段游戏中会大量使用WAV格式档案或是直接将音乐烧成音轨格式尤其很多游戏喜欢采用第片资料片第 2片音乐片作法平常不玩游戏还可以当成音乐CD来听算是满有质感件事当然我意思是这些音乐必须要声声入耳如果音乐本身庸庸碌碌即使烧成音轨样是庸庸碌碌改变不了这个事实
在WINDOW下考量到空间大小MIDI格式音乐档绝对是最佳选择首 5分钟MIDI了不起十万字元大小这跟WAV格式分钟占用量以MB计简直是小巫见大巫所以网站WebSite上音乐游戏音乐都很适合用MIDI来表现而音乐部份我个人注重旋律至於首音乐本身使用到乐器数量我倒是很少去注意人耳朵听东西有定极限只要不产生杂音配合优美旋律大致上都可以接受
□ 播放MIDI程式作法
游戏中播放音乐要点就是循环播放也就是播放完毕以後要让他从头开始播放直到场景更换或是游戏结束为止所以当MIDI档案播放完毕以後必须要能通知程式让程式做出适当处理播放MIDI作法只要藉由WINDOW多媒体支援马上就搞定了甚至直接从HELP作法剪过来稍微修改下也能符合需要这种东西相当公式化A君和B君写出来程式码也大致上会长得差不多废话不多说看看程式多麽简单便是:
CMidi
{
public:
DWORD Play(HWND,char* FileName);
void Replay;
void Stop;
private:
UINT wDeviceID;//MCI装置代号
DWORD dwReturn;
MCI_OPEN_PARMS mciOpenParms;
MCI_PLAY_PARMS mciPlayParms;
MCI_STATUS_PARMS mciStatusParms;
MCI_SEQ_SET_PARMS mciSeqSetParms;
};
将他包装成个类别来使用也可以而介面部份需要单纯化从直觉上来说第个动作就是播放(Play)接着是重播(Replay)最後当然是善後工作了(Stop)不多不少刚好 3个当然你会想到是不是需要个暂停介面没问题这不是什麽难事花额外 3分钟应该可以胜任愉快
了解类别大致上长相以後让我们来看看实作部份是怎麽回事先从CMidi::Play开始:
DWORD CMidi::Play(HWND hwnd,char* MidiFile)
{
// 开启Midi硬体装置我们使用般内定值
mciOpenParms.lpstrDeviceType = "sequencer";
//这个叁数就是要播放MIDI档案名称
mciOpenParms.lpstrElementName = MidiFile;
// 使用Message方式来播放MIDI而不是STRING方式
(dwReturn = mciSendCommand(NULL, MCI_OPEN,
MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
(DWORD)(LPVOID) &mciOpenParms)
(dwReturn);
// The device opened successfully; get the device ID.
wDeviceID = mciOpenParms.wDeviceID;
// Check the output port is the MIDI mapper.
mciStatusParms.dwItem = MCI_SEQ_STATUS_PORT;
(dwReturn = mciSendCommand(wDeviceID, MCI_STATUS,
MCI_STATUS_ITEM, (DWORD)(LPVOID) &mciStatusParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
(dwReturn);
}
// 为了达成重复播放目必须让我们程式能够接收到
// MM_MCINOTIFY讯息这个函示呼叫方式就是传递
// WM_PLAY讯息给装置叫他开始播放
mciPlayParms.dwCallback = (DWORD) hwnd;
(dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY,
(DWORD)(LPVOID) &mciPlayParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
(dwReturn);
}
(0L);
};
播放MIDI方式有两种第种是利用字串命令硬体动作第 2种是传递讯息方式我们采用第 2种原因很清楚了必须透过讯息传递我们才能得知音乐是否播放完毕了
接下来我们看看Cmidi::Replay是怎麽回事:
void CMidi::Replay
{
mciSendCommand(wDeviceID, MCI_SEEK,MCI_SEEK_TO_START, NULL);
mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD)(LPVOID) &mciPlayParms);
}
真是不可思议地简单呀函示里面只包含两条呼叫第条呼叫送讯息给装置叫他把MIDI播放指标移到最开头部份也就是MCI_SEEK_TO_START
作法就像移动档案指标样接着第 2条指令光看也明白就是叫他继续播放就是了而且别忘了MCI_NOTIFY当下次播放完毕还是得用讯息通知我们程式
最後看下Cmidi::Stop作法:
void CMidi::Stop
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
}
越来越单纯了里面只有包含个函示呼叫其中讯息叁数MCI_CLOSE就是结束整个音乐播放当你结束播放以後要播放另首音乐很简单再次呼叫Cmidi::Play即可
整个类别使用思路方法大致上是这样:首先配置个实际CMidi物件给程式只要在全域地方下条指令 CMidi midi;即可尔後midi就是真实物件了在场景化部份呼叫midi.Play(hwnd,"ff3celes.mid");输入正确MIDI档名即可此处我播放是太空战士 3代音乐只是示范下当然这首音乐确实很棒就是了而在讯息回圈里面我们必须定义个讯息:
MM_MCINOTIFY:
midi.Replay;
;
在音乐播放完毕以後我们讯息回圈会收到MM_MCINOTIFY这个讯息这时候如同我们前面所言呼叫Cmidi::Replay即可而当场景更换要重新首新音乐或是程式结束时候就是呼叫Cmidi::Stop时机个场景同时间只会存在首音乐所以我们类别表现良好不用担心
最新评论