Box2dSteeringBody.java
/*******************************************************************************
* Copyright 2014 davebaol https://github.com/davebaol
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
/*
* Max velocity/acceleration values were set and applySteering() was modified to fit the needs of this project.
*/
package com.devcharles.piazzapanic.utility.box2d;
import com.badlogic.gdx.ai.steer.Steerable;
import com.badlogic.gdx.ai.steer.SteeringAcceleration;
import com.badlogic.gdx.ai.steer.SteeringBehavior;
import com.badlogic.gdx.ai.utils.Location;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
/**
* Box2D {@link Body} and logic for AI agents, the {@link Box2dSteeringBody} responds to
* inputs from a {@link SteeringBehavior}. If no behaviour is set, the body will not move.
*/
public class Box2dSteeringBody implements Steerable<Vector2> {
Body body;
float boundingRadius;
boolean tagged;
float maxLinearSpeed = 1000;
float maxLinearAcceleration = 1000;
float maxAngularSpeed = 1000;
float maxAngularAcceleration = 1000;
boolean independentFacing;
protected SteeringBehavior<Vector2> steeringBehavior;
private static final SteeringAcceleration<Vector2> steeringOutput = new SteeringAcceleration<Vector2>(
new Vector2());
public Box2dSteeringBody(Body body, boolean independentFacing, float boundingRadius) {
this.body = body;
this.independentFacing = independentFacing;
this.boundingRadius = boundingRadius;
this.tagged = false;
body.setUserData(this);
}
public Body getBody() {
return body;
}
public void setBody(Body body) {
this.body = body;
}
public boolean isIndependentFacing() {
return independentFacing;
}
public void setIndependentFacing(boolean independentFacing) {
this.independentFacing = independentFacing;
}
@Override
public Vector2 getPosition() {
return body.getPosition();
}
@Override
public float getOrientation() {
return body.getAngle();
}
@Override
public void setOrientation(float orientation) {
body.setTransform(getPosition(), orientation);
}
@Override
public Vector2 getLinearVelocity() {
return body.getLinearVelocity();
}
@Override
public float getAngularVelocity() {
return body.getAngularVelocity();
}
@Override
public float getBoundingRadius() {
return boundingRadius;
}
@Override
public boolean isTagged() {
return tagged;
}
@Override
public void setTagged(boolean tagged) {
this.tagged = tagged;
}
@Override
public Location<Vector2> newLocation() {
return new Box2dLocation();
}
@Override
public float vectorToAngle(Vector2 vector) {
return (float) Math.atan2(-vector.x, vector.y);
}
@Override
public Vector2 angleToVector(Vector2 outVector, float angle) {
outVector.x = -(float) Math.sin(angle);
outVector.y = (float) Math.cos(angle);
return outVector;
}
public SteeringBehavior<Vector2> getSteeringBehavior() {
return steeringBehavior;
}
public void setSteeringBehavior(SteeringBehavior<Vector2> steeringBehavior) {
this.steeringBehavior = steeringBehavior;
}
public void update(float deltaTime) {
if (steeringBehavior != null) {
// Calculate steering acceleration
steeringBehavior.calculateSteering(steeringOutput);
// Apply steering acceleration
applySteering(steeringOutput, deltaTime);
}
}
protected void applySteering(SteeringAcceleration<Vector2> steering, float deltaTime) {
boolean anyAccelerations = false;
// Update position and linear velocity.
if (!steeringOutput.linear.isZero()) {
// this method internally scales the force by deltaTime
body.applyForceToCenter(steeringOutput.linear.cpy().scl(2), true);
anyAccelerations = true;
}
// Update orientation and angular velocity
if (isIndependentFacing()) {
if (steeringOutput.angular != 0) {
// this method internally scales the torque by deltaTime
body.applyTorque(steeringOutput.angular, true);
anyAccelerations = true;
}
} else {
}
if (anyAccelerations) {
// Cap the linear speed
Vector2 velocity = body.getLinearVelocity();
float currentSpeedSquare = velocity.len2();
float maxLinearSpeed = getMaxLinearSpeed();
if (currentSpeedSquare > maxLinearSpeed * maxLinearSpeed) {
body.setLinearVelocity(velocity.scl(maxLinearSpeed / (float) Math.sqrt(currentSpeedSquare)));
}
// Cap the angular speed
float maxAngVelocity = getMaxAngularSpeed();
if (body.getAngularVelocity() > maxAngVelocity) {
body.setAngularVelocity(maxAngVelocity);
}
}
}
//
// Limiter implementation
//
@Override
public float getMaxLinearSpeed() {
return maxLinearSpeed;
}
@Override
public void setMaxLinearSpeed(float maxLinearSpeed) {
this.maxLinearSpeed = maxLinearSpeed;
}
@Override
public float getMaxLinearAcceleration() {
return maxLinearAcceleration;
}
@Override
public void setMaxLinearAcceleration(float maxLinearAcceleration) {
this.maxLinearAcceleration = maxLinearAcceleration;
}
@Override
public float getMaxAngularSpeed() {
return maxAngularSpeed;
}
@Override
public void setMaxAngularSpeed(float maxAngularSpeed) {
this.maxAngularSpeed = maxAngularSpeed;
}
@Override
public float getMaxAngularAcceleration() {
return maxAngularAcceleration;
}
@Override
public void setMaxAngularAcceleration(float maxAngularAcceleration) {
this.maxAngularAcceleration = maxAngularAcceleration;
}
@Override
public float getZeroLinearSpeedThreshold() {
return 0.001f;
}
@Override
public void setZeroLinearSpeedThreshold(float value) {
throw new UnsupportedOperationException();
}
}