Camera rotation, first person

I'm developing a first person game, but I want to rotate the mouse and walk with W towards the object facing angle (Sorry could not explain better). So, here is my curently code of update method:


            public void update(float tpf) {
                super.update(tpf);

                if(input != null) input = null;
                cam.getLocation().set(character.getLocalTranslation().add(new Vector3f(0, 1.7f, 0)));
                cam.setAxes(character.getLocalRotation());

                pSpace.update(tpf);
            }



I want to implement now, in StandardGame, the mouselook for first person. like, when I rotate my mouse X_AXIS for +, the object angle just increase, so when it update it rotate the camera properly (Sorry could not explain better, too). I really need help with this thing.

Regards, Gustavo Borba.

Please help me! I'm waiting for the answer!

This is the code i use to control the rotation of my spaceship around all 3 axis



Its part of my playership class and derived from Node.





// factor how fast the ship can turn left or right in radians per second
private float fTurnSpeed = 1.0f;
private final Quaternion deltaRotation = new Quaternion();

// The node from where the camera "looks" - normally assigned to the ship
private CameraNode camNode;

void initCam()
{
      // Attach the cam to the player ship
      camNode = new CameraNode( "CAMNODE", display.getRenderer().getCamera());
      camNode.setLocalTranslation(0, 0, 0);
      camNode.updateWorldData(0);
      this.attachChild(camNode);
}


    /**
     * Used to change the rotation by applying an angle over time
     * @param fHAngle the angle to turn (left/right)
     * @param fVAngle the angle to turn (up/down)
     * @param fRollAngle the angle to roll (around the Z axis)
     * @param tpf time elapsed
     */      
   public void rotate(float fHAngle, float fVAngle, float fRollAngle, float tpf)
   {            
      fHAngle = (fTurnSpeed * tpf * fHAngle);
      fVAngle = (fTurnSpeed * tpf * fVAngle);
      fRollAngle = (fTurnSpeed * tpf * fRollAngle);
                                                                  
      // now do the new rotation
      deltaRotation.fromAngles(fVAngle, fHAngle, fRollAngle);
      this.getLocalRotation().multLocal(deltaRotation);               
   }   


I think the rotate method is called on update()? isn't it? Can you show me the update() if it is updated on there?

And one thing… where the mouse input gets in?



Regards, Gustavo Borba.

Have a look at FirstPersonHandler, that can take care of many of your looking around and movement needs.

Yeah, already looked at it, but FirstPersonHandler does not implements physics, I'm already using a CharacterNode from jme-bullet. I just need a mouse handler, like, when I mouse the mouse, it rotates the CharacterNode, and when it the game updates, change the camera view. Example: Grappling Hook's first person camera.

As far as i know there are two very different ways to handle input:

InputControl: you poll during update

InputHandler: you get called (listeners) on input event



I am using InputControl, but i dont use the mouse (only keyboard and joystick)



I post my code nevertheless, maybe it helps you

(look for MouseAxisBinding or so in jme, its not in my code)



To activate the following class

rootNode.addController(new PlayerController(playerNode));



package descented.input;


import java.beans.XMLEncoder;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.logging.Logger;

import org.lwjgl.input.Controllers;

import com.jme.input.InputSystem;
import com.jme.input.controls.GameControl;
import com.jme.input.controls.GameControlManager;
import com.jme.input.controls.binding.JoystickAxisBinding;
import com.jme.input.controls.binding.JoystickButtonBinding;
import com.jme.input.controls.binding.KeyboardBinding;
import com.jme.input.controls.binding.MouseButtonBinding;
import com.jme.input.joystick.Joystick;
import com.jme.input.joystick.JoystickInput;
import com.jme.math.Vector3f;
import com.jme.scene.Controller;
import com.jme.scene.Node;
import com.jme.system.GameSettings;

import descented.game.PlayerShip;

import static descented.input.PlayerController.PlayerAction.*;
import static com.jme.input.KeyInput.*;
import static com.jme.input.controls.binding.MouseButtonBinding.*;
 
/**
 * 
 * Controls the players input with keyboard and joystick (if any)
 * @author larynx
 *
 */
public class PlayerController extends Controller
{
    private static final long serialVersionUID = 1L;
    private static final Logger logger = Logger.getLogger(PlayerController.class.getName());
 
   
   enum PlayerAction {   TURNLEFTKEY, TURNRIGHTKEY, TURNUPKEY, TURNDOWNKEY,
                  TURNLEFTJOYSTICK, TURNRIGHTJOYSTICK, TURNUPJOYSTICK, TURNDOWNJOYSTICK,
                  MOVEFORWARDKEY, MOVEBACKWARDKEY,
                  MOVEFORWARDJOYSTICK, MOVEBACKWARDJOYSTICK,
                  STRAFELEFTKEY, STRAFERIGHTKEY, STRAFEUPKEY, STRAFEDOWNKEY,
                  STRAFELEFTJOYSTICK, STRAFERIGHTJOYSTICK, STRAFEUPJOYSTICK, STRAFEDOWNJOYSTICK,
                  FIREPRIMARY, FIRESECONDARY,
                  EXIT, SHOWLOCATION};
 
    private final static float SPEED = 1F;
 
    private final PlayerShip playerShip;
    private final InputControlManager manager;
   
    private static Vector3f acceleration = new Vector3f();
   
    // temporary vector for translation/rotation
    private static final Vector3f tempVShipDirection = new Vector3f();
   
     /**
      * Reads the keyboard and joystock to control the player ship
      * @param playerShip the player ship to adjust acceleration and rotation for
      */
    public PlayerController(PlayerShip playerShip)
    {
        this.playerShip = playerShip;
        this.manager = new InputControlManager();
        
        // create all actions
        for (PlayerAction action : PlayerAction.values()) {
            manager.addControl(action.name());
        }
        //bind keys
        // TODO: read from config file
        //bindKey(EXIT, KEY_X);
        bindKey(TURNLEFTKEY, KEY_LEFT);      
        bindKey(TURNRIGHTKEY, KEY_RIGHT);
        bindKey(TURNUPKEY, KEY_UP);
        bindKey(TURNDOWNKEY, KEY_DOWN);
       
        bindKey(STRAFELEFTKEY, KEY_S);
        bindKey(STRAFERIGHTKEY, KEY_D);
        bindKey(STRAFEUPKEY, KEY_W);
        bindKey(STRAFEDOWNKEY, KEY_X);
       
        bindKey(MOVEFORWARDKEY, KEY_A);
        bindKey(MOVEBACKWARDKEY, KEY_Y);
       
        bindKey(FIREPRIMARY, KEY_SPACE);
        bindKey(FIRESECONDARY, KEY_RCONTROL);
        bindKey(SHOWLOCATION, KEY_L);
 
        //bind mouse buttons
        //bindMouseButton(LEFT, LEFT_BUTTON);
        //bindMouseButton(RIGHT, RIGHT_BUTTON);
       
        // enable and bind joystick, take the first joystick if there is any
        // TODO: get the joystick from the settings
      if (JoystickInput.get().getJoystickCount() > 0)
      {
         logger.info("** INPUT **");
         Joystick joystick = JoystickInput.get().getJoystick(0);
         logger.info("Using joystick 0, " + joystick.getName());         
         String[] asAxisNames = joystick.getAxisNames();
         for (int i = 0; i < asAxisNames.length; i++)
           {          
              logger.info("Axis " + i + ", " + asAxisNames[i]);
           }
         logger.info("** END OF INPUT **");
         // axis 3, left analog left-right
         // axis 4, left analog up-down         
         // axis 5, right analog left-right
         // axis 6, right analog up-down
         // axis 10-14 left arrow buttons
         // button 8 - L2
         // button 9 - R2
         // button 10 - L1
         // button 11 - R1
         
         bindJoystickAxis(TURNLEFTJOYSTICK, joystick, 5 /*axis*/, false /*reverse*/);
         bindJoystickAxis(TURNRIGHTJOYSTICK, joystick, 5 /*axis*/, true /*reverse*/);
         bindJoystickAxis(TURNUPJOYSTICK, joystick, 6 /*axis*/, false /*reverse*/);
         bindJoystickAxis(TURNDOWNJOYSTICK, joystick, 6 /*axis*/, true /*reverse*/);

         bindJoystickAxis(STRAFELEFTJOYSTICK, joystick, 3 /*axis*/, false /*reverse*/);
         bindJoystickAxis(STRAFERIGHTJOYSTICK, joystick, 3 /*axis*/, true /*reverse*/);
         bindJoystickAxis(STRAFEUPJOYSTICK, joystick, 4 /*axis*/, false /*reverse*/);
         bindJoystickAxis(STRAFEDOWNJOYSTICK, joystick, 4 /*axis*/, true /*reverse*/);
         
         bindJoystickButton(MOVEFORWARDJOYSTICK, joystick, 10);   // button 10 - L1
         bindJoystickButton(MOVEBACKWARDKEY, joystick, 8);      // button 8 - L2            
         
         bindJoystickButton(FIREPRIMARY, joystick, 11);         // button 11 - R1
         bindJoystickButton(FIRESECONDARY, joystick, 9);         // button 9 - R2
      }
      
        //com.jme.system.PropertiesGameSettings pgs = new com.jme.system.PropertiesGameSettings("input.properties");
        //pgs.load();
      //GameControlManager.save(manager, pgs);
      
      //manager.save();
      

    }
 
 
    private void bindKey(PlayerAction action, int... keys) {
        final GameControl control = manager.getControl(action.name());
        for (int key : keys) {
          control.addBinding(new KeyboardBinding(key));
        }
    }
 
    private void bindMouseButton(PlayerAction action, int mouseButton) {
        final GameControl control = manager.getControl(action.name());
        control.addBinding(new MouseButtonBinding(mouseButton));
    }
 
    /**
     * Bind the joystick axis
     */
    private void bindJoystickAxis(PlayerAction action, Joystick joystick, int axis, boolean reverse)
    {
        final GameControl control = manager.getControl(action.name());
        control.addBinding(new JoystickAxisBinding(joystick, axis, reverse));
    }
 
    /**
     * Bind the joystick buttons
     */
    private void bindJoystickButton(PlayerAction action, Joystick joystick, int button)
    {
        final GameControl control = manager.getControl(action.name());
        control.addBinding(new JoystickButtonBinding(joystick, button));
    }
   
   
    private float value(PlayerAction action) {
        return manager.getControl(action.name()).getValue();
    }
 
    @Override
    public void update(float time)
    {
       
       
       //if (value(EXIT) > 0) {
        //    System.exit(0); //OK, this is just a demo...
        //}
       
        // Set the rotation       
        playerShip.rotate((value(TURNRIGHTJOYSTICK) - value(TURNLEFTJOYSTICK)) + (value(TURNLEFTKEY) - value(TURNRIGHTKEY)),
                      (value(TURNDOWNJOYSTICK) - value(TURNUPJOYSTICK)) + (value(TURNUPKEY) - value(TURNDOWNKEY)), 0f, time);
       
       
        // Apply velocity from keyboard
        acceleration.set(value(STRAFELEFTKEY) - value(STRAFERIGHTKEY),
                     value(STRAFEUPKEY) - value(STRAFEDOWNKEY),
                     value(MOVEFORWARDKEY) - value(MOVEBACKWARDKEY));

        // Add to velocity from joystick
        acceleration.addLocal(value(STRAFERIGHTJOYSTICK) - value(STRAFELEFTJOYSTICK),
                          value(STRAFEDOWNJOYSTICK) - value(STRAFEUPJOYSTICK),
                          value(MOVEFORWARDJOYSTICK) - value(MOVEBACKWARDJOYSTICK));
       
        // Update the playership velocity
       playerShip.accelerate(acceleration, time);
       

       // Fire weapons
       if (value(FIREPRIMARY) > 0)
       {
          // Issue fire command, the playership will determine if it is possible (max fire rate, aso)
          playerShip.firePrimary();
          //logger.info("isButtonPressed(11) " + Controllers.getController(0).isButtonPressed(11));
       }
       // Fire weapons
       if (value(FIRESECONDARY) > 0)
       {
          // Issue fire command, the playership will determine if it is possible (max fire rate, aso)
          playerShip.fireSecondary();
       }

       
       if (value(SHOWLOCATION) > 0)
       {
          logger.info("Player local location: " + playerShip.getLocalTranslation());
          logger.info("Player world location: " + playerShip.getWorldTranslation());
          float[] angles = new float[3];
          playerShip.getLocalRotation().toAngles(angles);
          logger.info("Player rotation: " + angles[0] + "," + angles[1] + "," + angles[2]);
       }       
    }
}