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

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

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

やりたいこと

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

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

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

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

うまくいったコード

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

 1// loading_scene.h
 2class LoadingScene : public cocos2d::CCLayer
 3{
 4private:
 5    void preloadSe();
 6    void preloadOne();
 7    void callNext();
 8    void toNextScene();
 9    std::vector<std::string> m_files;
10    int m_total;
11    int m_index;
12    :
13
 1// loading_scehe.cpp
 2void LoadingScene::preloadSe()
 3{
 4    m_files = {"se/scound1.ogg","se/scound2.ogg",,, };
 5    m_total = m_files.size();
 6    m_index = 0;
 7
 8    LoadingScene::preloadOne();
 9}
10
11void LoadingScene::preloadOne()
12{
13    updateProgress();
14    this->runAction(
15        Sequence::create(
16            DelayTime::create(0.0005),
17            CallFunc::create([this]() {
18                SimpleAudioEngine::getInstance()->preloadEffect( files[i].c_str() );
19                callNext();
20            }),
21            NULL
22        )
23    );
24}
25
26void LoadingScene::callNext()
27{
28    m_index++;
29    if (m_index >= m_total) {
30        this->scheduleOnce(schedule_selector(LoadingScene::toNextScene), 0.5);
31        return;
32    }
33    LoadingScene::preloadOne();
34}
35

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

おわりに

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

参考

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

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