23
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Cocos2d-x 3.2 でディレクトリ内のファイル一覧を取得したいお話

Last updated at Posted at 2014-12-21

はじめに

これは Cocos2d-x Advent Calendar 2014 の第21日目の記事です。

予定で「横スクロールゲームについて書きます」と言ったな。 アレは嘘だ
予告.png

すみません、他に書きたいネタが浮かんだのでそちらについて書きます。
Cocos2d-x で Resources のサブディレクトリ内のファイル一覧を取得する方法についてです。
バージョンは 3.2 を対象としています。

Cross Platform にできるか? → できない!

これはかなり必要な機会も多いはずなので、FileUtils あたりに API が準備されているだろうと思ったのですが、どうやらそうではないようです。
Stack Over Flow に、

There is no cross platform API in cocos2dx for listing directory contents. You can store file names in an array while creating them.

と答えている方がいらっしゃいます。
今回は iOS と Android についてやりたかったので、それぞれ別々の方法が必要になりますね...
なんとか両方のプラットフォームで実現できたので、以下に書いていこうと思います。

対象のディレクトリは Cocos2d-x の Resources に含まれていることを前提とします。

iOS ではどうやるの?

iOS のほうが素直に実装できます。
フルパスを取得したら、C言語標準の opendir 関数でディレクトリを開きます。戻り値として受け取ることができる、DIR 構造体から readdir() してディレクトリーの中身を表す構造体 dirent で受け取れば、中身のファイル名が調べられます。

サンプルコードは次のとおりです:


std::vector<std::string> getDirContents(std::string dirname) {
    FileUtils* fu = FileUtils::getInstance();

    std::string dir = fu->fullPathForFilename(dirname);

    std::vector<std::string> list;

    DIR* dp;
    struct dirent* ent;

    if ((dp = opendir(dir.c_str()), "r") == NULL) {
        CCLOGERROR("ディレクトリが開けません。:%s", dir.c_str());
        perror(dir.c_str());
        return list;
    }

    while ((ent = readdir(dp)) != NULL) {
        CCLOG("ファイル:%s", ent->d_name);
        list.push_back(ent->d_name);
    };
    closedir(dp);

    return list;
}

Android ではどうやるの?

Android では fullPathForFilename() メソッドでフルパスがうまく取れませんでした。
そうすると、opendir() 関数も使えません。Android/C++ では Resources 配下は JNI のAssetsManager というもので扱うようです。
AssetsManager のインスタンスの取得にはアプリケーションの Context が必要になるようで、少々厄介です。今回は Cocos2d-x の FileUtils が private 変数として持っているインスタンスを借りてきました。(とりあえず public に書き換えました。)

サンプルコードはつぎのとおりです:


std::vector<std::string> getDirContents(std::string dirname) {

    std::vector<std::string> list;

    AAssetManager* mgr = FileUtilsAndroid::assetmanager;

    AAssetDir* assetDir = AAssetManager_openDir(mgr, dirname.c_str());
    if (!assetDir) {
        CCLOGERROR("ディレクトリが開けません:%s", dirname.c_str());
        return list;
    }

    const char* filename = NULL;
    while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) {
        CCLOG("ファイル:%s", filename);
        list.push_back(filename);
    }
    AAssetDir_close(assetDir);

    return list;
}

おわりに

Cocos2d-x で Resources ディレクトリ内のファイル一覧を取得するお話を iOS, Android について書きました。自分としては必要になる機会も多いと思うので、FileUtilsあたりに実装されたらいいなーと思った次第。

お読みいただきありがとうございました。

23
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?