画像や効果音を読みっぱなしにするとメモリを消費して古い機種などではアプリケーションが落ちてしまいます。そこでこまめにキャッシュを削除して消費メモリを抑える努力をしています。
くまのがっこう神経衰弱バトルはiPod 4 (iOS 6.1)メモリ256Mもサポートしているのでメモリはおよそ80Mを下回るようにしています。80Mを超えたあたりからmemory warningが出はじめます。iPhone 5以上ならそのようなことはありませんのでサポートする機種に合わせて目標値を決めれば良いとおもいます。
くまのがっこう神経衰弱バトルでは画像と効果音を大きく3つに分けて管理しています。
- 各シーン毎の画像/効果音
- ゲーム共通の画像/効果音
- アプリケーション共通の画像/効果音
1.各シーン毎の画像/効果音は、シーンの開始時にキャッシュに読み込んで、そのシーンが終了するときにキャッシュを破棄します。主にシーン専用の背景画像やキャラクター、BGMなどです。
2.ゲーム共通の画像/効果音は、12ステージあるゲームの開始時にキャッシュに読み込んで全ステージを終了したときにキャッシュを破棄します。主にゲームのスコア表示やフレーム、ゲームエフェクトなど全ステージで共通の画像です。
3.のアプリケーション共通の画像/効果音は、アプリケーションを起動したときにキャッシュに読み込んで、アプリケーションが終了するまでキャッシュを破棄しません。主に全体で使用するボタン類、メッセージなどです。
シーン毎の画像/効果音のキャッシュへの読み込みと削除はコンストラクタとデストラクタで行っています。
HelloWorldScene.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" #include "SimpleAudioEngine.h" USING_NS_CC; using namespace CocosDenshion; class HelloWorld : public cocos2d::Layer { private: public: static cocos2d::Scene* createScene(); virtual bool init(); CREATE_FUNC(HelloWorld); HelloWorld() { // 画像のキャッシュを生成(スプライトシートからの読込み) SpriteFrameCache::getInstance()->addSpriteFramesWithFile("HelloWorld.plist"); // 効果音のキャッシュを生成 SimpleAudioEngine::getInstance()->preloadEffect("hello.mp3"); } ~HelloWorld() { // テクスチャを削除して画像のキャッシュを破棄 Director::getInstance()->getTextureCache()->removeAllTextures(); SpriteFrameCache::getInstance()->removeSpriteFramesFromFile("HelloWorld.plist"); // 効果音のキャッシュを削除 SimpleAudioEngine::getInstance()->unloadEffect("hello.mp3"); } }; #endif // __HELLOWORLD_SCENE_H__ |
HelloWorldScene.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#include "HelloWorldScene.h" USING_NS_CC; Scene* HelloWorld::createScene() { auto scene = Scene::create(); auto layer = HelloWorld::create(); scene->addChild(layer); return scene; } bool HelloWorld::init() { if ( !Layer::init() ) { return false; } // 画像を表示 auto image = Sprite::createWithSpriteFrameName("HelloWorld.png"); this->addChild(image); // 効果音を再生 SimpleAudioEngine::getInstance()->playEffect("hello.mp3"); return true; } |
この場合にシーンを切り替えた次のシーンでも同じHelloWorld.plistを使用していると現在のシーンのデストラクタにキャッシュが削除されてしまいエラーになりますので注意してください。
またシーンの切り替え中は現在のシーンと次のシーンのキャッシュ両方を同時に持つ事になるのでメモリの使用量は2重になりますので注意してください。
キャッシュの設計を終えたら実際に動かしてXcodeのデバッグナビゲータを使ってメモリの使用量を測定して何処で何がメモリを喰っているか分析します。
メモリを多く消費するところがある場合には画像の読み込みと破棄のタイミングを個別に調整してメモリの消費を抑えています。
古い機種を切り捨てればここまで神経を使わなくてもいいのかな…