libgdx
アシュリーエンティティシステム
サーチ…
備考
Ashley Entity Systemは、 LibGDX組織のもとで管理され、ゲーム開発に適したEntity Systemライブラリです。これはLibGDXユーティリティクラスに依存しますが、LibGDXに基づいていない他のJavaゲームフレームワークでも使用できます。
エンティティシステムは、オブジェクトクラスを継承で豊かにすることなく、大きなオブジェクトセットに向けてデータと機能を管理する別の方法を提供します。
Ashleyを利用することは、Unityのようなオブジェクトモデリングアプローチを探している人にとっては有用なアプローチかもしれませんが、ゲームエンジンではなくフレームワークの範囲に含まれています。
コンポーネントの作成
コンポーネントは、単にAshleyコンポーネントクラスを実装するインスタンスです。
import com.badlogic.ashley.core.Component;
import com.badlogic.ashley.core.ComponentMapper;
public class Position implements Component {
public static final ComponentMapper<Position> Map =
ComponentMapper.getFor(Position.class);
public float x = 0f,
y = 0f;
}
コンポーネントマップは、エンティティ上のコンポーネントに素早くアクセスする方法を提供します。コンポーネントマップを管理する2つの一般的な方法は、コンポーネントのクラス内に静的インスタンスを保持するか、すべてのコンポーネントのすべてのマッパーを含むクラス/ enumを持つことです。
アプリケーションでコンポーネントタイプのマッパーを複数回宣言する必要はありません。
エンティティシステムの作成
エンティティシステムは、エンティティのセットに対して機能的な操作を実行する方法です。コンポーネントは、エンティティシステムの仕事のように、通常、データまたは他のコンポーネントインスタンスの状態を認識することに関連するロジックをそれに関連付けるべきではありません。エンティティシステムは、一度に複数のエンジンに登録することはできません。
エンティティシステムは、複数のタイプの機能を実行すべきではありません。 MovementSystemは、レンダリングを処理する必要がありますが、MovementSystemは位置決めなどしか処理しません。
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.EntitySystem;
import com.badlogic.ashley.core.Family;
public class MovementSystem extends EntitySystem {
//the type of components necessary for entities to have to be operated on
private static final Family FAMILY = Family.all(Position.class).get();
public MovementSystem () {
super();
}
/**
* The update method called every tick.
* @param deltaTime The time passed since last frame in seconds.
*/
public void update (float deltaTime) {
for (Entity e : this.getEngine().getEntitiesFor(FAMILY)) {
Position pos = Position.Map.get(e);
// do entity movement logic on component
...
}
}
エンティティシステムにEntityListenersのような追加機能を追加すると、エンジンのすべてのエンティティを繰り返し処理するのではなく、操作対象のエンティティの種類のみを追跡することができます。 EntityListenersは、システムが登録されているのと同じエンジンにエンティティが追加されるたびにトリガされます。
import com.badlogic.ashley.core.EntityListener;
import com.badlogic.gdx.utils.Array;
public class MovementSystem extends EntitySystem implements EntityListener {
Array<Entity> moveables = new Array<>();
...
@Override
public void entityAdded(Entity entity) {
if (FAMILY.matches(entity)) {
moveables.add(entity);
}
}
@Override
public void entityRemoved(Entity entity) {
if (FAMILY.matches(entity)) {
moveables.removeValue(entity, true);
}
}
public void update (float deltaTime) {
for (Entity e : this.moveables) {
Position pos = Position.Map.get(e);
// do entity movement logic on component
...
}
}
}
関連するコンポーネントを削除したり、必要に応じてエンジン全体からコンポーネントを削除することなく、そのシステムの処理から特定のエンティティを削除することができるため、システムが常に処理するエンティティのサブセットを追跡することも最適です。
ソートされたエンティティシステムの作成
comparator
によって指定された順序で特定のファミリの各エンティティを処理し、EntitySystem
が更新されるたびに各エンティティに対してprocessEntity()
を呼び出す単純なEntitySystem
。これは、レンダリングシステムがソートされた方法でエンティティのリストを反復する傾向があるので、実際には便利なクラスです。エンティティを追加すると、エンティティリストが再ソートされます。ソート基準を変更した場合は、forceSort()
呼び出します。詳細はSortedIteratingSystemを参照してください。
以下のコード例では、スプライトをzindexで並べ替えてレンダリングするのに最適です。
public class SpriteComponent implements Component {
public TextureRegion region;
public int z = 0;
}
public class Mapper {
public static ComponentMapper<SpriteComponent> sprite = ComponentMapper.getFor(SpriteComponent.class);
}
public class RenderingSystem extends SortedIteratingSystem {
public RenderingSystem () {
super(Familly.all(SpriteComponent.class).get(), new ZComparator())
}
public void processEntity(Entity entity, float deltaTime) {
if(checkZIndexHasChangeValue()) {
forceSort();
}
}
private static class ZComparator implements Comparator<Entity> {
@Override
public int compare(Entity entityA, Entity entityB) {
return (int)Math.signum(Mapper.sprite.get(entityA).z - Mapper.sprite.get(entityB).z);
}
}
}
インターバル反復システムの作成
フレームごとに1回ではなく、一定間隔後にエンティティファミリを処理する単純な
EntitySystem
。エンティティ処理ロジックは、processEntity(Entity)
配置する必要があります。詳細は、 IntervalIteratingSystemを参照してください。
以下のコード例では、このための最良の使い方は物理学の世界のステップです。
public class Constants {
public final static float TIME_STEP = 1 / 60.0f; // 60 fps
public final static int VELOCITY_ITERATIONS = 6;
public final static int POSITION_ITERATIONS = 2;
}
public class PhysicsSystem extends IntervalIteratingSystem {
public PhysicsSystem () {
super(Family.all(PhysicsComponent.class), Constants.TIME_STEP);
}
@Override
protected void processEntity(Entity entity) {
// process the physics component here with an interval of 60fps
}
@Override
protected void updateInterval() {
WorldManager.world.step(Constants.TIME_STEP, Constants.VELOCITY_ITERATIONS, Constants.POSITION_ITERATIONS);
super.updateInterval();
}
}