cocos2d-xでキャラクターのセリフなどをテキストファイルから読み込んで、1行ずつ処理するにはどうしたらよいのかを検討してみたのでメモ。
cocos2d-x v3.5
先に結論を書くと、
FileUtilsのgetStringFromFile()メソッドでテキストファイルを読み込み、改行文字で分割して処理する
です。
この方法は最初に思いついた方法です。
しかし、C++の標準ライブラリには文字列を分割するAPIがないため、自分で実装するか、外部のライブラリを使用する必要があります。
それはちょっと面倒臭い上に、あまりスマートではない気がしたので、ファイルを1行ずつ読み込んで処理する方法がないかを模索したところ、std::ifstreamを使えばいけるのではと考えました。
コードはこんな感じです。
バージョン
cocos2d-x v3.5
結論
先に結論を書くと、
FileUtilsのgetStringFromFile()メソッドでテキストファイルを読み込み、改行文字で分割して処理する
です。
経緯
この方法は最初に思いついた方法です。
しかし、C++の標準ライブラリには文字列を分割するAPIがないため、自分で実装するか、外部のライブラリを使用する必要があります。
それはちょっと面倒臭い上に、あまりスマートではない気がしたので、ファイルを1行ずつ読み込んで処理する方法がないかを模索したところ、std::ifstreamを使えばいけるのではと考えました。
コードはこんな感じです。
#include <fstream>
USING_NS_CC;
auto filePath = FileUtils::getInstance()->fullPathForFilename("sample.txt");
std::ifstream inFile(filePath);
for (std::string line; std::getline(inFile, line);) {
// ここに処理を記述
log("%s", line.c_str());
}
この例ではResourcesディレクトリ直下に「sample.txt」を配置しているという想定です。
FileUtilsのfullPathForFilename()メソッドでパスの問題を解決し、std::ifstreamでファイルを開きます。
そして、std::getlineで1行ずつ読み込んでいます。
これでちゃんと動作したので、よっしゃ!と思ったのですが、問題が起こりました。
上記のコードは、iOSとWin32では問題なく動くのですが、Androidでは動かなかったのです。
問題は以下の部分です。
std::ifstream inFile(filePath);
Androidではここでファイルを開くことが出来ませんでした。
調べた所、Androidの場合、リソースファイルはapkファイルにzip形式で格納されますが、std::ifstreamはzipに格納されたファイルを読み込むことが出来ない、というのがその理由でした。
というわけで、残念ですがstd::ifstreamを使った方法は断念し、最初の案を採用することにしたのでした。
コード例
文字列を分割する方法は色々あるようですが、こちらの方法が短く書けていいかなと思いました。
これを使って書くと、こんな感じです。
USING_NS_CC;
auto split = [](const std::string& input, char delimiter) {
std::istringstream stream(input);
std::string field;
std::vector result;
while (std::getline(stream, field, delimiter)) {
result.push_back(field);
}
return result;
};
auto fileText = FileUtils::getInstance()->getStringFromFile("sample.txt");
auto lines = split(fileText, '\n');
for (const auto& line : lines) {
// ここに処理を記述
log("%s", line.c_str());
}
にしても、何か他に良い方法はないものだろうか…。
0 件のコメント:
コメントを投稿