106.さまざまなオブジェクト

このサンプルはFullTutorial006というディレクトリに含まれます。
 BaseCrossDx11.slnというソリューションを開くとDx11版が起動します。
 リビルドして実行すると以下の画面が出てきます。

 

図0106a

 


解説

 ここにはいろんなタイプのオブジェクトが配置されています。
 また、オーディオも追加されています。

オーディオ

 オーディオはまずリソース登録をします。以下はScene::CreateResourses()の抜粋ですが
    void Scene::CreateResourses() {
        wstring DataDir;
        //サンプルのためアセットディレクトリを取得
        App::GetApp()->GetAssetsDirectory(DataDir);

        //中略
        //以下オーディオ
        //サウンド
        wstring CursorWav = DataDir + L"cursor.wav";
        App::GetApp()->RegisterWav(L"cursor", CursorWav);
        //BGM
        wstring strMusic = DataDir + L"nanika .wav";
        App::GetApp()->RegisterWav(L"Nanika", strMusic);
    }
 また、宣言部にshared_ptr<SoundItem> m_BGM;を宣言しておきます。
 そして、Scene::OnCreate()関数で以下のように記述します。
void Scene::OnCreate(){
    try {
        //リソース作成
        CreateResourses();

        //BGMの再生
        auto XAPtr = App::GetApp()->GetXAudio2Manager();
        m_BGM = XAPtr->Start(L"Nanika", XAUDIO2_LOOP_INFINITE, 0.1f);

        //自分自身にイベントを送る
        //これにより各ステージやオブジェクトがCreate時にシーンにアクセスできる
        PostEvent(0.0f, GetThis<ObjectInterface>(), GetThis<Scene>(), L"ToGameStage");
    }
    catch (...) {
        throw;
    }
}
 これで、ゲーム中ミュージックが繰り返し再生されます。
 また、ゲームが終わったときに、ミュージックを終了します。このサンプルはステージが1つしかないので、ステージの終了イコールゲームの終了なので、実際には以下は記述しなくても大丈夫ですが、ステージごとにBGMが違う場合などは、以下のような処理が必要です。
    void Scene::OnDestroy() {
        //親クラスのOnDestroyを呼ぶ
        SceneBase::OnDestroy();

        auto XAPtr = App::GetApp()->GetXAudio2Manager();
        XAPtr->Stop(m_BGM);

    }
 OnDestroy()関数は、前もってOnCreate()などと同じように宣言しておく必要があります。
 この場合は、Scene::OnDestroy()に記述していますが、ステージごとにBGMを変える場合などはGameStage::OnDestroy()を多重定義して記述します。

プレーヤー

 続いてプレイヤーですが、ジャンプのタイミングで
void PlayerJumpState::Enter(const shared_ptr<Player>& Obj) {
    auto PtrGrav = Obj->GetBehavior<Gravity>();
    PtrGrav->StartJump(Vec3(0, 4.0f, 0));
    auto XAPtr = App::GetApp()->GetXAudio2Manager();
    XAPtr->Start(L"cursor",0,0.5f);
}
 のように記述します。
 エフェクトは、何かに衝突した瞬間になります。エフェクトはゲームオブジェクトなので、まずエフェクトクラスを記述します。Character.h/cppへの記述です。まず宣言は、
class MultiSpark : public MultiParticle {
public:
    //構築と破棄
    MultiSpark(shared_ptr<Stage>& StagePtr);
    virtual ~MultiSpark();
    //初期化
    virtual void OnCreate() override;
    void InsertSpark(const Vec3& Pos);
};
 のようになります。実体は、MultiSpark::InsertSpark()関数ですが、以下のように記述します。
void MultiSpark::InsertSpark(const Vec3& Pos) {
    auto ParticlePtr = InsertParticle(4);
    ParticlePtr->SetEmitterPos(Pos);
    ParticlePtr->SetTextureResource(L"SPARK_TX");
    ParticlePtr->SetMaxTime(0.5f);
    vector<ParticleSprite>& pSpriteVec = ParticlePtr->GetParticleSpriteVec();
    for (auto& rParticleSprite : ParticlePtr->GetParticleSpriteVec()) {
        rParticleSprite.m_LocalPos.x = Util::RandZeroToOne() * 0.1f - 0.05f;
        rParticleSprite.m_LocalPos.y = Util::RandZeroToOne() * 0.1f;
        rParticleSprite.m_LocalPos.z = Util::RandZeroToOne() * 0.1f - 0.05f;
        //各パーティクルの移動速度を指定
        rParticleSprite.m_Velocity = Vec3(
            rParticleSprite.m_LocalPos.x * 5.0f,
            rParticleSprite.m_LocalPos.y * 5.0f,
            rParticleSprite.m_LocalPos.z * 5.0f
        );
        //色の指定
        rParticleSprite.m_Color = Col4(1.0f, 1.0f, 1.0f, 1.0f);
    }
}
 このようにしておいて、ステージでの構築時に、
void GameStage::CreateSpark() {
    auto MultiSparkPtr = AddGameObject<MultiSpark>();
    //共有オブジェクトにスパークを登録
    SetSharedGameObject(L"MultiSpark", MultiSparkPtr);
}
 とするとプレイヤーからアクセスできるようになるので、プレイヤーの何かに衝突したタイミングで、
void Player::OnCollision(vector<shared_ptr<GameObject>>& OtherVec) {
    //最初に衝突するオブジェクトがあったとき
    //スパークの放出
    auto PtrSpark = GetStage()->GetSharedGameObject<MultiSpark>(L"MultiSpark", false);
    if (PtrSpark) {
        PtrSpark->InsertSpark(GetComponent<Transform>()->GetPosition());
    }
    //中略
}
 と記述すればスパークエフェクトが出ます。

SeekObjectクラス

 SeekObjectは前項とほぼ同じですが、球体の衝突判定にすることとファイアのエフェクトを出すが修正点です。エフェクトの送出はプレイヤーを参考にしてください。
 球体の衝突判定は、SeekObject::OnCreate()関数で以下のように記述します。
void SeekObject::OnCreate() {

    //中略

    //Sphereの衝突判定をつける
    auto PtrColl = AddComponent<CollisionSphere>();
    PtrColl->SetIsHitAction(IsHitAction::AutoOnParentSlide);
    PtrColl->SetCalcScaling(CalcScaling::YScale);
    PtrColl->SetDrawActive(true);

    //中略
}
 ここで、PtrColl->SetCalcScaling(CalcScaling::YScale);となっているのは球体の直径をYスケール基準でという設定です。このようにするとSeekObjectでこぼこ床に衝突するようになります。
 またこの項のSeekObjectは前項と違い行動クラスは実装していません。記述方法の違いを確認しましょう。

そのほかのオブジェクト

 このサンプルには、たくさんのタイプのオブジェクトが実装されています。Character.h/cppに記述されていますが、個別には説明しませんのでコードを参考にしてください。