# Problem with linear Velocity and linear Damping

Hey monkeys,

I try to write helicopter flight program. The helicopter shoud collide and accelerate with WASD into the chosen direction. Rotation around Y-axis and the UP/DOWN movement is realized with the arrow keys. The helicopter is build with 3 spatials. Body, mainrotor and rearrotor. These three spatials are attached to one “PlayerNode”. PlayerNode has a RigidBodyControl so the acceleration works with the setLinearVelocity(). If the key, which was pressed, is released, the model is flying into the last chosen direction. For that I use the setLinearDamping(). It slows down and stands on one place.

Now my problem. If I press a key into another direction the model “jumps” in the old direction and after that it accelerates into the new direction. For example: W is pressed for forward. W is released, heli slows down. S is pressed for backward. heli jumps forward, slows down and accelerates backwards. How can I avoid this jump?

Here is my steering code:

public class KeyBehavior implements ActionListener,AnalogListener{
static boolean forward, backward, leftward,rightward,upward,downward, rotateR, rotateL = false;
static float speed;
static boolean Engine;
static final Quaternion DEG1dot25p   = new Quaternion().fromAngleAxis(FastMath.PI/144,   new Vector3f(0,1,0));
static final Quaternion DEG1dot25m   = new Quaternion().fromAngleAxis(-FastMath.PI/144,   new Vector3f(0,1,0));

static Vector3f walkdir;
Camera cam;
InputManager inputManager;
static Vector3f xAxisMovement;
static Vector3f yAxisMovement;
static Vector3f zAxisMovement;

public KeyBehavior(InputManager inputManager, Camera cam){
this.cam = cam;
this.inputManager = inputManager;
walkdir=new Vector3f();
setupKeys();
speed = 0.5f;
}

private void setupKeys() {

}

public void onAction(String binding, boolean value, float tpf) {
System.out.println(binding);

/**
* Helicoptermovement
*/
if(TerrainFlight3D.player){
if(Player.PlayerNode.getName().equals("HELICOPTER")){
if (binding.equals("Reset")) {
if (value) {
System.out.println("Reset");
Player.FlyControl.setPhysicsLocation(Vector3f.ZERO);
Player.FlyControl.setPhysicsRotation(new Matrix3f());
Player.FlyControl.setLinearVelocity(Vector3f.ZERO);
Player.FlyControl.setAngularVelocity(Vector3f.ZERO);
}
} else if (binding.equals("Engine") && !value ) {
if(!Engine && (AudioEffects.audio_helicopter_stop.getStatus() == AudioSource.Status.Stopped)){
System.out.println("Start Engine");
Engine = true;
AudioEffects.audio_helicopter_start.play();
} else if ((AudioEffects.audio_helicopter_fly.getStatus() == AudioSource.Status.Playing)){
System.out.println("Stop Engine");
AudioEffects.audio_helicopter_start.stop();
AudioEffects.audio_helicopter_fly.stop();
AudioEffects.audio_helicopter_stop.play();
Engine = false;
}
}

if (binding.equals("Left")) {
if (value) {
leftward = true;
}
else {
leftward = false;
}
} else if (binding.equals("Right")) {
if (value) {
rightward = true;
} else {
rightward = false;
}
} else if (binding.equals("Forward")) {
if (value) {
forward = true;

} else {
forward = false;

}
} else if (binding.equals("Backward")) {
if (value) {
backward = true;

} else {
backward = false;

}
} else if (binding.equals("Up") ) {
System.out.println(binding);
if (value) {
upward = true;
} else {
upward = false;
}
} else if (binding.equals("Down") ) {
System.out.println(binding);
if (value) {
downward = true;

} else {
downward = false;

}
}

}
if (binding.equals("Camera") && !value ){
if (Player.FPC){
System.out.println("Chase Camera");
Player.camNode.setEnabled(false);
Player.chaseCam.setEnabled(true);
Player.FPC = false;
}
else if (!Player.FPC){
System.out.println("3rd-Person Camera");
Player.chaseCam.setEnabled(false);
Player.camNode.setEnabled(true);
Player.FPC = true;
}
}
}

}

public void onAnalog(String binding, float value, float tpf) {
if(TerrainFlight3D.player){
if(Player.PlayerNode.getName().equals("HELICOPTER")){
xAxisMovement = Player.FlyControl.getPhysicsRotation().getRotationColumn(0).mult(speed);
yAxisMovement = Player.FlyControl.getPhysicsRotation().getRotationColumn(1).mult(speed/2);
zAxisMovement = Player.FlyControl.getPhysicsRotation().getRotationColumn(2).mult(speed);

if (binding.equals("RotLeft")) {
System.out.println(binding);
Player.FlyControl.setPhysicsRotation(Player.FlyControl.getPhysicsRotation().mult(DEG1dot25p));
} else if (binding.equals("RotRight")) {
System.out.println(binding);
Player.FlyControl.setPhysicsRotation(Player.FlyControl.getPhysicsRotation().mult(DEG1dot25m));
}

if (binding.equals("Left")) {
if (leftward) {
walkdir = new Vector3f(walkdir.x-xAxisMovement.x, walkdir.y-xAxisMovement.y, walkdir.z-xAxisMovement.z);
} else {
walkdir = new Vector3f(walkdir.x+xAxisMovement.x, walkdir.y+xAxisMovement.y, walkdir.z+xAxisMovement.z);
}
} else if (binding.equals("Right")) {
if (rightward) {
walkdir = new Vector3f(walkdir.x+xAxisMovement.x, walkdir.y+xAxisMovement.y, walkdir.z+xAxisMovement.z);
} else {
walkdir = new Vector3f(walkdir.x-xAxisMovement.x, walkdir.y-xAxisMovement.y, walkdir.z-xAxisMovement.z);
}
}

if (binding.equals("Forward")) {
if (forward) {
walkdir = new Vector3f(walkdir.x-zAxisMovement.x, walkdir.y-zAxisMovement.y, walkdir.z-zAxisMovement.z);
} else {
walkdir = new Vector3f(walkdir.x+zAxisMovement.x, walkdir.y+zAxisMovement.y, walkdir.z+zAxisMovement.z);
}
} else if (binding.equals("Backward")) {
if (backward) {
walkdir = new Vector3f(walkdir.x+zAxisMovement.x, walkdir.y+zAxisMovement.y, walkdir.z+zAxisMovement.z);
} else {
walkdir = new Vector3f(walkdir.x-zAxisMovement.x, walkdir.y-zAxisMovement.y, walkdir.z-zAxisMovement.z);
}
}

if (binding.equals("Down") ) {
if (downward) {
walkdir = new Vector3f(walkdir.x-yAxisMovement.x, walkdir.y-yAxisMovement.y, walkdir.z-yAxisMovement.z);
} else {
walkdir = new Vector3f(walkdir.x+yAxisMovement.x, walkdir.y+yAxisMovement.y, walkdir.z+yAxisMovement.z);
}
} else if (binding.equals("Up") ) {
if (upward) {
walkdir = new Vector3f(walkdir.x+yAxisMovement.x, walkdir.y+yAxisMovement.y, walkdir.z+yAxisMovement.z);
} else {
walkdir = new Vector3f(walkdir.x-yAxisMovement.x, walkdir.y-yAxisMovement.y, walkdir.z-yAxisMovement.z);
}
}

//                System.out.println("walkdir:"+walkdir);
//                System.out.println("Velocity:"+ Player.FlyControl.getLinearVelocity());
//                System.out.println("Damping:"+ Player.FlyControl.getLinearDamping());
Player.FlyControl.setLinearDamping(speed*1.9f);
Player.FlyControl.setLinearVelocity(walkdir);
}
}
}
}

and here is a video. I hope it shows my problem good enough.

You should not be using setPhysicsRotation and setLinearVelocity. Use applyTorque and applyCentralForce instead.

Here is some code I used. I was flying a phycis camera around instead, but same idea.

private AnalogListener analogListener = new AnalogListener() {
public void onAnalog(String name, float value, float tpf) {

if (name.equals("MoveLeft"))
cameraNodePhysicsControl.applyCentralForce(getCamera().getLeft().mult(linearSpeed));
if (name.equals("MoveRight"))
cameraNodePhysicsControl.applyCentralForce(getCamera().getLeft().mult(-linearSpeed));
if (name.equals("MoveForward"))
cameraNodePhysicsControl.applyCentralForce(getCamera().getDirection().mult(linearSpeed));
if (name.equals("MoveBackward"))
cameraNodePhysicsControl.applyCentralForce(getCamera().getDirection().mult(-linearSpeed));

Vector3f xRotation = cameraNodePhysicsControl.getPhysicsRotation().getRotationColumn(0).normalize();
Vector3f yRotation = cameraNodePhysicsControl.getPhysicsRotation().getRotationColumn(1).normalize();
Vector3f zRotation = cameraNodePhysicsControl.getPhysicsRotation().getRotationColumn(2).normalize();

if (name.equals("RotateLeft"))
cameraNodePhysicsControl.applyTorque(yRotation.mult(angularSpeed));
if (name.equals("RotateRight"))
cameraNodePhysicsControl.applyTorque(yRotation.mult(-angularSpeed));
if (name.equals("RotateUp"))
cameraNodePhysicsControl.applyTorque(xRotation.mult(angularSpeed));
if (name.equals("RotateDown"))
cameraNodePhysicsControl.applyTorque(xRotation.mult(-angularSpeed));
if (name.equals("SpinLeft"))
cameraNodePhysicsControl.applyTorque(zRotation.mult(-angularSpeed));
if (name.equals("SpinRight"))
cameraNodePhysicsControl.applyTorque(zRotation.mult(angularSpeed));

}
};

Ok, thank you for your idea. I’ll try to write your code to my structure. Can I replace the CameraNodePhysicsControl with my FlyControl(RigidBodyControl)? Have a nice Sunday!

Hey, thanks for this tipp. I changed my steering to applyImpulse() and when key is released I clearForces() and set my vector walkdir to zero. This is a acceptable steering for a helicopter.

Thanks for help

Greets from Germany

Taros