最近では、多くの人が、scene をクリアするレベルで再スタートする方法を求めています。 これは全てのゲームで本当に重要なことなので、この件について説明することにしました。
やり方はたくさんありますが、どれ使うかはあなたのゲームコンセプトや、複雑さや、その他いくつかの要因によって変わります。 次の言葉を常に念頭に置いてください: "必要ない作業はするな" I
public interface IMyGameObject { public void onRestart(); }そして、例えばPlayer クラスがある場合は、上記のインタフェースを実装します。例えば:
public class Player implements IMyGameObject { @Override public void onRestart() { setPosition(defaultX, defaultY); } }インタフェースを実装すると、未実装のonRestart メソッドを追加しなければならなくなります。 そして、onRestart メソッド内に再スタート時に実行したい処理にオブジェクトを付けて記述します (このサンプル例では、プレイヤーの位置を初期位置に戻す設定をしています)。 これでゲームのSceneを作成する際に、全てのdynamic オブジェクトを保存するためのListを新規作成できます。 そしてこれらのオブジェクトを作成する際に、それらをList内に配置します。例えば:
import java.util.ArrayList; import java.util.List; import org.andengine.entity.scene.Scene; public class MyGameScene extends Scene { private List<IMyGameObject> myEntities; private void initiScene() { // create new list to store our dynamic entities myEntities = new ArrayList<IMyGameObject>(); // create your game scene now, example create your player object Player player = new Player(); attachChild(player); // since our player is dynamic, and implements IMyGameObject, add it to the list myEntities.add(player); } }これで後はrestart メソッドを作成し、List内の各オブジェクトごとに onRestart()メソッドの呼び出しを繰り返すだけです。
/** * Itterate through our dynamic entities from the list * calling onRestart() for each entry. */ private void restart() { final int myEntitiesSize = myEntities.size(); for (int i=0; i<=myEntitiesSize; i++) { myEntities.get(i).onRestart(); } }
簡単なゲームの場合はこれが良い方法です。
yourScene = null; // set your scene to null yourScene = new YourScene(); // initialize scene again, recreate engine.setScene(yourScene); // set scene
あなたのゲームの複雑さにも依りますが、sceneを初期化している間に読み込み画面を表示すると良いかもしれません。 このやり方を改善してメモリリークの可能性を減らすために、物理オブジェクトを破棄してentityを手動で破棄することもできます。
protected void clearPhysicsWorld(PhysicsWorld physicsWorld) { Iterator<Joint> allMyJoints = physicsWorld.getJoints(); while (allMyJoints.hasNext()) { try { final Joint myCurrentJoint = allMyJoints.next(); physicsWorld.destroyJoint(myCurrentJoint); } catch (Exception localException) { Debug.d("SPK - THE JOINT DOES NOT WANT TO DIE: " + localException); } } Iterator<Body> localIterator = physicsWorld.getBodies(); while (true) { if (!localIterator.hasNext()) { physicsWorld.clearForces(); physicsWorld.clearPhysicsConnectors(); physicsWorld.reset(); physicsWorld.dispose(); physicsWorld = null; return; } try { physicsWorld.destroyBody(localIterator.next()); } catch (Exception localException) { Debug.d("SPK - THE BODY DOES NOT WANT TO DIE: " + localException); } } }
public void cleanEntities() { for (IEntity entity: yourEntitiesList) { entity.clearEntityModifiers(); entity.clearUpdateHandlers(); entity.detachSelf(); if (!entity.isDisposed()) { entity.dispose(); } } yourEntitiesList.clear(); yourEntitiesList = null; }そしてこれで、これらのメソッドの実行を司るメソッドを作成できます。アップデート時のエラーを回避するために、このメソッドはupdate スレッド上で実行することが重要です。
public void clearScene() { engine.runOnUpdateThread(new Runnable() { @Override public void run() { onCleanScene(); cleanEntities(); clearTouchAreas(); clearUpdateHandlers(); System.gc(); } }); }sceneを再スタートするには、以下を使用します:
yourScene.clearScene() // execute our cleanup method yourScene = null; // set scene to null yourScene = new YourScene() // initialize scene again, recreate engine.setScene(yourScene) // set scene