summaryrefslogtreecommitdiff
path: root/core/src/org/snoopdesigns/endless/world/steering
diff options
context:
space:
mode:
authorDmitri Morozov <snoopdesigns@gmail.com>2024-02-09 14:44:02 +0100
committerue86388 <dmitrii.morozov@sbb.ch>2024-02-09 14:44:02 +0100
commit6fec228efbc3534b7464e70e0791e0afdd94d4f6 (patch)
treeb092848c94fcf71e7b2f8796709f551ffb80c610 /core/src/org/snoopdesigns/endless/world/steering
parentee3e8ec9883c1f78c73493526b493cef33bd9fc7 (diff)
Smart pursue for enemy shipsHEADmaster
Diffstat (limited to 'core/src/org/snoopdesigns/endless/world/steering')
-rw-r--r--core/src/org/snoopdesigns/endless/world/steering/ChaseSteering.java108
-rw-r--r--core/src/org/snoopdesigns/endless/world/steering/Steering.java5
-rw-r--r--core/src/org/snoopdesigns/endless/world/steering/SteeringApplicator.java9
3 files changed, 122 insertions, 0 deletions
diff --git a/core/src/org/snoopdesigns/endless/world/steering/ChaseSteering.java b/core/src/org/snoopdesigns/endless/world/steering/ChaseSteering.java
new file mode 100644
index 0000000..3ac3ac7
--- /dev/null
+++ b/core/src/org/snoopdesigns/endless/world/steering/ChaseSteering.java
@@ -0,0 +1,108 @@
+package org.snoopdesigns.endless.world.steering;
+
+import java.util.List;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.ai.steer.SteeringAcceleration;
+import com.badlogic.gdx.ai.steer.SteeringBehavior;
+import com.badlogic.gdx.ai.steer.behaviors.Arrive;
+import com.badlogic.gdx.ai.steer.behaviors.BlendedSteering;
+import com.badlogic.gdx.ai.steer.behaviors.Face;
+import com.badlogic.gdx.ai.utils.Location;
+import com.badlogic.gdx.math.MathUtils;
+import com.badlogic.gdx.math.Vector2;
+import org.snoopdesigns.endless.context.Context;
+import org.snoopdesigns.endless.physics.Box2DLocation;
+import org.snoopdesigns.endless.physics.SteerablePhysicalBody;
+
+public class ChaseSteering implements Steering {
+
+ private final SteeringAcceleration<Vector2> steeringOutput = new SteeringAcceleration<>(new Vector2());
+ private final BlendedSteering<Vector2> steeringCombination;
+ private final Location<Vector2> positionTarget;
+ private final Location<Vector2> faceTarget;
+ private final SteeringApplicator steeringApplicator;
+ private final SteerablePhysicalBody steerablePhysicalBody;
+ private final Vector2 lastVelocity = new Vector2(0f, 0f);
+ private final float maxDistance;
+ private final float minDistance;
+ private float targetDirection;
+
+ public ChaseSteering(final SteerablePhysicalBody steerablePhysicalBody,
+ final float maxDistance,
+ final float minDistance,
+ final SteeringApplicator steeringApplicator) {
+ this.steerablePhysicalBody = steerablePhysicalBody;
+ this.maxDistance = maxDistance;
+ this.minDistance = minDistance;
+ this.steeringApplicator = steeringApplicator;
+
+ positionTarget = new Box2DLocation();
+ faceTarget = new Box2DLocation();
+
+ steeringCombination = new BlendedSteering<>(steerablePhysicalBody);
+ getSteeringBehaviours().forEach(steeringBehaviour ->
+ steeringCombination.add(steeringBehaviour, 0.5f));
+
+ targetDirection = MathUtils.random(MathUtils.PI2);
+ }
+
+ @Override
+ public void calculate() {
+ final Vector2 targetDisplacement = new Vector2(maxDistance, 0f).rotateRad(targetDirection);
+ final float distanceToPlayer = new Vector2(
+ steerablePhysicalBody.getBody().getPosition().x -
+ Context.getInstance().getPlayerShip().getBody().getPosition().x,
+ steerablePhysicalBody.getBody().getPosition().y -
+ Context.getInstance().getPlayerShip().getBody().getPosition().y)
+ .len();
+ if (distanceToPlayer > maxDistance + 10f) {
+ // Rotate target rotation point only of player is far away
+ targetDirection += Gdx.graphics.getDeltaTime() / 1f;
+ }
+ final Vector2 displacement = targetDisplacement.limit(Math.max(0, (distanceToPlayer - minDistance)));
+ final Vector2 targetPos = new Vector2(
+ Context.getInstance().getPlayerShip().getBody().getPosition().x + displacement.x,
+ Context.getInstance().getPlayerShip().getBody().getPosition().y + displacement.y);
+
+ positionTarget.getPosition().set(targetPos);
+ faceTarget.getPosition().set(positionTarget.getPosition());
+
+ steeringCombination.calculateSteering(steeringOutput);
+ if (distanceToPlayer <= minDistance) { // do not move, if close to player, only rotate
+ steeringOutput.linear.setZero();
+ }
+
+ applySteering();
+ }
+
+ private void applySteering() {
+ // Update position and linear velocity.
+ if (steeringOutput.angular != 0) {
+ // this method internally scales the torque by deltaTime
+ steeringApplicator.applyAngularVelocity(steeringOutput.angular);
+ }
+
+ if (!steeringOutput.linear.isZero()) {
+ if (steeringOutput.linear.len() >= lastVelocity.len() - 10) {
+ steeringApplicator.applyLinearVelocity(steeringOutput.linear);
+ } else {
+ steeringApplicator.stopLinearVelocity();
+ }
+ lastVelocity.x = steeringOutput.linear.x;
+ lastVelocity.y = steeringOutput.linear.y;
+ } else {
+ steeringApplicator.stopLinearVelocity();
+ }
+ }
+
+ private List<SteeringBehavior<Vector2>> getSteeringBehaviours() {
+ return List.of(
+ new Face<>(steerablePhysicalBody, faceTarget),
+ new Arrive<>(steerablePhysicalBody, positionTarget)
+ .setTimeToTarget(0.1f)
+ .setArrivalTolerance(10f)
+ .setDecelerationRadius(100f)
+ );
+ }
+}
diff --git a/core/src/org/snoopdesigns/endless/world/steering/Steering.java b/core/src/org/snoopdesigns/endless/world/steering/Steering.java
new file mode 100644
index 0000000..c13b575
--- /dev/null
+++ b/core/src/org/snoopdesigns/endless/world/steering/Steering.java
@@ -0,0 +1,5 @@
+package org.snoopdesigns.endless.world.steering;
+
+public interface Steering {
+ void calculate();
+}
diff --git a/core/src/org/snoopdesigns/endless/world/steering/SteeringApplicator.java b/core/src/org/snoopdesigns/endless/world/steering/SteeringApplicator.java
new file mode 100644
index 0000000..d683465
--- /dev/null
+++ b/core/src/org/snoopdesigns/endless/world/steering/SteeringApplicator.java
@@ -0,0 +1,9 @@
+package org.snoopdesigns.endless.world.steering;
+
+import com.badlogic.gdx.math.Vector2;
+
+public interface SteeringApplicator {
+ void applyAngularVelocity(float angular);
+ void applyLinearVelocity(Vector2 linear);
+ void stopLinearVelocity();
+}