I've just recently learned of Ashley ECS while searching up tutorials on the libGDX wiki and I've been replacing many aspects of my code with the Ashley ECS components which has made life a lot easier, however, I have encountered a problem that I can't seem to solve. The problem is is that I am also using box2D for the physics/collision detection side of my game and the problem that I have encountered is is that when I declare my box2D World in my WorldGen class and go on to use that variable in my Ashley ECS system, the collision detection is broken between the bodies on my map and my entities such as the player. In addition, the collision detection of two entities using the system does not work. Here is the code:
In WorldGen:
world = new World(new Vector2(0f, 0f), true);
...
//Instance of an entity in the world
entityManager.createEntity(new Vector2(500, 500),
SpriteSheet.npcSpriteSheet, true,
"Billy",
MobType.VILLAGER,
TitleTypes.PEASANT,
this.getWorld(),
body, 10,
BodyDef.BodyType.StaticBody, "npc1_1/");
In my EntityManager:
public Entity createEntity (Vector2 position,
TextureAtlas atlas, boolean isRenderable,
String mobName, MobType mobType, TitleTypes title,
World world, Body body, float mass, BodyDef.BodyType bodyType, String extension) {
Entity entity = new Entity();
entity.add(new PositionComponent(position.x, position.y))
.add(new SpriteComponent(extension, atlas))
.add(new SocialComponent(mobName, mobType, title))
.add(new BodyComponent(world, body, mass, new SpriteComponent(extension, atlas).getSprite, bodyType, position));
if (isRenderable) {
entity.add(new RenderableComponent());
}
engine.addEntity(entity);
return entity;
}
BodyComponent:
public class BodyComponent implements Component {
public transient World world;
public transient Body body;
public float mass;
public transient Sprite sprite;
public transient BodyDef.BodyType type;
public transient Vector2 position;
public BodyComponent(World world, Body body, float mass, Sprite sprite, BodyDef.BodyType type, Vector2 position) {
this.world = world;
this.body = body;
this.mass = mass;
this.sprite = sprite;
this.type = type;
this.position = position;
addBody();
}
public void updateBox2D (PositionComponent component) {
//Forces the values into integers instead of real numbers
component.posX = this.body.getPosition().x * GameUtils.PPM;
component.posY = this.body.getPosition().y * GameUtils.PPM;
}
public Body addBody () {
BodyDef bodyDef = new BodyDef();
bodyDef.type = type;
bodyDef.position.set(position.x / GameUtils.PPM, position.y / GameUtils.PPM);
bodyDef.fixedRotation = true;
//bodyDef.position.set(700/ GameUtils.PPM, 700/ GameUtils.PPM); //I hard-set values here, change to relative values
this.body = world.createBody (bodyDef);
PolygonShape shape = new PolygonShape();
shape.setAsBox((sprite.getWidth()/4) / GameUtils.PPM, (sprite.getHeight()/4) / GameUtils.PPM);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = mass;
Fixture fixture = this.body.createFixture (fixtureDef);
shape.dispose();
return body;
}
}
In my ControlledMovementSystem:
public void update(float deltaTime) {
for (int i = 0; i < entities.size(); ++i) {
Entity entity = entities.get(i);
PositionComponent position = pm.get(entity);
SocialComponent socialComponent = socialComponents.get(entity);
BodyComponent bodyComponent = bodyComponents.get(entity);
//bodyComponent.world = this.world;
switch (socialComponent.mobType) {
case PLAYER:
position.isWalking = false;
position.isStanding = true;
if (StateGame.getGameRenderer().getPlayerGUI().getInvScreen().getInventoryActorVisibility() == true) {
return;
}
if (!position.isWalking) {
position.isStanding = true;
}
bodyComponent.updateBox2D (position);
handlePlayerMovements(position, bodyComponent);
System.out.println("-----------------");
System.out.println("Entity x-pos: " + bodyComponent.body.getPosition().x);
System.out.println("Entity y-pos: " + bodyComponent.body.getPosition().y);
break;
case NOBLE:
break;
case VILLAGER:
break;
case MONSTER:
break;
}
}
}
private void handlePlayerMovements (PositionComponent positionComponent, BodyComponent bodyComponent) {
float xa = 0, ya = 0;
if (Gdx.input.isKeyPressed(Input.Keys.W) || Gdx.input.isKeyPressed(Input.Keys.UP)) {
positionComponent.setAnimationBooleans(true, false, false, false, true, false);
ya++;
} else if (Gdx.input.isKeyPressed(Input.Keys.S) || Gdx.input.isKeyPressed(Input.Keys.DOWN)) {
positionComponent.setAnimationBooleans(false, true, false, false, true, false);
ya--;
}
if (Gdx.input.isKeyPressed(Input.Keys.D) || Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
positionComponent.setAnimationBooleans(false, false, false, true, true, false);
xa++;
} else if (Gdx.input.isKeyPressed(Input.Keys.A) || Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
positionComponent.setAnimationBooleans(false, false, true, false, true, false);
xa--;
}
bodyComponent.body.setLinearVelocity(xa * 50, ya * 50);
// position.posX += xa; // position.posY += ya; } }
In my Mob class' render method:
private void updateEntityPosition () {
objectBody = objectEntity.getComponent(BodyComponent.class).body;
position.x = (int) (objectBody.getPosition().x);
position.y = (int) (objectBody.getPosition().y);
}
This is what it looks like in-game:
Before posting this I checked to see if this would be caused by two different box2D worlds being active at the same time, but the body counts are the same when I check this. I feel like the problem lies with the createEntity() method that I have in my EntityManager.
To clarify, I do not declare the 'body' variable fully in the WorldGen class because the body gets created in the BodyComponent class.