Correct input handling

Hi,



After several tests with the just corrected physics setup I realized that my input handling is more than broken.



My general setup:

I have a control named ManualControl that extends AbstractControl. It’s meant to move a spatial (e.g. the player) according to user input.

In this control there are two custom Analoglisteners:

one for keyinput → movement

one for mouseinput → looking around.

Whenever onAnalog is called in one of the listeners a variable is in- or decreased.

This works as follows:

[java]if(name==“moveForward”)forward+=value;[/java]

and

[java]if(name==“mouseUp”)mousey+=value;[/java]

In total there are four variables that store the input: forward, side, mousex, mousey

Moreover I got a couple of vectors: one for the walkdirection, one for the viewdirection, one for the direction to the left.

Now all there is to do is to update the vectors and use a CharacterControl to actually move the spatial… At least in theory.

After I saw the strange behaviour I stripped the control of its dependance of any physics and relied solely on the move and lookat function of my spatial. To respond to the input I use controlUpdate. Here’s some code:



[java]protected void controlUpdate(float tpf) {

if(mousex!=0||mousey!=0){

Vector3f viewoffset=new Vector3f(mousex,mousey,0);

lookdir.addLocal(viewoffset);

lookdir.normalizeLocal();

//player.setViewDirection(lookdir);



//restrict walking to the x,z plane

walkdir.set(lookdir.x,0,lookdir.z);

walkdir.normalizeLocal();

leftdir=ROTATE_90.mult(walkdir);



spatial.lookAt(spatial.getLocalTranslation().add(lookdir), Vector3f.UNIT_Y);

}

mousex=0;

mousey=0;



forward*=tpf;

side*=tpf;

if(forward!=0||side!=0){

//player.setWalkDirection(walkdir.mult(forward).add(leftdir.mult(side)).normalize().mult(walkspeed));

spatial.move(walkdir.mult(forward).add(leftdir.mult(side)).normalize().mult(walkspeed).mult(tpf));

}

else{

//player.setWalkDirection(Vector3f.ZERO);

}

forward=0;

side=0;

}[/java]



As you can see I change the viewdirection not by rotating but by adding an offset vector in the new direction. Actually I started with Quaternions to rotate the viewdir vector. Converting to an offset vector didn’t solve the problem but also didn’t make it any worse. After the rotation the mousex and mousey variables are set to 0.

Then the spatial itself is rotated and moved.

Finally forward and side are set to 0.



The problem is as follows:

The rotation is not considered, this means that although the spatial is moved, it is always moved in the same directions. With Quaternions for rotation the spatial quivers and shakes violently but at least responds to the mouse. I tried multiplying the mousex and mousey variables with 0.1 and even 0.01 to reduce the effect and prevent the strong shaking but it didn’t work



What can I do to fix the problem. How would you implement something like this ?

Maybe you don’t consider that when you rotate and then subtract some direction vector that it now points to a different location and thus you do not “reverse” the previous direction? Anyway theres a lot of code in terms of movement etc. in MonkeyZone, I suggest you take a look at that:

http://monkeyzone.googlecode.com/

1 Like

I don’t now what you mean. To rotate the viewdirection I add a small vector that points is based on the mouse movement and normalize the new viewdirection. The idea is that whenever the mouse is moved the viewdirection is moved too. I had a script in Unity which implemented movement like this. It always worked very reliable therefore I restructured my control like this when there where problems. I certainly don’t rotate and add at the same time.



However. I’ve looked at monkeyzone again. I liked the way you use different controls to listen to input and move the spatial. I was also impressed by the idea to abstract over manualcontrol and implement manualcharactercontrol and manualvehiclecontrol differently. Nevertheless I still have only one script that heavily resembles your code and is boiled together from the various monkeyzone controls. The movement now almost works. There’s still a strange flaw:



When moving backwards the spatial lifts off the ground. This is surprising as the control only uses charactercontrol.setWalkDirection to move the spatial.



Moreover: Although the manualcharactercontrol from monkeyzone is pretty straightforward I would have preferred a different approach and would not have tried this version on my own. There are so many different ways to rotate something I just never tried fromAngleAxis. Can you tell me the problem with my code ? Is fromAngleAxis the only advisable possibility or can I do it my way ?

You would have to maintain the rotation angles yourself if you want to keep track of the euler angles, but then you’d have to care yourself for limiting the rotation amount to 360 degrees to prevent overflows and inaccuracies etc. Thats why the quaternion is being used for all of this, it allows efficient matrix-like manipulations. Just rotate your vector using a quaternion instead of adding another one, the way you do this doesn’t really make sense. Think about it: even when the mouse movement is quick, your direction can never be over 90 degrees… The issue with your code is what I tried to explain in the first post: You first rotate the spatial using the input and then move it locally using the same directions. This way you apply them twice in different directions.

1 Like

I looked at my code again and figured out that you’re right. I’ll use quaternions from now on.



Do you have any idea why the spatial lifts from the ground when moving backwards ?



UPDATE:

The spatial lifts from the ground not only when moving backward but also when moving forward provided that the viewdirection points upwards. What’s going on there ? I thought setWalkDirection was meant for walking on the ground, not flying.

I’m very confused now. After I tried my luck with this workaround

[java]walkDirection.set(new Vector3f(walkDirection.x,0,walkDirection.z));[/java]

I thought the movement was a little rough and deleted the line.

Now everything works fine. Even without the line the spatial stays on the ground.

Seriously, what has happened ?

Anybody ?