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(); } }