Hi everyone.
I’m a jMonkeyEngine beginner from Croatia, and I have a QWERTZ keyboard. Since FlyByCamera uses QWERTY, and I found this topic
[java]http://hub.jmonkeyengine.org/forum/topic/bettercharactercontrol-cameranode-how-to-make-first-person-view/[/java]
on avoiding it, I’ve decided to write a little QWERTZ FlyByCamera implementation.
Since I’m just on my first jMK tutorials, I hope you can comment / criticise / improve this solution.
Thank you!
Main.java
[java]
package mygame;
import com.jme3.app.DebugKeysAppState;
import com.jme3.app.SimpleApplication;
import com.jme3.app.StatsAppState;
import com.jme3.app.state.AppState;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
/**
-
test
-
@author normenhansen
*/
public class Main extends SimpleApplication {Vector3f camLocation;
public Main(AppState… initialStates) {
//Skipping Fly Cam
// inspired by:
//http://hub.jmonkeyengine.org/forum/topic/bettercharactercontrol-cameranode-how-to-make-first-person-view/
super(new StatsAppState(), new DebugKeysAppState());
}public static void main(String[] args) {
Main app = new Main();
app.start(); // start the game
}@Override
public void simpleInitApp() {
camLocation = new Vector3f(0f, 0f, 10f);
cam.setLocation(camLocation);
new AnalogListenerImpl(cam, inputManager);Box b = new Box(1f, 1f, 1f); Geometry geom = new Geometry("Box", b); Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); mat.setColor("Color", ColorRGBA.Blue); geom.setMaterial(mat); rootNode.attachChild(geom);
}
@Override
public void simpleUpdate(float tpf) {
//TODO: add update code
}@Override
public void simpleRender(RenderManager rm) {
//TODO: add render code
}
}
[/java]
AnalogListenerImpl
[java]
package mygame;
import com.jme3.input.InputManager;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseAxisTrigger;
import com.jme3.math.FastMath;
import com.jme3.math.Matrix3f;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
public class AnalogListenerImpl implements AnalogListener {
public static final String FLYCAM_Forward = "FLYCAM_Forward";
public static final String FLYCAM_Backward = "FLYCAM_Backward";
public static final String FLYCAM_StrafeLeft = "FLYCAM_StrafeLeft";
public static final String FLYCAM_StrafeRight = "FLYCAM_StrafeRight";
public static final String FLYCAM_Left = "FLYCAM_Left";
public static final String FLYCAM_Right = "FLYCAM_Right";
public static final String FLYCAM_Up = "FLYCAM_Up";
public static final String FLYCAM_Down = "FLYCAM_Down";
public static final String FLYCAM_Rise = "FLYCAM_Rise";
public static final String FLYCAM_Lower = "FLYCAM_Lower";
public static final String FLYCAM_ZoomIn = "FLYCAM_ZoomIn";
public static final String FLYCAM_ZoomOut = "FLYCAM_ZoomOut";
Camera cam;
InputManager inputManager;
Vector3f initialUpVec;
float rotationSpeed = 1f;
float moveSpeed = 3f;
float zoomSpeed = 1f;
boolean invertY = false;
public AnalogListenerImpl(Camera cam, InputManager inputManager) {
this.cam = cam;
this.inputManager = inputManager;
initialUpVec = cam.getUp().clone();
inputManager.setCursorVisible(false);
inputManager.addMapping(FLYCAM_Forward, new KeyTrigger(KeyInput.KEY_W));
inputManager.addMapping(FLYCAM_Backward, new KeyTrigger(KeyInput.KEY_S));
inputManager.addMapping(FLYCAM_StrafeLeft, new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping(FLYCAM_StrafeRight, new KeyTrigger(KeyInput.KEY_D));
inputManager.addListener(this, FLYCAM_Forward);
inputManager.addListener(this, FLYCAM_Backward);
inputManager.addListener(this, FLYCAM_StrafeLeft);
inputManager.addListener(this, FLYCAM_StrafeRight);
inputManager.addMapping(FLYCAM_Up, new MouseAxisTrigger(MouseInput.AXIS_Y, false));
inputManager.addMapping(FLYCAM_Down, new MouseAxisTrigger(MouseInput.AXIS_Y, true));
inputManager.addMapping(FLYCAM_Left, new MouseAxisTrigger(MouseInput.AXIS_X, true));
inputManager.addMapping(FLYCAM_Right, new MouseAxisTrigger(MouseInput.AXIS_X, false));
inputManager.addListener(this, FLYCAM_Up);
inputManager.addListener(this, FLYCAM_Down);
inputManager.addListener(this, FLYCAM_Left);
inputManager.addListener(this, FLYCAM_Right);
inputManager.addMapping(FLYCAM_Rise, new KeyTrigger(KeyInput.KEY_Q));
inputManager.addMapping(FLYCAM_Lower, new KeyTrigger(KeyInput.KEY_Y));
inputManager.addListener(this, FLYCAM_Rise);
inputManager.addListener(this, FLYCAM_Lower);
inputManager.addMapping(FLYCAM_ZoomIn, new MouseAxisTrigger(MouseInput.AXIS_WHEEL, false));
inputManager.addMapping(FLYCAM_ZoomOut, new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true));
inputManager.addListener(this, FLYCAM_ZoomIn);
inputManager.addListener(this, FLYCAM_ZoomOut);
}
public void onAnalog(String name, float value, float tpf) {
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 * (invertY ? -1 : 1), cam.getLeft());
}else if (name.equals(FLYCAM_Down)){
rotateCamera(value * (invertY ? -1 : 1), cam.getLeft());
}else if (name.equals(FLYCAM_Forward)){
moveCamera(value, false);
}else if (name.equals(FLYCAM_Backward)){
moveCamera(-value, false);
}else if (name.equals(FLYCAM_StrafeLeft)){
moveCamera(value, true);
}else if (name.equals(FLYCAM_StrafeRight)){
moveCamera(-value, true);
}else if (name.equals(FLYCAM_Rise)){
riseCamera(value);
}else if (name.equals(FLYCAM_Lower)){
riseCamera(-value);
}else if (name.equals(FLYCAM_ZoomIn)){
zoomCamera(value);
}else if (name.equals(FLYCAM_ZoomOut)){
zoomCamera(-value);
}
}
protected void moveCamera(float value, boolean sideways){
Vector3f vel = new Vector3f();
Vector3f pos = cam.getLocation().clone();
if (sideways){
cam.getLeft(vel);
}else{
cam.getDirection(vel);
}
vel.multLocal(value * moveSpeed);
pos.addLocal(vel);
cam.setLocation(pos);
}
protected void rotateCamera(float value, Vector3f axis){
Matrix3f mat = new Matrix3f();
mat.fromAngleNormalAxis(rotationSpeed * value, axis);
Vector3f up = cam.getUp();
Vector3f left = cam.getLeft();
Vector3f dir = cam.getDirection();
mat.mult(up, up);
mat.mult(left, left);
mat.mult(dir, dir);
Quaternion q = new Quaternion();
q.fromAxes(left, up, dir);
q.normalizeLocal();
cam.setAxes(q);
}
protected void riseCamera(float value){
Vector3f vel = new Vector3f(0, value * moveSpeed, 0);
Vector3f pos = cam.getLocation().clone();
pos.addLocal(vel);
cam.setLocation(pos);
}
protected void zoomCamera(float value){
// derive fovY value
float h = cam.getFrustumTop();
float w = cam.getFrustumRight();
float aspect = w / h;
float near = cam.getFrustumNear();
float fovY = FastMath.atan(h / near)
/ (FastMath.DEG_TO_RAD * .5f);
float newFovY = fovY + value * 0.1f * zoomSpeed;
if (newFovY > 0f) {
// Don't let the FOV go zero or negative.
fovY = newFovY;
}
h = FastMath.tan( fovY * FastMath.DEG_TO_RAD * .5f) * near;
w = h * aspect;
cam.setFrustumTop(h);
cam.setFrustumBottom(-h);
cam.setFrustumLeft(-w);
cam.setFrustumRight(w);
}
}
[/java]