サイトのトップへ戻る

AndEngineドキュメント 日本語訳

ステージSceneを再スタートする方法:

最近では、多くの人が、scene をクリアするレベルで再スタートする方法を求めています。 これは全てのゲームで本当に重要なことなので、この件について説明することにしました。

やり方はたくさんありますが、どれ使うかはあなたのゲームコンセプトや、複雑さや、その他いくつかの要因によって変わります。 次の言葉を常に念頭に置いてください: "必要ない作業はするな" I



1. 一つ目のやり方。例:

以下のゲームレベルの例を考えて見ましょう:
Picture
画面上には何が見えますか?
  • 何らかの背景 (この場合は、ただの青い背景)
  • プレイヤーのsprite
  • いくつかの地面のタイル
  • スコアtext
  • プレイヤーが集めることができる三つのコイン
  • 完了を示す星
そして、3種類の dynamic entityがあると結論付けることができます (dynamicと言うのは、それらの状態を変更できるという意味です)
  • プレイヤーのspriteは自分の位置を変更できます (移動できます)
  • コインの sprites は取得されることができます (つまり、コインは取得された後に非表示になります)
  • スコアtext はその値を変更できます
この例において再スタートするには、単に以下のことをするだけです。:
  1. プレイヤーをその初期の位置 (x/y)に戻す
  2. コインの可視性をtrueに戻す (コインが"収集されて"、非表示設定になっている場合)
  3. スコアtextの値をその初期値に設定する(Score: 0)
ゲーム開発で使用しているオブジェクト生成方法にも依りますが、今回の例では、例えばIMyGameObjectという名前の新しいインタフェースを作成するのも有用です。
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();
	}
}

簡単なゲームの場合はこれが良い方法です。 



2. 二つ目のやり方。例:

それでは、ほとんどの開発者が使用している、単純に最初からscene を再現する方法を紹介します。 あなたのアプリがとても大きい場合、例えば大量の物理オブジェクトを使用しており、一つ目のやり方を使うと問題がある場合に便利です。 実際、これが最もシンプルな方法です:
yourScene = null; // set your scene to null
yourScene = new YourScene(); // initialize scene again, recreate
engine.setScene(yourScene); // set scene

あなたのゲームの複雑さにも依りますが、sceneを初期化している間に読み込み画面を表示すると良いかもしれません。 このやり方を改善してメモリリークの可能性を減らすために、物理オブジェクトを破棄してentityを手動で破棄することもできます。



1. 全ての物理オブジェクトを破棄する:
使用している Physics Worldから、全ての物理bodyとjointsへの参照を取得することができます。以下にて、Physics Worldをクリーンアップして全てのbodies/jointsを破棄する例を示します。
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);
		}
	}
}


2. 全てのscene エンティティを破棄する:
参照が必要なので、新たにListを作成して全てのエンティティを保存し(単に、List内に新規に作成したエンティティを追加するだけです)、後で繰り返し処理で各エンティティを破棄できるようにするのが良いでしょう。
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