cocos2d-xで音声ファイルの名前を自動で取得してpreloadする

cocos2d-xのSimpleAudioEngineやexperimental::AudioEngineで音声ファイルを鳴らすときは、アプリ起動時等にpreloadしてから使う。

experimental::AudioEngine::preload("a.mp3");

音声ファイルがたくさんある場合は、それらのファイル名を全て指定するのが面倒だし、 ファイルを追加、削除、リネームした場合に ファイル名を間違える可能性がある。

音声ファイル名を自動で取得して、preloadするようにしたい。

Resourcesフォルダ内に、soundNames.txtという空のテキストファイルを追加する。 1

Resources/seフォルダ内のmp3ファイル名一覧を取得して、soundNames.txtに書き込む。

Target->Build Phasesを開き、 左上の+ボタンを押してNew Run Script Phaseを追加する。

2

output="${PROJECT_DIR}/../Resources/soundNames.txt"
echo '' > $output

se="${PROJECT_DIR}/../Resources/se"
for file in `find $se -name "*.mp3"`; do
echo ${file##*/} >> $output
done

このRun Script PhaseはCopy Bundle Resourcesの上に移動する。

3

これで、ビルドした時にsoundNames.txtに音声ファイル名が書き込まれる。

4

あとは、アプリ起動時にsoundNames.txtから読み込んだファイル名を指定してpreloadする。

このプロジェクトではRRGSoundManagerというクラスで 音声を扱っているので、全ての音声ファイルをpreloadするメソッドを追加する。

RRGSoundManager.h

#include "cocos2d.h"

#define sharedSoundManager RRGSoundManager::getInstance()

class RRGSoundManager : public cocos2d::Ref
{
private:
    bool _isPlaying;
    std::string _bgm;
    int _audioID;
public:
    RRGSoundManager();
    virtual ~RRGSoundManager();
    static RRGSoundManager* getInstance();
    static void destroyInstance();
    void playBGM(const std::string& bgm);
    void stopBGM();
    void playSE(const std::string& sound);
    void pauseAll();
    void resumeAll();
    //追加
    void preloadAll();
};

RRGSoundManager.cpp

#include "RRGSoundManager.h"
#include "audio/include/AudioEngine.h"

using namespace std;
USING_NS_CC;

/*中略*/

namespace {
    string trim(const string& str, const char* trimCharacterList = "; \t\v\r\n\"\'") {
        string result;
        string::size_type left = str.find_first_not_of(trimCharacterList);
        
        if (left != string::npos) {
            string::size_type right = str.find_last_not_of(trimCharacterList);
            result = str.substr(left, right - left + 1);
        }
        
        return result;
    }
    
    list<string> split(string str, string delim) {
        list<string> result;
        long cutAt;
        
        
        while( (cutAt = str.find_first_of(delim)) != str.npos ) {
            if(cutAt > 0) {
                result.push_back(trim(str.substr(0, cutAt)));
            }
            str = str.substr(cutAt + 1);
        }
        if(str.length() > 0) {
            result.push_back(trim(str));
        }
        
        return result;
    }
}

void RRGSoundManager::preloadAll()
{
    FileUtils* fileUtil = FileUtils::getInstance();
    string fullpath = fileUtil->fullPathForFilename("soundNames.txt");
    string strings = fileUtil->getStringFromFile(fullpath);
    
    if (strings.empty()) return;
    
    list<string> stringLines = split(strings, "\n");
    for(list<string>::iterator begin = stringLines.begin(),
        end = stringLines.end();
        begin != end;
        ++begin)
    {
        CCLOG("soundName = %s",(*begin).c_str());
        experimental::AudioEngine::preload(*begin);
    }
}

preloadAllメソッドを起動時に呼ぶ。

AppDelegate.cpp

bool AppDelegate::applicationDidFinishLaunching() {
	/*中略*/
	sharedSoundManager->preloadAll();
	/*中略*/
	return true;
}
Written on September 19, 2016