package net.alcuria.umbracraft.engine.components;
import net.alcuria.umbracraft.Game;
import net.alcuria.umbracraft.engine.entities.Entity;
import net.alcuria.umbracraft.engine.entities.EntityManager.EntityScope;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Rectangle;
/** A component for handling when an entity overlaps with another entity.
* @author Andrew Keturi */
public class EntityCollisionComponent implements Component {
private final Rectangle r1 = new Rectangle(), r2 = new Rectangle();
@Override
public void create(Entity entity) {
}
@Override
public void dispose(Entity entity) {
}
public Rectangle getBounds() {
return r1;
}
@Override
public void render(Entity entity) {
if (Game.isDebug()) {
Color oldColor = Game.batch().getColor();
Game.batch().setColor(Color.RED);
Game.batch().draw(Game.assets().get("debug.png", Texture.class), r1.x, r1.y, r1.width, r1.height);
Game.batch().setColor(oldColor);
}
}
@Override
public void update(Entity entity) {
for (Entity otherEntity : Game.entities().getEntities(EntityScope.MAP)) {
// ensure it's another entity and it's on the same z axis
if (otherEntity != entity && MathUtils.isEqual(entity.position.z, otherEntity.position.z, 2f)) {
// only check a collision if both entities have an EntityCollisionComponent and the other entity is visible
if (entity.getComponent(EntityCollisionComponent.class) != null && otherEntity.getComponent(EntityCollisionComponent.class) != null && otherEntity.isVisible()) {
MapCollisionComponent component = entity.getComponent(MapCollisionComponent.class);
MapCollisionComponent otherComponent = otherEntity.getComponent(MapCollisionComponent.class);
// only check a collision if both entities have an MapCollisionComponent
if (component != null && otherComponent != null) {
r1.set(entity.position.x - component.getWidth() / 2, entity.position.y - component.getHeight() / 2, component.getWidth(), component.getHeight());
r2.set(otherEntity.position.x - otherComponent.getWidth() / 2, otherEntity.position.y - otherComponent.getHeight() / 2, otherComponent.getWidth(), otherComponent.getHeight());
if (r1.overlaps(r2)) {
// determine the magnitude of overlap for both x and y
float overlapX = Math.min(Math.abs(r2.x + r2.width - r1.x), Math.abs(r1.x + r1.width - r2.x));
float overlapY = Math.min(Math.abs(r2.y + r2.height - r1.y), Math.abs(r1.y + r1.height - r2.y));
// if there's more x overlap we want to nudge in the y direction, and vice versa
if (overlapX < overlapY) {
// determine nudge sign by the x positions
if (r1.x > r2.x) {
entity.position.x += overlapX;
} else {
entity.position.x -= overlapX;
}
} else {
// determine nudge sign by the y positions
if (r1.y > r2.y) {
entity.position.y += overlapY;
} else {
entity.position.y -= overlapY;
}
}
// determine if we need to start an even triggered on touch
final ScriptComponent scripts = otherEntity.getComponent(ScriptComponent.class);
if (scripts != null) {
scripts.setCollided();
}
}
}
}
}
}
}
}