package com.jenjinstudios.demo.server.event;
import com.jenjinstudios.world.Location;
import com.jenjinstudios.world.WorldObject;
import com.jenjinstudios.world.event.PostUpdateEvent;
import com.jenjinstudios.world.math.Vector2D;
import javafx.geometry.Rectangle2D;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @author Caleb Brinkman
*/
public abstract class Collision implements PostUpdateEvent
{
public static final String SIZE_PROPERTY = "ObjectSize";
public static final double DEFAULT_OBJECT_SIZE = Location.SIZE;
private static final Logger LOGGER = Logger.getLogger(Collision.class.getName());
private final WorldObject worldObject;
public Collision(WorldObject worldObject) { this.worldObject = worldObject; }
@Override
public void onPostUpdate() {
worldObject.getWorld().getWorldObjects().stream().filter(this::checkForCollision).forEach(this::onCollision);
}
private boolean checkForCollision(WorldObject collider) {
boolean collision = false;
if (checkRoughCollision(collider))
{
collision = checkFinerCollision(collider);
}
return collision;
}
private boolean checkRoughCollision(WorldObject collider) {
// TODO Make this more granular.
return collider != worldObject && collider.getZoneID() == worldObject.getZoneID();
}
private boolean checkFinerCollision(WorldObject collider) {
// TODO Probably shouldn't use JavaFX Rectangle; maybe a private inner class?
Rectangle2D objectRect = getCollisionRect(worldObject);
Rectangle2D colliderRect = getCollisionRect(collider);
return objectRect.intersects(colliderRect);
}
private Rectangle2D getCollisionRect(WorldObject obj) {
double objectRad = calculateCollisionRad(obj);
Vector2D objectVector = obj.getVector2D();
double objectX = objectVector.getXCoordinate();
double objectY = objectVector.getYCoordinate();
double objectMinX = objectX - objectRad;
double objectMinY = objectY - objectRad;
return new Rectangle2D(objectMinX, objectMinY, objectRad, objectRad);
}
protected double calculateCollisionRad(WorldObject collider) {
Object o = collider.getProperties().get(SIZE_PROPERTY);
try
{
return (o != null ? (double) o : DEFAULT_OBJECT_SIZE) / 2;
} catch (ClassCastException ex)
{
LOGGER.log(Level.WARNING, "Object size not instance of double: {0}, {1}", new Object[]{collider, o});
return DEFAULT_OBJECT_SIZE / 2;
}
}
public abstract void onCollision(WorldObject collided);
}