From ee3e8ec9883c1f78c73493526b493cef33bd9fc7 Mon Sep 17 00:00:00 2001 From: Dmitri Morozov Date: Fri, 9 Feb 2024 13:43:17 +0100 Subject: Smart pursue for enemy ships --- assets/face.png | Bin 0 -> 29258 bytes assets/target.png | Bin 0 -> 8279 bytes .../org/snoopdesigns/endless/config/Config.java | 4 +- .../snoopdesigns/endless/physics/PhysicalBody.java | 1 + .../endless/world/ship/SteerableEnemyShip.java | 131 +++++++++++++++------ 5 files changed, 100 insertions(+), 36 deletions(-) create mode 100644 assets/face.png create mode 100644 assets/target.png diff --git a/assets/face.png b/assets/face.png new file mode 100644 index 0000000..80006f9 Binary files /dev/null and b/assets/face.png differ diff --git a/assets/target.png b/assets/target.png new file mode 100644 index 0000000..ed80e94 Binary files /dev/null and b/assets/target.png differ diff --git a/core/src/org/snoopdesigns/endless/config/Config.java b/core/src/org/snoopdesigns/endless/config/Config.java index 34ce45d..31b9d0e 100644 --- a/core/src/org/snoopdesigns/endless/config/Config.java +++ b/core/src/org/snoopdesigns/endless/config/Config.java @@ -1,8 +1,8 @@ package org.snoopdesigns.endless.config; public final class Config { - private static int screenWidth = 1280; - private static int screenHeight = 720; + private static int screenWidth = 1900; + private static int screenHeight = 1200; private Config() { } diff --git a/core/src/org/snoopdesigns/endless/physics/PhysicalBody.java b/core/src/org/snoopdesigns/endless/physics/PhysicalBody.java index 31204a9..914d06a 100644 --- a/core/src/org/snoopdesigns/endless/physics/PhysicalBody.java +++ b/core/src/org/snoopdesigns/endless/physics/PhysicalBody.java @@ -37,6 +37,7 @@ public abstract class PhysicalBody { public void limitVelocity() { if (getBody().getLinearVelocity().len() > getMaxVelocity()) { + System.out.println("Limit velocity" + getMaxVelocity()); getBody().setLinearVelocity(getBody().getLinearVelocity().limit(getMaxVelocity())); } } diff --git a/core/src/org/snoopdesigns/endless/world/ship/SteerableEnemyShip.java b/core/src/org/snoopdesigns/endless/world/ship/SteerableEnemyShip.java index 4a0ae2d..6db087e 100644 --- a/core/src/org/snoopdesigns/endless/world/ship/SteerableEnemyShip.java +++ b/core/src/org/snoopdesigns/endless/world/ship/SteerableEnemyShip.java @@ -5,9 +5,9 @@ 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.steer.behaviors.Wander; import com.badlogic.gdx.ai.utils.Location; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Sprite; @@ -21,14 +21,24 @@ import org.snoopdesigns.endless.context.Context; import org.snoopdesigns.endless.physics.Box2DLocation; import org.snoopdesigns.endless.physics.SteerablePhysicalBody; import org.snoopdesigns.endless.world.Renderable; +import org.snoopdesigns.endless.world.effects.EngineEffect; public class SteerableEnemyShip extends SteerablePhysicalBody implements Renderable { private Sprite sprite; + private Sprite targetSprite; //target position + private Sprite farAttackPointSprite; //farAttackPoint + private Sprite faceSprite; //face position private final SteeringAcceleration steeringOutput = new SteeringAcceleration<>(new Vector2()); private BlendedSteering steeringCombination; - private Location target; + private Location positionTarget; + private Location faceTarget; + private float targetDirection; + + private final Vector2 lastVelocity = new Vector2(0f, 0f); + + private EngineEffect engineEffect; @Override public BodyType getBodyType() { @@ -56,12 +66,12 @@ public class SteerableEnemyShip extends SteerablePhysicalBody implements Rendera @Override public float getMaxVelocity() { - return 50; + return 80f; } @Override public Vector2 getInitialPosition() { - return new Vector2(MathUtils.random(50), MathUtils.random(50)); + return new Vector2(MathUtils.random(150), MathUtils.random(150)); } @Override @@ -69,33 +79,83 @@ public class SteerableEnemyShip extends SteerablePhysicalBody implements Rendera initBody(); final Texture texture = new Texture(Gdx.files.internal("ship.png")); sprite = new Sprite(texture); - sprite.setScale(0.1f); + final float expectedSizeInMeters = 15f; + final Vector2 scale = new Vector2( + expectedSizeInMeters / sprite.getHeight(), + expectedSizeInMeters / sprite.getWidth()); + sprite.setScale(scale.x, scale.y); sprite.setRotation(MathUtils.radDeg * getBody().getAngle()); - target = new Box2DLocation(); - target.getPosition().set( - Context.getInstance().getPlayerShip().getBody().getPosition().x, - Context.getInstance().getPlayerShip().getBody().getPosition().y); - target.setOrientation(Context.getInstance().getPlayerShip().getBody().getAngle()); + final Texture targetTexture = new Texture(Gdx.files.internal("target.png")); + targetSprite = new Sprite(targetTexture); + targetSprite.setScale(0.03f); + farAttackPointSprite = new Sprite(targetTexture); + farAttackPointSprite.setScale(0.02f); + faceSprite = new Sprite(new Texture(Gdx.files.internal("face.png"))); + faceSprite.setScale(0.02f); + + positionTarget = new Box2DLocation(); + faceTarget = new Box2DLocation(); + + engineEffect = new EngineEffect(this); steeringCombination = new BlendedSteering<>(this); getSteeringBehaviours().forEach(steeringBehaviour -> steeringCombination.add(steeringBehaviour, 0.5f)); + + targetDirection = MathUtils.random(MathUtils.PI2); } @Override public void render(SpriteBatch batch) { - target.getPosition().set( - Context.getInstance().getPlayerShip().getBody().getPosition().x, - Context.getInstance().getPlayerShip().getBody().getPosition().y); - target.setOrientation(Context.getInstance().getPlayerShip().getBody().getAngle()); + final float maxDistance = 100f; + final float minDistance = 70f; + final Vector2 targetDisplacement = new Vector2(maxDistance, 0f).rotateRad(targetDirection); + final Vector2 farAttackPoint = new Vector2( + Context.getInstance().getPlayerShip().getBody().getPosition().x + targetDisplacement.x, + Context.getInstance().getPlayerShip().getBody().getPosition().y + targetDisplacement.y); + final float distanceToPlayer = new Vector2( + getBody().getPosition().x - Context.getInstance().getPlayerShip().getBody().getPosition().x, + 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() / 2f; + } + 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); + //positionTarget.setOrientation(Context.getInstance().getPlayerShip().getBody().getAngle()); + faceTarget.getPosition().set(positionTarget.getPosition()); steeringCombination.calculateSteering(steeringOutput); + if (distanceToPlayer <= minDistance) { // do not move, if close to player, only rotate + steeringOutput.linear.setZero(); + } applySteering(); sprite.setCenter(getBody().getPosition().x, getBody().getPosition().y); sprite.setRotation(MathUtils.radDeg * getBody().getAngle()); sprite.draw(batch); + farAttackPointSprite.setCenter( + farAttackPoint.x, + farAttackPoint.y); + farAttackPointSprite.draw(batch); + targetSprite.setCenter( + positionTarget.getPosition().x, + positionTarget.getPosition().y); + targetSprite.draw(batch); + faceSprite.setCenter( + faceTarget.getPosition().x, + faceTarget.getPosition().y); + faceSprite.draw(batch); + + engineEffect.render(batch); + + // TODO limitVelocity(); } @@ -105,21 +165,11 @@ public class SteerableEnemyShip extends SteerablePhysicalBody implements Rendera private List> getSteeringBehaviours() { return List.of( - new Face<>(this, target), - /*new Arrive<>(this, target) + new Face<>(this, faceTarget), + new Arrive<>(this, positionTarget) .setTimeToTarget(0.1f) - .setArrivalTolerance(1f) - .setDecelerationRadius(100f)*/ - new Wander<>(this) - .setTarget(target) - .setFaceEnabled(true) // We want to use Face internally (independent facing is on) - .setAlignTolerance(0.001f) // Used by Face - .setDecelerationRadius(100f) // Used by Face - .setTimeToTarget(0.1f) // Used by Face - .setWanderOffset(200) // - .setWanderOrientation(10) // - .setWanderRadius(200f) // - .setWanderRate(MathUtils.PI2 * 4) + .setArrivalTolerance(10f) + .setDecelerationRadius(100f) ); } @@ -140,15 +190,28 @@ public class SteerableEnemyShip extends SteerablePhysicalBody implements Rendera } if (!steeringOutput.linear.isZero()) { - speedUp(steeringOutput.linear); + if (steeringOutput.linear.len() >= lastVelocity.len() - 10) { + speedUp(steeringOutput.linear); + engineEffect.start(); + } else { + engineEffect.stop(); + } + lastVelocity.x = steeringOutput.linear.x; + lastVelocity.y = steeringOutput.linear.y; + } else { + engineEffect.stop(); } } private void speedUp(final Vector2 force) { - getBody().applyForceToCenter( - force.x * 100, - force.y * 100, - true); + /*getBody().applyForceToCenter( + force.x * 10000, + force.y * 10000, + true);*/ + + final float forceToApply = getBody().getMass() * 200; // force 200x times more than self mass + final Vector2 impulse = new Vector2(forceToApply, 0).rotateRad(getBody().getAngle()); + getBody().applyForceToCenter(impulse, true); } // TODO common @@ -159,7 +222,7 @@ public class SteerableEnemyShip extends SteerablePhysicalBody implements Rendera @Override public float getMaxSpeed() { - return 70f; + return 100f; } @Override -- cgit v1.2.3