package com.gdxjam.systems;
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.Family;
import com.badlogic.ashley.systems.IteratingSystem;
import com.badlogic.gdx.ai.steer.SteeringAcceleration;
import com.badlogic.gdx.ai.steer.SteeringBehavior;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.gdxjam.GameManager;
import com.gdxjam.components.Components;
import com.gdxjam.components.SteerableComponent;
import com.gdxjam.components.SteeringBehaviorComponent;
public class SteeringSystem extends IteratingSystem {
private static final SteeringAcceleration<Vector2> steeringOutput = new SteeringAcceleration<Vector2>(new Vector2());
public SteeringSystem() {
super(Family.all(SteeringBehaviorComponent.class).one(SteerableComponent.class).get());
}
@Override
protected void processEntity(Entity entity, float deltaTime) {
SteeringBehavior<Vector2> behavior = Components.STEERING_BEHAVIOR.get(entity).getBehavior();
SteerableComponent steerable = Components.STEERABLE.get(entity);
if (behavior == null)
return;
if (steerable.getBody() == null)
return; // We shouldn't need this
behavior.calculateSteering(steeringOutput);
boolean anyAccelerations = false;
Body body = steerable.getBody();
if (!steeringOutput.linear.isZero()) {
Vector2 force = steeringOutput.linear.scl(deltaTime);
body.applyForceToCenter(force, true);
anyAccelerations = true;
}
// Update orientation and angular velocity
if (steerable.isIndependentFacing()) {
if (steeringOutput.angular != 0) {
body.applyTorque(steeringOutput.angular * deltaTime, true);
anyAccelerations = true;
}
}
else {
// If we haven't got any velocity, then we can do nothing.
Vector2 linVel = body.getLinearVelocity();
if (!linVel.isZero(steerable.getZeroLinearSpeedThreshold())) {
float newOrientation = steerable.vectorToAngle(linVel);
body.setAngularVelocity((newOrientation - steerable.getAngularVelocity()) * deltaTime); // this
// is
// superfluous
// if
// independentFacing
// is
// always
// true
body.setTransform(body.getPosition(), newOrientation);
}
}
if (anyAccelerations) {
// Cap the linear speed
Vector2 velocity = body.getLinearVelocity();
float currentSpeedSquare = velocity.len2();
float maxLinearSpeed = steerable.getMaxLinearSpeed();
if (currentSpeedSquare > maxLinearSpeed * maxLinearSpeed) {
body.setLinearVelocity(velocity.scl(maxLinearSpeed / (float) Math.sqrt(currentSpeedSquare)));
}
// Cap the angular speed
float maxAngVelocity = steerable.getMaxAngularSpeed();
if (body.getAngularVelocity() > maxAngVelocity) {
body.setAngularVelocity(maxAngVelocity);
}
}
}
@Override
public boolean checkProcessing() {
return !GameManager.isPaused();
}
}