EmergentOrganization/cell-rpg

View on GitHub
core/src/io/github/emergentorganization/cellrpg/core/PhysicsContactListener.java

Summary

Maintainability
B
5 hrs
Test Coverage
package io.github.emergentorganization.cellrpg.core;

import com.artemis.Entity;
import com.artemis.World;
import com.artemis.managers.TagManager;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.*;
import io.github.emergentorganization.cellrpg.components.CAGridComponents;
import io.github.emergentorganization.cellrpg.components.CollideEffect;
import io.github.emergentorganization.cellrpg.components.Health;
import io.github.emergentorganization.cellrpg.core.components.Bounds;
import io.github.emergentorganization.cellrpg.core.components.Name;
import io.github.emergentorganization.cellrpg.core.components.Position;
import io.github.emergentorganization.cellrpg.core.components.Rotation;
import io.github.emergentorganization.cellrpg.events.EntityEvent;
import io.github.emergentorganization.cellrpg.events.GameEvent;
import io.github.emergentorganization.cellrpg.managers.EventManager;
import io.github.emergentorganization.cellrpg.systems.CASystems.layers.CALayer;
import io.github.emergentorganization.cellrpg.tools.CGoLShapeConsts;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;


class PhysicsContactListener implements ContactListener {
    private final Logger logger = LogManager.getLogger(getClass());
    private final EventManager eventManager;
    private final com.artemis.World world;

    public PhysicsContactListener(World world) {
        this.world = world;
        this.eventManager = world.getSystem(EventManager.class);
    }

    @Override
    public void beginContact(Contact contact) {

    }

    @Override
    public void endContact(Contact contact) {
        Entity entityA = world.getEntity(getEntityId(contact.getFixtureA()));
        Entity entityB = world.getEntity(getEntityId(contact.getFixtureB()));
        handleContact(entityA, entityB);
    }

    @Override
    public void preSolve(Contact contact, Manifold oldManifold) {

    }

    @Override
    public void postSolve(Contact contact, ContactImpulse impulse) {

    }

    private void handleContact(Entity entityA, Entity entityB) {
        Name nameA = entityA.getComponent(Name.class);
        Name nameB = entityB.getComponent(Name.class);
        handleContact(entityA, nameA);
        handleContact(entityB, nameB);

        handleContactPair(entityA, nameA, entityB, nameB);
        handleContactPair(entityB, nameB, entityA, nameA);
    }

    private void handleContactPair(Entity entityA, Name nameA, Entity entityB, Name nameB) {
        // collision damage form A to B
        if (entityA.getComponent(CollideEffect.class) != null
                && entityB.getComponent(Health.class) != null) {
            entityB.getComponent(Health.class).health -= entityA.getComponent(CollideEffect.class).damage;
//            logger.trace("puff health=" + entityB.getComponent(Health.class).health);
        }

        // === specific pair effects:
        if (nameA.internalID.equals(EntityID.BULLET.toString())
                && nameB.internalID.equals(EntityID.PLAYER.toString())) {
            Health bulletHealth = entityA.getComponent(Health.class);
            if (bulletHealth.health < bulletHealth.maxHealth) {
                // cannot hit until after a bounce (helps keep player from shooting self in foot as bullet is leaving)
                eventManager.pushEvent(new EntityEvent(EntityEvent.NO_ENTITY, GameEvent.PLAYER_HIT));
            }
        } else if (nameA.internalID.equals(EntityID.POWERUP_PLUS.toString())
                && nameB.internalID.equals(EntityID.PLAYER.toString())) {
            eventManager.pushEvent(new EntityEvent(entityB.getId(), GameEvent.POWERUP_PLUS));
            try {
                world.deleteEntity(entityA);
            } catch (RuntimeException ex) {
                logger.trace("powerup_plus already deleted");
            }
        } else if (nameA.internalID.equals(EntityID.POWERUP_STAR.toString())
                && nameB.internalID.equals(EntityID.BULLET.toString())) {
            try {
                Vector2 pos = entityA.getComponent(Position.class)
                        .getCenter(entityA.getComponent(Bounds.class), entityA.getComponent(Rotation.class).angle);
                TagManager tagMan = world.getSystem(TagManager.class);
                tagMan.getEntity(CALayer.VYROIDS.getTag()).getComponent(CAGridComponents.class)
                        .stampCenteredAt(CGoLShapeConsts.EMPTY(30, 30), pos);
                tagMan.getEntity(CALayer.VYROIDS_GENETIC.getTag()).getComponent(CAGridComponents.class)
                        .stampCenteredAt(CGoLShapeConsts.EMPTY(10, 10), pos);
                tagMan.getEntity(CALayer.ENERGY.getTag()).getComponent(CAGridComponents.class)
                        .stampCenteredAt(CGoLShapeConsts.BOOM(30, 30), pos);
                world.deleteEntity(entityA);
            } catch (NullPointerException ex) {
                logger.trace("failed star detonate");
                // powerup may have been deleted
                return;
            } catch (RuntimeException ex) {
                logger.trace("failed star detonate");
                // powerup may have been deleted
                return;
            }
        } else if (nameA.internalID.equals(EntityID.POWERUP_STAR.toString())
                && nameB.internalID.equals(EntityID.PLAYER.toString())) {
            eventManager.pushEvent(new EntityEvent(entityB.getId(), GameEvent.POWERUP_STAR));
            try {
                world.deleteEntity(entityA);
            } catch (RuntimeException ex) {
                logger.trace("star powerup already deleted");
            }
        }
    }

    private void handleContact(Entity entity, Name name) {
//        logger.trace("contact " + name.internalID);

        // collide effects on self
        CollideEffect eff = entity.getComponent(CollideEffect.class);
        if (eff != null) {
            // self-damage from collision
            Health health = entity.getComponent(Health.class);
            if (health != null) {
                health.health -= eff.selfDamage;
//                logger.trace("health-damage="+health.health);
            }
        }

        if (name.internalID.equals(EntityID.BULLET.toString())) {  // TODO: add collide-events to CollideEffect?
            eventManager.pushEvent(new EntityEvent(EntityEvent.NO_ENTITY, GameEvent.COLLISION_BULLET));
        }
    }

    private int getEntityId(Fixture fixture) {
        return (Integer) fixture.getBody().getUserData();
    }
}