★さめがめ 効果音★


続いて効果音(SE)について説明します。

効果音はゲームにとって重要な音の1つです。

広い意味での「手ごたえ」も効果音で表現する事が出来ます。

※敵に弾が当たったとかボタンを押したとか色々ですね・・・


効果音の準備


効果音も音源データのファイルを用意する必要があります。

※このシステムで使用可能な効果音データは「wav」形式のみです。

今回も「魔王魂」様に頼ります。

「魔王魂」様の効果音素材、システム音にある「システム12」をwav形式でダウンロードしました。

ダウンロードしたファイルは、プロジェクトフォルダの「Resource\\SEフォルダ」に入れておきます。

私が選んだ曲のファイル名は「se_maoudamashii_system12.wav」でした。


システムへの取り込み


効果音もリソース(資源)の1つですから、テクスチャ(画像)と同じように扱います。

「GameBase.h」を開き、パス付ファイル名を定数化しましょう。

//-----------------------------------------------------------------------------
//ゲーム中で使用するテクスチャ、BGM、SE、フォントのパス付ファイル名を書きます。
//-----------------------------------------------------------------------------
namespace KeyString
{
    const std::string TEXTURE_SAMEGAME = "Resource\\Texture\\Samegame.png";

    const std::string BGM_GAME = "Resource\\BGM\\game_maoudamashii_7_event45.mp3";

    const std::string SE_CLICK = "Resource\\SE\\se_maoudamashii_system12.wav";
}

マウスのクリック音として使いたいので「SE_CLICK」と言う名前にしました。


「SceneGame.cpp」の「Start関数」で効果音を追加します。

//=============================================================================
// シーンの実行時に1度だけ呼び出される開始処理関数
//=============================================================================
void SceneGame::Start()
{
    m_pEngine->AddTexture(TEXTURE_SAMEGAME);

    m_pEngine->AddSE(SE_CLICK);

    m_pEngine->LoadBGM(BGM_GAME);

    m_pEngine->PlayBGM();

    m_samegame.Initialize(4);

    m_bStalemate = false;
}

効果音は一度に複数の音を再生する事がありますので、Add(追加)出来るように作っています。


効果音の再生


効果音の再生には「PlaySE関数」を使います。

BGMと違い、何かのアクションに合わせて再生させますので、再生する場所が大事です。

今回はクリック音として使おうと思っていますが、ブロックを消した時に鳴るようにしたいと思います。

ブロックが消えるのは、Samegaraクラスの「DeleteBlock関数」です。

すでにシステムには効果音を追加していますので、エンジンさえあれば効果音を再生出来ます。

そこで、「DeleteBlock関数」に引数を追加します。

「Samegame.h」を開き、「DeleteBlock関数」に引数を追加します。

    //ブロックの選択
    void SelectBlock(POINT &refPoint);

    //ブロックを消す
    void DeleteBlock(Engine *pEngine);

    //手詰まりチェック
    bool IsStalemate();

「Samegame.cpp」にある本体にも追加しましょう。

//ブロックを消す
void Samegame::DeleteBlock(Engine *pEngine)
{
    if (m_selectBlockNum <= 1) {
        return;
    }

    DeleteSelectBlock();

    FallBlock();

    SlideLine();

    m_score += (m_selectBlockNum - 2) * (m_selectBlockNum - 2);
}

「SceneGame.cpp」の「Update関数」の関数呼び出しに引数を追加します。

    if (m_pEngine->GetMouseButtonSync(DIK_LBUTTON)) {

        if (!m_bStalemate) {

            m_samegame.DeleteBlock(m_pEngine);

        }
        else {

            m_nowSceneData.Set(Common::SCENE_EXIT, false, NULL);
        }
    }

これで「DeleteBlock関数」にエンジンを渡す事が出来るようになりました。

「Samegame.cpp」の「DeleteBlock関数」を開き、効果音の再生を追加しましょう。

//ブロックを消す
void Samegame::DeleteBlock(Engine *pEngine)
{
    if (m_selectBlockNum <= 1) {
        return;
    }

    DeleteSelectBlock();

    FallBlock();

    SlideLine();

    m_score += (m_selectBlockNum - 2) * (m_selectBlockNum - 2);

    pEngine->PlaySE(SE_CLICK);
}

BGMと違い複数の効果音が追加出来るので、どの効果音を再生するか引数で渡す必要があります。

それでは、実行して試してください。

マウスをクリックする度に音が鳴るようになればOKです。


バグ対応


上に書いたようにブロックを消す時に効果音を出したいのですが、ブロックの無い部分でクリックしてもたまに音が鳴ります。

このバグの原因を考え対処していきます。

文字で伝えるのは難しいですが、状況を書きます。

「DeleteBlock関数」を再度表示します。

//ブロックを消す
void Samegame::DeleteBlock(Engine *pEngine)
{
    if (m_selectBlockNum <= 1) {
        return;
    }

    DeleteSelectBlock();

    FallBlock();

    SlideLine();

    m_score += (m_selectBlockNum - 2) * (m_selectBlockNum - 2);

    pEngine->PlaySE(SE_CLICK);
}

この関数はマウスの左ボタンを押した時に呼び出されます。

場所のチェックはしていませんので、どこでボタンを押しても呼び出されるのです。

ここでやっているのは、現在2個以上のブロックが選択されていた場合、そのブロックを消すと言う事です。

2個以上選択されているかどうかは「m_selectBlockNum」を調べて判定しています。

この変数は「SelectBlock関数」で毎回更新されていますが、空いているブロックの上では更新されません。

例えば、3個つながっているブロックの上にマウスカーソルを合わせると「m_selectBlockNum」は3になります。

その後、空いているブロックの上にカーソルを移動させても「m_selectBlockNum」は更新されないので3のままです。

そのまま左ボタンを押すと、(実際にブロックが消される事はありませんが)「DeleteBlock関数」が呼び出され、効果音が再生されます。

結局「m_selectBlockNum」が更新されていない事が原因で発生しているバグです。

ちゃんと「DeleteBlock関数」でも座標を取得し、隣接したブロックの数を更新出来るようにする必要があります。


「Samegame.h」を開き、「DeleteBlock関数」の引数を追加します。

    //ブロックの選択
    void SelectBlock(POINT &refPoint);

    //ブロックを消す
    void DeleteBlock(Engine *pEngine, POINT &refPoint);

    //手詰まりチェック
    bool IsStalemate();

「Samegame.cpp」を開き、「DeleteBlock関数」に次のコードを追加しましょう。

//ブロックを消す
void Samegame::DeleteBlock(Engine *pEngine, POINT &refPoint)
{
    if (IsOutsideField(refPoint)) {
        return;
    }

    int x = (refPoint.x - BLOCK_DEST_X) / BLOCK_WIDTH;
    int y = (refPoint.y - BLOCK_DEST_Y) / BLOCK_HEIGHT;

    if (m_field[y][x].m_color == NO_BLOCK) {
        return;
    }

    ClearSelectFlag();

    CheckAround(x, y, m_field[y][x].m_color);

    m_selectBlockNum = GetSelectBlockNum();

    if (m_selectBlockNum <= 1) {
        return;
    }

    DeleteSelectBlock();

    FallBlock();

    SlideLine();

    m_score += (m_selectBlockNum - 2) * (m_selectBlockNum - 2);

    pEngine->PlaySE(SE_CLICK);

「SelectBlock関数」と同じように、現在のカーソル位置を元に処理出来るように変更しました。


「SceneGame.cpp」を開き、「Update関数」の「DeleteBlock関数」に引数を追加します。

    if (m_pEngine->GetMouseButtonSync(DIK_LBUTTON)) {

        if (!m_bStalemate) {

            m_samegame.DeleteBlock(m_pEngine, point);

        }
        else {

            m_nowSceneData.Set(Common::SCENE_EXIT, false, NULL);
        }
    }

これで実行して確認してください。


効果音の停止


効果音の停止は「StopSE関数」で行います。

「PlaySE関数」同様、どの効果音を停止するか、引数で渡す必要があります。

「SceneGame.cpp」の「Exit関数」で呼び出してみましょう。

//=============================================================================
// シーンの終了時に呼び出される終了処理関数
//=============================================================================
void SceneGame::Exit()
{
    m_pEngine->StopSE(SE_CLICK);

    m_pEngine->StopBGM();

    m_pEngine->ReleaseBGM();
}

もう1つ、全ての効果音を停止させる「StopAllSE関数」も用意しています。

こちらは引数は不要です。

シーンの切り替え時に効果音を全て停止する際は、この関数の方が向いています。

「Exit関数」を書き換えてみます。

//=============================================================================
// シーンの終了時に呼び出される終了処理関数
//=============================================================================
void SceneGame::Exit()
{
    m_pEngine->StopAllSE();

    m_pEngine->StopBGM();

    m_pEngine->ReleaseBGM();
}

効果音の解放


効果音の解放は「ReleaseSE関数」を使います。

システムには複数の効果音が追加出来ますが、不要な効果音はメモリから削除した方が良いと思います。

「Exit関数」にコードを追加してみます。

//=============================================================================
// シーンの終了時に呼び出される終了処理関数
//=============================================================================
void SceneGame::Exit()
{
    m_pEngine->StopAllSE();

    m_pEngine->ReleaseSE(SE_CLICK);

    m_pEngine->StopBGM();

    m_pEngine->ReleaseBGM();
}

これで「さめがめ」も終了です。

今回は「音」についても触れましたので、タイトルやエンディングなどもBGMを追加したり出来そうです。

いつも通り、シーンの追加は皆さんでチャレンジしてください。


次へ

戻る

目次へ