-
Notifications
You must be signed in to change notification settings - Fork 1
Entities
Lunar uses Ashley as an ECS. All entities within Lunar are prefixed with Lunar
- EntityPropertiesComponent
- Stores data about an entities size, entity ID, name, health, moving speed, etc.
- EntityTextureComponent
- Basic convenience functions for storing
Texture(s)
andTextureRegion(s)
- Only present if an entity implements
LunarTexturedEntity
or extendsAbstractLunarTexturedEntity
- Basic convenience functions for storing
- EntityPositionComponent
- Contains the entities current position, previous position, and, interpolated position.
- EntityVelocityComponent
- Contains the entities current velocity and force being applied.
You can access these components from the base implementing entity or by using the GlobalEntityMapper
GlobalEntityMapper.texture.get(myEntity);
GlobalEntityMapper.position.get(myEntity);
As such, you can access the underlying Ashley
entity within all classes that implement LunarEntity
or
extend AbstractLunarEntity
myLunarEntity.getEntity().add(myComponent);
All entities implement or extend LunarEntity
. LunarEntity
provides a basic outline for properties and methods all
entities should have.
Each entity also includes its own default implemention usually prefixed with Abstract
, for
example AbstractLunarEntityPlayer
.
Type | Implementation | Description |
---|---|---|
LunarEntity | AbstractLunarEntity | The base entity holding common properties |
LunarTexturedEntity | AbstractLunarTexturedEntity | Allows you to store textures, regions, sprites and current drawing states |
LunarEntityPlayer | AbstractLunarEntityPlayer | The base of any player. Provides implementation for spawning, networking, etc. |
LunarEntityNetworkPlayer | AbstractLunarEntityNetworkPlayer | The base of a network player. Provides methods for updating and interpolating position/velocity + more |
Along with these are two adapters; basically, just default implementations that contain convenient methods. These
are Player
and NetworkPlayer
So with creating your own custom entities you may extend any of those default implementations which do a large amount of the work for you. Below is an example of a custom player that does a few extra things.
public final class DemoPlayer extends Player {
public DemoPlayer(boolean initializeComponents, TextureRegion playerTexture) {
super(initializeComponents);
setMoveSpeed(6.0f);
// we don't want to collide with other players
disablePlayerCollision(true);
setMoving(true);
// describes how often position updates will be sent
setNetworkSendRateInMs(10, 10);
// default player texture
addRegion("player", playerTexture);
// default player configuration
setSize(16, 16, (1 / 16.0f));
}
@Override
public void pollInput() {
setVelocity(0.0f, 0.0f);
if (Gdx.input.isKeyPressed(Input.Keys.W)) {
setAngle(0f);
setVelocity(0.0f, getMoveSpeed());
} else if (Gdx.input.isKeyPressed(Input.Keys.S)) {
setAngle(1f);
setVelocity(0.0f, -getMoveSpeed());
} else if (Gdx.input.isKeyPressed(Input.Keys.A)) {
setAngle(2f);
setVelocity(-getMoveSpeed(), 0.0f);
} else if (Gdx.input.isKeyPressed(Input.Keys.D)) {
setAngle(3f);
setVelocity(getMoveSpeed(), 0.0f);
}
}
@Override
public void render(SpriteBatch batch, float delta) {
batch.draw(getRegion("player"), getInterpolatedPosition().x, getInterpolatedPosition().y, getScaledWidth(), getScaledHeight());
}
@Override
public void spawnInWorld(LunarWorld world, Vector2 position) {
super.spawnInWorld(world, position);
// TODO: Implement any custom logic here.
}
}
By default a simple square body is created for the entity when spawning them in a world. You can override and provide
your own custom implementation by using EntityBodyHandler
. When implementing this class you can provide your
own Body
context with however you wish to configure it.
As an example, here is the default implementation to give you an idea.
public class EntityBodyCreator implements EntityBodyHandler {
private BodyDef definition;
private FixtureDef fixture;
private boolean hasSetFixedRotation, hasSetDensity;
private boolean fixedRotation;
private float density;
@Override
public void setBodyDefinition(BodyDef definition) {
this.definition = definition;
}
@Override
public void setFixtureDefinition(FixtureDef definition) {
this.fixture = definition;
}
@Override
public void setHasFixedRotation(boolean fixedRotation) {
this.hasSetFixedRotation = true;
this.fixedRotation = fixedRotation;
}
@Override
public void setDensity(float density) {
this.hasSetDensity = true;
this.density = density;
}
@Override
public void resetDefinition() {
definition = null;
fixture = null;
}
@Override
public Body createBodyInWorld(World world, float x, float y, EntityPropertiesComponent configuration) {
if (definition == null) {
definition = new BodyDef();
definition.type = BodyDef.BodyType.DynamicBody;
}
if (this.fixture == null)
this.fixture = new FixtureDef();
if (hasSetFixedRotation) {
definition.fixedRotation = fixedRotation;
}
definition.position.set(x, y);
final Body body = world.createBody(definition);
PolygonShape shape = null;
if (fixture.shape == null) {
shape = new PolygonShape();
shape.setAsBox(configuration.getScaledWidth() / 2f, configuration.getScaledHeight() / 2f);
fixture.shape = shape;
if (!hasSetDensity) {
fixture.density = 1.0f;
} else {
fixture.density = density;
}
}
body.createFixture(fixture);
if (shape != null) shape.dispose();
return body;
}
}
Once you have created your own implementation you can tell the entity to use it by this method:
myEntity.setBodyHandler(handler);
You should do this once an entity is created, maybe in the constructor, before spawning them or anything.
entity.getPosition();
//
entity.getPreviousPosition();
//
entity.getInterpolatedPosition();
To update positions it is desirable to use the method setPosition
. If you have a box2d entity you can also use transform on this entity.
Generally, transform is only reserved for initial spawning or teleporting, otherwise all other position related changes are by velocity.
// for example, I spawned in my player and I need them to start in a fixed location
player.setPosition(position, angle, true);
If no box2d entity is present (their body) then transform will have no effect.
You can interpolate a entities position by using various methods:
public void interpolatePosition();
public void interpolatePosition(float alpha);
public void interpolatePosition(Interpolation interpolation, float alpha);
You can use these methods to customize which interpolation method to use and the smoothing/alpha. You may wish to override these as-well for your own custom implementation.
Getting Started
Server
Networking
Entities
Worlds
Instances