BGMを鳴らす
無音の世界で寂しかったのでBGMでも付けてみます。すでに作ってあるサウンドエンジン(2005/12/10)を組み込んで音を鳴らすだけなんで簡単です。マップごとに独自のBGMを用意する。マップ切り替え時にBGMを切り替えるあたりがミソです。ちなみにMIDIファイルは、ドラクエからパクるTAM Music Factoryさんからお借りしています。すばらしい曲が多く、ゲームで使ってもいいそうです。私のつぼにはまるメロディがけっこう多くて気に入ってます。
マップごとにBGMを設定する
一般的にBGMはマップごとに決まってる感じがします。お城に入ればお城のBGMが流れ、フィールドに出ればフィールドのBGMが流れます。というわけでマップごとにBGMを設定しましょう。MapクラスにBGM番号を設定できるようにします。
// BGM番号 private int bgmNo; public Map(String mapFile, String eventFile, int bgmNo, MainPanel panel) { this.bgmNo = bgmNo; ・・・ } /** * このマップのBGM番号を返す * @return BGM番号 */ public int getBgmNo() { return bgmNo; }
MapコンストラクタでBGM番号(bgmNo)を与えて再生するBGMを指定しています。Mapが管理するのはBGM番号だけで実際にBGMを鳴らす処理は入れません。BGMの再生処理は全Mapを管理しているMainPanelで行います。
BGMの再生
マップに割り当てられたBGM番号と実際に鳴らすMIDIファイル名を関連づける必要があります。それがMainPanelのbgmNamesです。
// BGM名(from TAM Music Factory: http://www.tam-music.com/) // BGM番号は0, 1, ・・・というように割り当てられる private static final String[] bgmNames = {"tamhe07.mid", "tamsu02.mid"};
ここにMIDIファイル名の配列を用意してます。BGM番号は配列のインデックスです。つまり、BGM番号0のマップではtamhe07.midが鳴り、BGM番号1のマップではtamsu02.midが鳴るようにします。コンストラクタでマップを作るときにBGM番号を渡してます。
// マップを作成(マップで鳴らすBGM番号を渡す) maps = new Map[2]; // 王の間 maps[0] = new Map("map/king_room.map", "event/king_room.evt", 0, this); // フィールド maps[1] = new Map("map/field.map", "event/field.evt", 1, this);
BGMのロードはloadSound()です。
/** * サウンドをロードする */ private void loadSound() { // BGMをロード for (int i=0; i<bgmNames.length; i++) { try { MidiEngine.load("bgm/" + bgmNames[i]); } catch (MidiUnavailableException e) { e.printStackTrace(); } catch (InvalidMidiDataException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
bgmNamesのMIDIファイルを全部MidiEngineにロードしています。MidiEngineの使い方はサウンドエンジンを参照してください。まあ簡単なので直感的にわかると思いますが。BGMの再生はMainPanelのコンストラクタです。
public MainPanel() { ・・・・ // サウンドをロード loadSound(); // BGMを再生 MidiEngine.play(maps[mapNo].getBgmNo()); ・・・ }
現在いるマップ(maps[mapNo])のBGM番号を取り出して再生しています。最後にマップを切り替えたときにBGMも切り替えないといけません。これはMainPanelのheroMove()です。
/** * 勇者の移動処理 */ private void heroMove() { // 移動(スクロール)中なら移動する if (hero.isMoving()) { if (hero.move()) { // 移動(スクロール) // 移動が完了した後の処理はここに書く // 移動イベント // イベントがあるかチェック Event event = maps[mapNo].eventCheck(hero.getX(), hero.getY()); if (event instanceof MoveEvent) { // 移動イベントなら MoveEvent m = (MoveEvent)event; // 移動元マップの勇者を消去 maps[mapNo].removeChara(hero); // 現在のマップ番号に移動先のマップ番号を設定 mapNo = m.destMapNo; // 移動先マップでの座標を取得して勇者を作り直す hero = new Chara(m.destX, m.destY, 0, DOWN, 0, maps[mapNo]); // 移動先マップに勇者を登録 maps[mapNo].addChara(hero); // 移動先マップのBGMを鳴らす MidiEngine.play(maps[mapNo].getBgmNo()); } } } }
マップの切り替えと同じタイミングでBGMも切り替えればいいですね。MidiEngineは play()を呼び出せば前に鳴ってたBGMは自動的に止まります。自分で止める必要はありません。BGM番号じゃわかりにくいので定数にしておくといいですね。こんなふうに
// BGM番号 public static final int CASTLE = 0; public static final int OVERWORLD = 1; public static final int TOWN = 2; public static final int CAVE = 3; public static final int VILLAGE = 4; public static final int SHRINE = 5; public static final int BATTLE = 6;