私はCocos2d-xを使ってコツコツとアプリ実装を続けています。

今回、「大量のSEファイルをループでプリロードする」処理を実装しましたが、 処理が完了するまで全く動かなくなる状態 になってしまいました。
他のアプリではロード中にバリバリアニメーションするものが多いですが、いったいどうやって実装しているのでしょうか。

ブロッキングを回避するまで結構時間を使ってしまいました。
私のとった対応についてログを公開いたします。

※こちらのアプリのローディング画面で実装したものです。

やりたいこと

ロード用の画面を実装し、ローディングの進捗を表示する。

うまくいかなかったコード

void LoadingScene::preloadSe()
{
    vector<std::string> files = {"se/scound1.ogg","se/scound2.ogg",,, };
    for (int i=0; i<files.size(); i++) {
        updateProgress();
        SimpleAudioEngine::getInstance()->preloadEffect( files[i].c_str() );
    }
}

SEファイルをループで連続してプリロードする実装です。
プリロードの直前でupdateProgress()を呼び出していますが、なぜか プリロードがすべて完了するまで全く動かない のです。。。

うまくいったコード

scheduleOnceを使ってもうまくいかず、最終的には次のようにDelayを入れて解決しました。

// loading_scene.h
class LoadingScene : public cocos2d::CCLayer
{
private:
    void preloadSe();
    void preloadOne();
    void callNext();
    void toNextScene();
    std::vector<std::string> m_files;
    int m_total;
    int m_index;
    :
// loading_scehe.cpp
void LoadingScene::preloadSe()
{
    m_files = {"se/scound1.ogg","se/scound2.ogg",,, };
    m_total = m_files.size();
    m_index = 0;

    LoadingScene::preloadOne();
}

void LoadingScene::preloadOne()
{
    updateProgress();
    this->runAction(
        Sequence::create(
            DelayTime::create(0.0005),
            CallFunc::create([this]() {
                SimpleAudioEngine::getInstance()->preloadEffect( files[i].c_str() );
                callNext();
            }),
            NULL
        )
    );
}

void LoadingScene::callNext()
{
    m_index++;
    if (m_index >= m_total) {
        this->scheduleOnce(schedule_selector(LoadingScene::toNextScene), 0.5);
        return;
    }
    LoadingScene::preloadOne();
}

部分的に抜粋したコードのため、誤りがありましたらご指摘ください。

おわりに

他社さんで当たり前に実装されているコードでも、いざ自分が実装するとなると躓くことが多いものです。
こうやって一歩ずつ、できることを増やしていくことが、私は楽しいですね。

この記事はtomita@atuwebがお届けしました。

参考

Delayを入れる方法については、以下を参考にいたしました。
ありがとうございました。

cocos2d-x 3.0で一定時間後にラムダ式を実行する
http://qiita.com/keroxp/items/ba15b1ab485b1b11eceb


2016年04月04日:アプリリンクを追加