cocos2d-xでゲームデータをPlistで管理する

ChainZ(クリエイター)
いろいろやってます。

ゲームデータを保存するには主に二つの方法があります:

  • sqliteを利用してデータを保存
  • ファイルベースでデータを保存(XML, JSONなど)

sqliteのようなデータベースを使うと、データのソートや抽出など、明らかにファイルベースより都合がいいと思いますが、その代わりにデータ抽出の処理を書かなくちゃいけないです。

本当にデータベースなんか必要なのか?

ゲームの種類にはよるけど、本当にデータベースが必要になってくるのは恐らくFootball Managerのような、データ処理がメインで、大量なデータが必要なゲームでしょう。普通のカードゲームなどはファイルベースで十分です。あとバックエンドがあれば、ソートなどはバックエンドに任せてもいいと思います。

cocos2d-xゲームデータの保存

ユーザーデータならUserDefaultを使えばよいでしょう。他のデータはplistとして保存して、ディレクトリーで管理すればといいと思います。

JSONかplistか? cocos2d-xはcocos2dから生まれたフレームワークで、iOSがネイティヴにサポートしているplistがJSONより都合がよかったので、cocos2d-xもそのまま引き継いてplistをメインに使っています。もちろんcocos2d-xはJSONもサポートしています

plistファイルを読み込む

plistを読み込むのが簡単です、cocos2d-xのFileUtilsに便利なメソードがあります:

auto path = FileUtils::getInstance()->getWritablePath();
// ValueMapとして読み込む
ValueMap data = FileUtils::getInstance()->getValueMapFromFile(path + "test.plist");
// 文字列として読み込む
std::string s = FileUtils::getInstance()->getStringFromFile(path + "test.plist");

ValueMapからデータを取得するには、.as<型>というメソードを使います:

ValueMap player = FileUtils::getInstance()->getValueMapFromFile(path + "test.plist");
auto name = player["name"].asString();
auto age = player["age"].asInt();
auto is_active = player["is_active"].asBool();
auto cards = player["cards"].asValueMap();
auto card1 = cards[0].asValueMap();
auto card1_name = card1["name"].asString();

この例ではやってないですが、値を取り出す前に、.isNull()で値が存在するかどうかを確認することが必要です。

ValueMapをplistファイルに書き込む

cocos2d-xでplistファイルを作成するのも簡単です:

auto path = FileUtils::getInstance()->getWritablePath();
auto file = path + "hello.plist";
ValueMap data;
data["name"] = "cocos";
data["greeting"] = "Hello World";
if (FileUitils::getInstance()->writeToFile(data, file))
{
CCLOG("データを%sに書き出しました。", file.c_str());
}
else
{
CCLOG("Ops!");
}

書き出したファイルの中身は下記になります:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>greeting</key>
<string>Hello World</string>
<key>name</key>
<string>cocos</string>
</dict>
</plist>

plistは単純なxmlなので、ウェブサーバーからxmlをリスポンスして、アプリ側でFileUtils::getValueMapFromData()を使って受け取ればデータの処理も円滑になりますし、一番重要なのは、機能自身がcocos2d-xに入ってるので、ラッパーとか作る手間も必要なく楽です。