0
\$\begingroup\$

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:

Between two players

Between an entity and a body on the map

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.

\$\endgroup\$
  • \$\begingroup\$ What are you doing with the body variable after entityManager.createEntity()? It is not needed and it will not point to the right object. \$\endgroup\$ – Niall Quinlan Dec 28 '17 at 16:29
  • \$\begingroup\$ I just use the body variable to initiate the creation of the entity through the createEntity() method, after that it is no longer called. EDIT: I got rid of that variable and instead have the body created by the BodyComponent's addBody() method, but the problem still persists. \$\endgroup\$ – BlueJet Dec 28 '17 at 17:47
  • \$\begingroup\$ Static bodies dont have collisions, use a dynamicbody \$\endgroup\$ – Niall Quinlan Dec 28 '17 at 19:00
  • \$\begingroup\$ @NiallQuinlan It seems that changing the entity from a Static body to a Kinematic body fixed the issue. I completely forgot that Static bodies had no collisions. Thanks for pointing that out. \$\endgroup\$ – BlueJet Dec 28 '17 at 20:36
1
\$\begingroup\$

After following a suggestion to change the entity body from Static to Kinematic, it seems that the whole problem sorted itself out. The reason for this is that Static bodies do not have collision detection.

\$\endgroup\$
  • \$\begingroup\$ Glad to hear you found a solution to your problem! Please mark it as accepted - this helps others who may run into the same or similar problems. \$\endgroup\$ – Pikalek Aug 8 '18 at 22:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.