• 沒有找到結果。

遊戲音樂

在文檔中 虛擬寵物與市場設計實作 (頁 70-76)

第四章 交易市場與網路

4.3 遊戲音樂

大部份撥放遊戲背景音樂有三種方式 l WAVE 格式

l CD 音軌 l MIDI

我們在遊戲中使用 MIDI,MIDI 是 Musical Instrument Digital Interface 的簡稱。MIDI 不必像 Wave 檔那樣做聲音抽樣,所以檔案不 大但可以長時間演奏。MIDI 是一種只紀錄演奏演奏相關資訊的檔案(像 樂譜),音樂本身並沒有存放在檔案中,所以再撥放時需要【相當於樂 器的裝置】。

在 CPU 不像現在一樣強大時,需要 MIDI 音源器才能撥放 MIDI,現 在的電腦都支援軟體 MIDI,直接使用 CPU 模擬出 MIDI 的聲音。

MIDI 缺點在使用軟體音源時,CPU 負荷高,且無法撥放音源能力 以上的聲音。超過音源的情況,一是無法放入【人聲】,二是同時最大 發音數不夠的情況下,可能有些音色聲音會不見,也就是,製作好的 音樂無法在使用者電腦上 100%呈現。

遊戲中撥放背景音樂方式就是循環撥放,直到遊戲結束。

我們是使用 Windows API 的 MCI(Multimedia Control Interface) 來演奏 MIDI Data。MCI 是 Windows 用來操作多媒體的工具,還可以操 控掃描器、CD、撥放動畫裝置、WAVE、VCR……。

MCI 的控制方法有兩種,Commend String 或 Command Message。

l Commend String 是把 MCI 指令寫成字串再丟出去。

l Command Message 以訊息和參數來組成必要的指令,控制方式較靈 活。

我們使用 mciSendCommand 函數把指令送到 MCI,函數根據欲傳送 的指令選用不同的旗標種類和參數類型。

MCIERROR mciSemdCommand(

MCIDEVICIED devicdID, //指定開啟裝置時所得到的裝置 ID UNIT uMessage, //指定傳送的訊息 midi.Open();

歌曲結束

midi.MciNotify();

停止 midi.Stop();

結束

midi.Close();

撥放音樂 midi.Play();

額外動作 重播音樂

midi.Replay();

choose1

Choose2

YES

NO

我們把使用到的相關函式包裝成一個類別好方便使用。類別定義 如下:

class CMidi { public:

CMidi(): Wnd(0), Id(0) {}

~CMidi() { Close(); }

BOOL Open(CWnd *wnd); //開啟裝置 BOOL Close(); //關閉裝置

BOOL Play(const char *name); //指定撥放的檔案 BOOL Replay(); //重覆撥放

BOOL Stop(); //停止

BOOL MciNotify(DWORD id); //音樂撥放完畢時,接受 //呼叫的函式

protected:

CWnd *Wnd;

DWORD Id; //MCI裝置 Id

} ;

Member Function Member Variables Open() CWnd *Wnd

Close() DWORD Id Play()

Replay() Stop() MciNotify()

圖 4.10 Cmidi 類別圖

了解界面後,接下來看看實作部分。

// 開啟 Midi

BOOL CMidi::Open(CWnd *wnd) { Wnd = wnd;

return TRUE;

}

// 關閉

BOOL CMidi::Close() { return TRUE;

}

// 撥放

BOOL CMidi::Play(const char *name) { DWORD err;

MCI_OPEN_PARMS open; // MCI_OPEN_PARMS結構體物件 // MIDI裝置型態是 sequencer

open.lpstrDeviceType = "sequencer"; open.lpstr ElementName = "itdontrg.mid"; // 初始檔案名稱

if ((err = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYP E|MCI_OPEN_ELEMENT|MCI_WAIT, (DWORD)&open)) != 0)

{ char errstr[256];

mciGetErrorString(err, errstr, sizeof(errst r));

TRACE1("%s\n", errstr);

Wnd->MessageBox(errstr);

return FALSE;

} // 當無法取得裝置時顯示錯誤訊息對話框 Id = open.wDeviceID; // 取得裝置 Id MCI_PLAY_PARMS play;

// 結束撥放時,MM_MCINOTIFY 訊息會被送到

//MCI_PLAY_PARMS結構體的 dwCallback 成員所指定的視窗 play.dwCallback = (DWORD)Wnd->GetSafeHwnd();

if (mciSendCommand(Id, MCI_PLAY, MCI_NOTIFY, (DWORD)

&play))

Id = 0;

return FALSE;

}

return TRUE;

}

// 從頭播放讀進的 Midi 檔案 BOOL CMidi::Replay() { MCI_PLAY_PARMS play;

//為達到重覆撥放,程式必須能夠接受 MM_MCINOTIFY 訊息 //函式的呼叫方式就是就是傳遞 MCI_PLAY 給裝置叫他開始撥放 // MCI_SEEK_TO_START演奏開始位置移動到 Data 最前面 // MCI_WAIT 結束撥放後傳回控制

// 下一次撥放結束時 MCI_NOTIFY 會通知程式

play.dwCallback = (DWORD)Wnd->GetSafeHwnd();

if (mciSendCommand(Id, MCI_SEEK,MCI_SEEK_TO_START|

MCI_WAIT, 0)

|| mciSendCommand(Id, MCI_PLAY, MCI_NOTIFY, (DW ORD)&play)) {

mciSendCommand(Id, MCI_CLOSE, MCI_WAIT, 0);

Id = 0;

}

return TRUE;

}

// 播放完畢

BOOL CMidi::Stop() { UINT id = Id;

if (Id == 0) return FALSE;

Id = 0;

DWORD err;

0)) != 0

|| (err = mciSendCommand(id, MCI_CLOSE, MCI_WAI T, 0)) != 0) { return FALSE; }

return TRUE;

}

// 播放完畢時,接受視窗呼叫的函式 BOOL CMidi::MciNotify(DWORD id) { if (Id != id)

return FALSE;

return TRUE;

}

至於音樂的來源,我們是抓別人的 midi sample,然後取樣,再以 音樂編輯軟體 remix 後輸出新的 midi。

軟體名稱:cakewalk SONAR 介面如下:

圖 4.11 SONAR 編輯音樂

在文檔中 虛擬寵物與市場設計實作 (頁 70-76)

相關文件