Coverage Summary for Class: AINavigation (com.mygdx.game.Components)
Class |
Method, %
|
Line, %
|
AINavigation |
37%
(10/27)
|
56.7%
(34/60)
|
AINavigation$1 |
AINavigation$Attributes |
100%
(1/1)
|
100%
(7/7)
|
Total |
39.3%
(11/28)
|
61.2%
(41/67)
|
1 package com.mygdx.game.Components;
2
3 import com.badlogic.gdx.ai.steer.Steerable;
4 import com.badlogic.gdx.ai.steer.SteeringAcceleration;
5 import com.badlogic.gdx.ai.steer.SteeringBehavior;
6 import com.badlogic.gdx.ai.utils.Location;
7 import com.badlogic.gdx.math.Vector2;
8 import com.mygdx.game.Entitys.Ship;
9 import com.mygdx.game.Managers.GameManager;
10 import com.mygdx.utils.Utilities;
11
12 /**
13 * Used to control NPCs with steerable for movement and state machines for behaviour
14 */
15 public class AINavigation extends Component implements Steerable<Vector2> {
16 /**
17 * NPC settings class to be used for steerable units
18 */
19 private static class Attributes {
20 public float boundingRadius = 128;
21 public float maxSpd = GameManager.getSettings().get("AI").getFloat("maxSpeed");
22 public float maxAcc = 50000;
23 public float maxAngSpd = 0;
24 public float maxAngAcc = 0;
25 public boolean isTagged = false;
26 }
27
28 RigidBody rb;
29 Transform t;
30 Attributes attributes;
31 SteeringBehavior<Vector2> behavior;
32 SteeringAcceleration<Vector2> steeringOutput;
33
34 /**
35 * Creates a simple navigation component
36 */
37 public AINavigation() {
38 super();
39 attributes = new Attributes();
40 setRequirements(ComponentType.RigidBody);
41 type = ComponentType.AINavigation;
42 steeringOutput = new SteeringAcceleration<>(new Vector2());
43 }
44
45 /**
46 * @param behavior the behavior the AI will be set to
47 */
48 public void setBehavior(SteeringBehavior<Vector2> behavior) {
49 this.behavior = behavior;
50 }
51
52 /**
53 * Gets the components if != null
54 */
55 private void getComps() {
56 if (rb == null) {
57 rb = parent.getComponent(RigidBody.class);
58 t = parent.getComponent(Transform.class);
59 }
60 }
61
62 /**
63 * Called once per frame. Apply the steering behaviour and sets the ship direction, so it faces the right way
64 */
65 @Override
66 public void update() {
67 super.update();
68 getComps();
69 if (behavior != null) {
70 behavior.calculateSteering(steeringOutput);
71 applySteering();
72 } else {
73 stop();
74 }
75
76 Vector2 vel = rb.getVelocity().cpy();
77 if (vel.x == 0 && vel.y == 0) {
78 ((Ship) parent).setShipDirection("-up");
79 return;
80 }
81 vel.nor();
82 Utilities.round(vel);
83
84 if (Ship.shipDirections.containsKey(vel)) {
85 ((Ship) parent).setShipDirection(vel);
86 }
87 }
88
89 /**
90 * Calculates the forces required by the steering behaviour (no rotation)
91 */
92 private void applySteering() {
93 boolean anyAcc = false;
94 if (!steeringOutput.linear.isZero()) {
95 Vector2 f = steeringOutput.linear;
96 rb.applyForce(f);
97 anyAcc = true;
98 }
99
100 if (anyAcc) {
101 Vector2 vel = rb.getVelocity();
102 float speed = vel.len2();
103 if (speed > attributes.maxSpd * attributes.maxSpd) {
104 rb.setVelocity(vel.scl(attributes.maxSpd / (float) Math.sqrt(speed)));
105 }
106 }
107 }
108
109 /**
110 * Stops all motion
111 */
112 public void stop() {
113 getComps();
114 rb.setVelocity(new Vector2(0, 0));
115 }
116
117 /**
118 * @return the linear velocity of the rigid body this AI is attached to
119 */
120 @Override
121 public Vector2 getLinearVelocity() {
122 getComps();
123 return rb.getVelocity();
124 }
125
126 /**
127 * @return the angular velocity of the rigid body this AI is attached to
128 */
129 @Override
130 public float getAngularVelocity() {
131 getComps();
132 return rb.getAngularVelocity();
133 }
134
135 /**
136 * @return the bounding radius of the AI's area
137 */
138 @Override
139 public float getBoundingRadius() {
140 return attributes.boundingRadius;
141 }
142
143 /**
144 * @return whether the AI has been tagged
145 */
146 @Override
147 public boolean isTagged() {
148 return attributes.isTagged;
149 }
150
151 /**
152 * @param tagged the boolean to set the tagged status to
153 */
154 @Override
155 public void setTagged(boolean tagged) {
156 attributes.isTagged = tagged;
157 }
158
159 /**
160 * @return the Zero Linear Speed Threshold `unused`
161 */
162 @Override
163 public float getZeroLinearSpeedThreshold() {
164 return 0.01f;
165 }
166
167 /**
168 * @param value the float to set the Zero Linear Speed Threshold to `unused`
169 */
170 @Override
171 public void setZeroLinearSpeedThreshold(float value) {}
172
173 /**
174 * @return the maximum Linear Speed
175 */
176 @Override
177 public float getMaxLinearSpeed() {
178 return attributes.maxSpd;
179 }
180
181 /**
182 * @param maxLinearSpeed the float to set the maximum Linear Speed to
183 */
184 @Override
185 public void setMaxLinearSpeed(float maxLinearSpeed) {
186 attributes.maxSpd = maxLinearSpeed;
187 }
188
189 /**
190 * @return the maximum Linear Acceleration
191 */
192 @Override
193 public float getMaxLinearAcceleration() {
194 return attributes.maxAcc;
195 }
196
197 /**
198 * @param maxLinearAcceleration the float to set the maximum Linear Acceleration to
199 */
200 @Override
201 public void setMaxLinearAcceleration(float maxLinearAcceleration) {
202 attributes.maxAcc = maxLinearAcceleration;
203 }
204
205 /**
206 * @return the maximum Angular Speed
207 */
208 @Override
209 public float getMaxAngularSpeed() {
210 return attributes.maxAngSpd;
211 }
212
213 /**
214 * @param maxAngularSpeed the float to set the maximum Angular Speed to
215 */
216 @Override
217 public void setMaxAngularSpeed(float maxAngularSpeed) {
218 attributes.maxAngSpd = maxAngularSpeed;
219 }
220
221 /**
222 * @return the maximum Angular Acceleration
223 */
224 @Override
225 public float getMaxAngularAcceleration() {
226 return attributes.maxAngAcc;
227 }
228
229 /**
230 * @param maxAngularAcceleration the float to set the maximum Angular Acceleration to
231 */
232 @Override
233 public void setMaxAngularAcceleration(float maxAngularAcceleration) {
234 attributes.maxAngAcc = maxAngularAcceleration;
235 }
236
237 /**
238 * @return the position of the AI
239 */
240 @Override
241 public Vector2 getPosition() {
242 getComps();
243 return t.getPosition();
244 }
245
246 /**
247 * @return the orientation of the AI
248 */
249 @Override
250 public float getOrientation() {
251 getComps();
252 return t.getRotation();
253 }
254
255 /**
256 * @param orientation the float to set the orientation to `unused`
257 */
258 @Override
259 public void setOrientation(float orientation) {}
260
261 /**
262 * @param vector the vector to be converted
263 * @return the parsed vector as an angle
264 */
265 @Override
266 public float vectorToAngle(Vector2 vector) {
267 return Utilities.vectorToAngle(vector);
268 }
269
270 /**
271 * @param angle the angle to be converted
272 * @return the parsed angle as a vector
273 */
274 @Override
275 public Vector2 angleToVector(Vector2 outVector, float angle) {
276 return Utilities.angleToVector(outVector, angle);
277 }
278
279 /**
280 * @return an empty location
281 */
282 @Override
283 public Location<Vector2> newLocation() {
284 getComps();
285 return t;
286 }
287 }