From f44f34b3de896e5daea9141dfd76d1dad79ff743 Mon Sep 17 00:00:00 2001 From: Matt Low Date: Sat, 25 Jan 2020 15:17:50 +0400 Subject: [PATCH] Add ComponentMapper for faster retrieval of entity components --- .../com/me/asteroids/screens/GameScreen.java | 8 +++---- .../asteroids/systems/ModelRenderSystem.java | 11 ++++++--- .../me/asteroids/systems/MovementSystem.java | 24 ++++++++++++++----- .../asteroids/systems/PlayerInputSystem.java | 18 ++++++++++---- .../asteroids/systems/ScreenWrapSystem.java | 15 ++++++++---- .../com/me/common/ecs/ComponentMapper.java | 19 +++++++++++++++ core/src/com/me/common/ecs/Engine.java | 20 ++++++++++++++++ core/src/com/me/common/ecs/EntitySystem.java | 8 ++++--- 8 files changed, 99 insertions(+), 24 deletions(-) create mode 100644 core/src/com/me/common/ecs/ComponentMapper.java diff --git a/core/src/com/me/asteroids/screens/GameScreen.java b/core/src/com/me/asteroids/screens/GameScreen.java index 41aedd8..c3de16d 100644 --- a/core/src/com/me/asteroids/screens/GameScreen.java +++ b/core/src/com/me/asteroids/screens/GameScreen.java @@ -37,10 +37,10 @@ public class GameScreen extends Screen { engine.registerComponentClass(AccelerationComponent.class); engine.registerComponentClass(ModelComponent.class); - engine.registerSystem(new PlayerInputSystem()); - engine.registerSystem(new MovementSystem()); - engine.registerSystem(new ScreenWrapSystem()); - engine.registerSystem(new ModelRenderSystem(graphics)); + engine.registerSystem(new PlayerInputSystem(engine)); + engine.registerSystem(new MovementSystem(engine)); + engine.registerSystem(new ScreenWrapSystem(engine)); + engine.registerSystem(new ModelRenderSystem(engine, graphics)); engine.ready(); diff --git a/core/src/com/me/asteroids/systems/ModelRenderSystem.java b/core/src/com/me/asteroids/systems/ModelRenderSystem.java index a38de76..95c3597 100644 --- a/core/src/com/me/asteroids/systems/ModelRenderSystem.java +++ b/core/src/com/me/asteroids/systems/ModelRenderSystem.java @@ -5,15 +5,20 @@ import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.math.Polygon; import com.me.asteroids.Graphics; import com.me.asteroids.components.ModelComponent; +import com.me.common.ecs.ComponentMapper; +import com.me.common.ecs.Engine; import com.me.common.ecs.Entity; import com.me.common.ecs.EntitySystem; public class ModelRenderSystem extends EntitySystem { + private ComponentMapper modelMapper; + private ShapeRenderer renderer; - public ModelRenderSystem(Graphics graphics) { - super(ModelComponent.class); + public ModelRenderSystem(Engine engine, Graphics graphics) { + super(engine, ModelComponent.class); + this.modelMapper = engine.getComponentMapper(ModelComponent.class); this.renderer = graphics.getShapeRenderer(); } @@ -25,7 +30,7 @@ public class ModelRenderSystem extends EntitySystem { @Override public void processEntity(Entity entity, float dt) { - ModelComponent modelComponent = entity.getComponent(ModelComponent.class); + ModelComponent modelComponent = modelMapper.get(entity); Polygon model = modelComponent.model; renderer.polygon(model.getTransformedVertices()); diff --git a/core/src/com/me/asteroids/systems/MovementSystem.java b/core/src/com/me/asteroids/systems/MovementSystem.java index 7c344bf..40d7a26 100644 --- a/core/src/com/me/asteroids/systems/MovementSystem.java +++ b/core/src/com/me/asteroids/systems/MovementSystem.java @@ -6,6 +6,8 @@ import com.me.asteroids.components.AccelerationComponent; import com.me.asteroids.components.ModelComponent; import com.me.asteroids.components.PositionComponent; import com.me.asteroids.components.VelocityComponent; +import com.me.common.ecs.ComponentMapper; +import com.me.common.ecs.Engine; import com.me.common.ecs.Entity; import com.me.common.ecs.EntitySystem; @@ -13,20 +15,30 @@ public class MovementSystem extends EntitySystem { private Vector2 tmp = new Vector2(); - public MovementSystem() { - super(PositionComponent.class, VelocityComponent.class); + private ComponentMapper positionMapper; + private ComponentMapper velocityMapper; + private ComponentMapper accelMapper; + private ComponentMapper modelMapper; + + public MovementSystem(Engine engine) { + super(engine, PositionComponent.class, VelocityComponent.class); + + positionMapper = engine.getComponentMapper(PositionComponent.class); + velocityMapper = engine.getComponentMapper(VelocityComponent.class); + accelMapper = engine.getComponentMapper(AccelerationComponent.class); + modelMapper = engine.getComponentMapper(ModelComponent.class); } @Override public void processEntity(Entity entity, float dt) { - PositionComponent positionComponent = entity.getComponent(PositionComponent.class); - VelocityComponent velocityComponent = entity.getComponent(VelocityComponent.class); + PositionComponent positionComponent = positionMapper.get(entity); + VelocityComponent velocityComponent = velocityMapper.get(entity); Vector2 velocity = velocityComponent.velocity; float maxVelocity = velocityComponent.maxVelocity; Vector2 position = positionComponent.position; - AccelerationComponent accelComponent = entity.getComponent(AccelerationComponent.class); + AccelerationComponent accelComponent = accelMapper.get(entity); if (accelComponent != null && !accelComponent.acceleration.isZero()) { velocity.add(tmp.set(accelComponent.acceleration).scl(dt)); } @@ -36,7 +48,7 @@ public class MovementSystem extends EntitySystem { position.add(tmp.set(velocity).scl(dt)); } - ModelComponent modelComponent = entity.getComponent(ModelComponent.class); + ModelComponent modelComponent = modelMapper.get(entity); if (modelComponent != null) { Polygon model = modelComponent.model; model.setPosition(position.x, position.y); diff --git a/core/src/com/me/asteroids/systems/PlayerInputSystem.java b/core/src/com/me/asteroids/systems/PlayerInputSystem.java index bed9c05..39b3daf 100644 --- a/core/src/com/me/asteroids/systems/PlayerInputSystem.java +++ b/core/src/com/me/asteroids/systems/PlayerInputSystem.java @@ -8,6 +8,8 @@ import com.me.asteroids.components.AccelerationComponent; import com.me.asteroids.components.PlayerComponent; import com.me.asteroids.components.PositionComponent; import com.me.asteroids.components.VelocityComponent; +import com.me.common.ecs.ComponentMapper; +import com.me.common.ecs.Engine; import com.me.common.ecs.Entity; import com.me.common.ecs.EntitySystem; @@ -15,20 +17,28 @@ public class PlayerInputSystem extends EntitySystem { public Vector2 tmp = new Vector2(0, 1); - public PlayerInputSystem() { + private ComponentMapper positionMapper; + private ComponentMapper velocityMapper; + private ComponentMapper accelMapper; + + public PlayerInputSystem(Engine engine) { super( + engine, PositionComponent.class, VelocityComponent.class, AccelerationComponent.class, PlayerComponent.class ); + positionMapper = engine.getComponentMapper(PositionComponent.class); + velocityMapper = engine.getComponentMapper(VelocityComponent.class); + accelMapper = engine.getComponentMapper(AccelerationComponent.class); } @Override public void processEntity(Entity entity, float dt) { - PositionComponent positionComponent = entity.getComponent(PositionComponent.class); - VelocityComponent velocityComponent = entity.getComponent(VelocityComponent.class); - AccelerationComponent accelComponent = entity.getComponent(AccelerationComponent.class); + PositionComponent positionComponent = positionMapper.get(entity); + VelocityComponent velocityComponent = velocityMapper.get(entity); + AccelerationComponent accelComponent = accelMapper.get(entity); if (Gdx.input.isKeyPressed(Input.Keys.D)) { positionComponent.rotation = Utils.rotate(positionComponent.rotation, -300 * dt); diff --git a/core/src/com/me/asteroids/systems/ScreenWrapSystem.java b/core/src/com/me/asteroids/systems/ScreenWrapSystem.java index 4c519e5..859999c 100644 --- a/core/src/com/me/asteroids/systems/ScreenWrapSystem.java +++ b/core/src/com/me/asteroids/systems/ScreenWrapSystem.java @@ -5,19 +5,26 @@ import com.badlogic.gdx.math.Vector2; import com.me.asteroids.Constants; import com.me.asteroids.components.ModelComponent; import com.me.asteroids.components.PositionComponent; +import com.me.common.ecs.ComponentMapper; +import com.me.common.ecs.Engine; import com.me.common.ecs.Entity; import com.me.common.ecs.EntitySystem; public class ScreenWrapSystem extends EntitySystem { - public ScreenWrapSystem() { - super(PositionComponent.class, ModelComponent.class); + private ComponentMapper positionMapper; + private ComponentMapper modelMapper; + + public ScreenWrapSystem(Engine engine) { + super(engine, PositionComponent.class, ModelComponent.class); + positionMapper = engine.getComponentMapper(PositionComponent.class); + modelMapper = engine.getComponentMapper(ModelComponent.class); } @Override public void processEntity(Entity entity, float dt) { - PositionComponent positionComponent = entity.getComponent(PositionComponent.class); - ModelComponent modelComponent = entity.getComponent(ModelComponent.class); + PositionComponent positionComponent = positionMapper.get(entity); + ModelComponent modelComponent = modelMapper.get(entity); Vector2 position = positionComponent.position; Rectangle aabb = modelComponent.aabb; diff --git a/core/src/com/me/common/ecs/ComponentMapper.java b/core/src/com/me/common/ecs/ComponentMapper.java new file mode 100644 index 0000000..2baac3d --- /dev/null +++ b/core/src/com/me/common/ecs/ComponentMapper.java @@ -0,0 +1,19 @@ +package com.me.common.ecs; + +public class ComponentMapper { + + private Engine engine; + private ComponentType type; + private Class typeClass; + + public ComponentMapper(Engine engine, Class typeClass) { + this.engine = engine; + this.type = ComponentType.getComponentType(typeClass); + this.typeClass = typeClass; + } + + public T get(Entity entity) { + return typeClass.cast(engine.getEntityComponent(entity, type)); + } + +} diff --git a/core/src/com/me/common/ecs/Engine.java b/core/src/com/me/common/ecs/Engine.java index d24bc4f..921d528 100644 --- a/core/src/com/me/common/ecs/Engine.java +++ b/core/src/com/me/common/ecs/Engine.java @@ -4,6 +4,9 @@ import com.badlogic.gdx.utils.Array; import com.me.common.ecs.event.Event; import com.me.common.ecs.event.Listener; +import java.util.HashMap; +import java.util.Map; + public class Engine { private Array entities; @@ -16,6 +19,8 @@ public class Engine { private ListenerRegistry listenerRegistry; + private Map, ComponentMapper> componentMappers; + public Engine() { this.entities = new Array<>(); this.toActivate = new Array<>(); @@ -24,6 +29,7 @@ public class Engine { this.systems = new Array<>(); this.listenerRegistry = new ListenerRegistry(); + this.componentMappers = new HashMap<>(); } public void registerComponentClass(Class clazz) { @@ -154,4 +160,18 @@ public class Engine { return clazz.cast(components[type.getId()].get(entity.getId())); } + protected Component getEntityComponent(Entity entity, ComponentType type) { + return components[type.getId()].get(entity.getId()); + } + + @SuppressWarnings("unchecked") + public ComponentMapper getComponentMapper(Class typeClass) { + ComponentMapper mapper = componentMappers.get(typeClass); + if (mapper == null) { + mapper = new ComponentMapper<>(this, typeClass); + componentMappers.put(typeClass, mapper); + } + return mapper; + } + } diff --git a/core/src/com/me/common/ecs/EntitySystem.java b/core/src/com/me/common/ecs/EntitySystem.java index 51f8ecc..b70696e 100644 --- a/core/src/com/me/common/ecs/EntitySystem.java +++ b/core/src/com/me/common/ecs/EntitySystem.java @@ -6,11 +6,13 @@ public abstract class EntitySystem { private long typeBits; + protected Engine engine; protected Array entities; - public EntitySystem(Class... components) { - typeBits = ComponentType.getMaskBits(components); - entities = new Array<>(); + public EntitySystem(Engine engine, Class... components) { + this.engine = engine; + this.typeBits = ComponentType.getMaskBits(components); + this.entities = new Array<>(true, 16, Entity.class); } public void preProcessing() {}