FPS Character Control Problem

  1. In the following FPS PlayerCharacterNode code,



    [java] if (left) { walkDirection.addLocal(camLeft); }

    if (right) { walkDirection.addLocal(camLeft.negate()); }

    if (up) { walkDirection.addLocal(camDir); }

    if (down) { walkDirection.addLocal(camDir.negate()); }

    [/java]



    if i face down(at me feet), and press downkey, then character starts going up(starts flying).Same thing happens when I am facing up and press up key…the character starts flying.So, the movement is always with respect to the Cam direction.



    What I have to do to make him stick to the ground?If I face to my feet , then pressing downkey will move the character back, not up.


  2. How do I make a character stick with moving platform?



    Can both of this problem solved by, adding a physics property(Constant downward force) to make it stay on the ground(except jump), and to sticking with the moving platform.



    I am new with both java and jmonkey, so some sample code will help a lot.

After lot of pain I made out of the first problem,



Just changing the last two line makes it work perfectly



[java]if (up) { walkDirection = new Vector3f(cam.getDirection().getX(),0,cam.getDirection().getZ()); }

if (down) { walkDirection = new Vector3f(-cam.getDirection().getX(),0,-cam.getDirection().getZ()); } [/java]



Now the character dont fly around according to the camera dircetion.Perfect FPS character control.



I suggest to make this modification to the tutorials.



But, I am still stuck with the second problem.How can I stick a PhysicsCharacterControl to a moving platform.

1 Like

You cant. You will have to move it accordingly. Or use a “real” physicsnode.

the first problem, when you look down and fly up is because you still have the flyCam enabled. Turn of the flyCam by.



[java] flyCam.setEnabled(false);[/java]



Of course now you will notice some of your camera properties are gone, you will want to use a different camera type. Take a look at chaseCam, it is defined and used a lot in the TestWalkingChar.java Example.



For the second problem of sticking the character onto a platform, I would try using collision detection. If your player hits/collides with the moving platform (basically jumped on top of it, also might want to check if local y of player is >= local y of platform) then set the local translation of the player equal to the platform. What I just described for the platform isn’t the ideal way to do it in all cases but it might give you a few ideas

No, its not the FlyCam moving the character upwards, his “fix” is fine.

I don’t want to start an argument, but if you have the fly cam enabled you realize when he pushes W,A,S,D it also maneuvers the flycam as well as his player direction. The following code is from the flyCam class. Now I could be totally wrong about this question but I am assuming he is extending simpleApplication and hasn’t changed the default keys for movement W,A,S,D. That would mean on keypress he is executing his code for “up” and “down” as well as the flyCam classes “FLYCAM_Forward” and “FLYCAM_Backward”. Also if he is using the PhysicsCharacterNode it is safe to assume he is using the bullet physics which means he shouldn’t be flying up at all because of gravity (when using the default walking code).



Flycam input if enabled.

[java] if (!enabled)

return; if (name.equals(“FLYCAM_Left”)){

rotateCamera(value, initialUpVec);

}else if (name.equals(“FLYCAM_Right”)){

rotateCamera(-value, initialUpVec);

}else if (name.equals(“FLYCAM_Up”)){

rotateCamera(-value, cam.getLeft());

}else if (name.equals(“FLYCAM_Down”)){

rotateCamera(value, cam.getLeft());

}else if (name.equals(“FLYCAM_Forward”)){

moveCamera(value, false);[/java]



The TestWalkingChar example uses the chasecam to portray a 3rd person view. He could use the chaseCam and set the location to characters location and height to try and give it a 1st person view if he desired. Or if he needs a custom camera he could make his own camera class and extend from either of those cameras and override functionality he wants to change.

Also if he is using the PhysicsCharacterNode it is safe to assume he is using the bullet physics which means he shouldn’t be flying up at all because of gravity (when using the default walking code).


Here was the actual problem, these following codes totally overrides the physics system.The gravity or anything else dont take place while these statements are updating, the PhysicsCharacterNode's position.


if (up) { walkDirection.addLocal(camDir); }
if (down) { walkDirection.addLocal(camDir.negate());

if (up) { walkDirection = new Vector3f(cam.getDirection().getX(),0,cam.getDirection().getZ()); }
if (down) { walkDirection = new Vector3f(-cam.getDirection().getX(),0,-cam.getDirection().getZ()); }


These is very similar to, other physics nodes.If you use, the move or rotate function on them, inside the update method, the gravity mass etc etc stuff just stops working on that node.
scrubalub said:
I don't want to start an argument, but if you have the fly cam enabled you realize when he pushes W,A,S,D it also maneuvers the flycam as well as his player direction. The following code is from the flyCam class. Now I could be totally wrong about this question but I am assuming he is extending simpleApplication and hasn't changed the default keys for movement W,A,S,D. That would mean on keypress he is executing his code for "up" and "down" as well as the flyCam classes "FLYCAM_Forward" and "FLYCAM_Backward". Also if he is using the PhysicsCharacterNode it is safe to assume he is using the bullet physics which means he shouldn't be flying up at all because of gravity (when using the default walking code).

Believe me, I have written the physics adaptation ;)
The flyCam only gives the direction, the movement of the flyCam is reset by syncing the cam location with the bullet character node. But the character node *will* start to "fly" when you set the walkDirection vector upwards and make it big enough so that it surpasses the gravity. So the solution is exactly right, simply remove the y component of the cam direction and apply that as the walkDirection. I would suggest normalizing the vector afterwards using .normalizeLocal(); to avoid slower movement when looking up or down.

Cheers,
Normen
I would suggest normalizing the vector afterwards using .normalizeLocal(); to avoid slower movement when looking up or down.

what does normalizeLocal() do?

What is the difference between normalize() and normalizeLocal() ? I dont understand clearly from the doc.

Is there any documentation of jMoneky3 like JavaDoc, that I can browse in the browser?

It brings the length of the vector to 1. normalizeLocal changes the Vector3f object directly while normalize returns a new one with the new values.

[java]if (left) { walkDirection = cam.getLeft().mult(.235f);}

if (right) { walkDirection = cam.getLeft().negate().mult(.235f); }

if (up) { walkDirection = new Vector3f(cam.getDirection().getX(),0,cam.getDirection().getZ()).mult(.5f); }

if (down) { walkDirection = new Vector3f(-cam.getDirection().getX(),0,-cam.getDirection().getZ()).mult(.5f); }



playerPhysicsNode.setWalkDirection(walkDirection.normalizeLocal());[/java]



Is this what I should do?



If I use normalize/normalizeLocal, the speed of the character increases, and also the speed variation(.235 & .5) is lost.


normalizeLocal changes the Vector3f object directly while normalize returns a new one with the new values.


Doesn't both method return vector of unit length, while retaining the original direction.What is the reason of creating a new one, when the outcome is same?

The outcome is not the same. If you get the same vector or a new one, thats a completely different thing. If you got the Vector3f from something like getLocalTranslation() and then do normalizeLocal() you could actually change the Spatials location because that Vector3f is used by the scenegraph to locate the Spatial. On the other hand when you create a new Vector and then perform some operation on it theres no need to make a new Vector3f each time.



Use normalizeLocal like this in your code:

[java]

if (left) { walkDirection = cam.getLeft().mult(.235f);}

if (right) { walkDirection = cam.getLeft().negate().normalizeLocal().multLocal(.235f); }

if (up) { walkDirection = new Vector3f(cam.getDirection().getX(),0,cam.getDirection().getZ()).normalizeLocal().multLocal(.5f); }

if (down) { walkDirection = new Vector3f(-cam.getDirection().getX(),0,-cam.getDirection().getZ()).normalizeLocal().multLocal(.5f); }



playerPhysicsNode.setWalkDirection(walkDirection);

[/java]

Also you should probably remove the new Vector and replace it with a global variable to not produce too much garbage for the garbage collector.

1 Like