Hello there,
i am currently working on a project called “SpaceFight”. It’s a space shooter game with a gameplay-style like X-Wing vs. Tie-Fighter.
It’s making good progress as everything works pretty good. But I have a problem regarding AI turning to a target:
This is how the ships are controlled:
- RigidBodyControl is used to apply physics to the spaceships.
- Custom "FlightControl" keeps data like Top-Speed, Linear brake strength, Acceleration etc. and manipulates physics regarding to core values (elevator, aileron, rudder). It takes values from -1f to 1f.
- Then a custom "PlayerControl" or "AIControl" manipulates the FlightControl's parameters to turn and fly towards targets
Up to now I was using "cheating" AI which just used Quaternions and "slerp" to turn the ship's Node directly in World space. Some reasons I want to change this:
- I consider the AI "cheating" because they directly manipulate the node.
- It breaks the workflow described above
- It has side-effects on physics (rotations from collisions are overwritten by AI inputs)
- Since I switched to multithreaded BulletAppState and Native bullet i've got serious problems with velocities when constantly modifying physicsRotation directly
So far here is the code I use to determine where the AI has to steer:
[java]
private Vector3f getSteeringData(Vector3f worldPosition, Vector3f up) {
Vector3f steeringPosition = new Vector3f();
getSpatial().getWorldRotation().inverse().multLocal(steeringPosition.set(worldPosition).subtractLocal(getSpatial().getWorldTranslation()));
Quaternion targetRotation = new Quaternion();
targetRotation.lookAt(steeringPosition, up);
Vector3f steeringData = new Vector3f();
float[] angles = targetRotation.toAngles(null);
steeringData.x = angles[0] / (FastMath.pow(flightControl.getTurnrate(), 2) / (2 * flightControl.getAngulardamp()));
steeringData.y = angles[1] / (FastMath.pow(flightControl.getTurnrate(), 2) / (2 * flightControl.getAngulardamp()));
steeringData.z = angles[2] / (FastMath.pow(flightControl.getTurnrate(), 2) / (2 * flightControl.getAngulardamp()));
return steeringData;
}
[/java]
Application to FlightControl works like this:
[java]
Vector3f steeringData = getSteeringData(position, up);
flightControl.setElevator(steeringData.x);
flightControl.setRudder(steeringData.y);
flightControl.setAileron(steeringData.z);
[/java]
Currently the code to determine the elevator, rudder and aileron values (from -1 to 1) is temporary...
It somewhat works but sometimes ships just start flying wild circles...
It would be very great if someone could point me into the right direction on how to calculate that correctly with angular values...
Greetings
P.S.: I am aware that the code above is not optimal... But if you got a tip for me how I can make it better you're welcome.
P.P.S: Here are some Screenshots of the project: