i tried a few things and this worked for me:
- when you press A or D, set a variable toRotate to 90 and isRotationg to true
- in the update cycle, check if you are rotating, if yes, calculate the amount of degree you rotate in this update cycle
- subtract this from the toRotate value
- create a new quaternion with this amount negative or positive depending on the direction and apply it to your char
the good thing about this, is its easy to see when the rotation is ended
// left rotation code
if (KeyBindingManager.getKeyBindingManager().isValidCommand("rotateLeft", false)) {
if (isRotating) {
System.out.println("ignoring keypress while rotating");
} else {
isRotating = true;
toRotate = ROTATION_STEP; // 90 or 45
dir = Direction.LEFT;
}
}
if (isRotating) {
float value = 0;
// look in which direction we turn, and calculate
// how much we should turn in this update cycle
if (dir == Direction.RIGHT) {
value = rotationSpeed*tpf*-1;
toRotate += value;
} else {
value = rotationSpeed*tpf;
toRotate -= value;
}
System.out.println("Degrees toRotate: " +toRotate);
// have we finished rotating ?
if (toRotate <= 0) {
// rotation has reached its end
isRotating = false;
} else {
// not yet reached the end position, continue rotation
// create a Quaternion which represents the Rotation
// for this Cycle
tmpAngles[0] = 0; // X
tmpAngles[1] = value * FastMath.DEG_TO_RAD; // Y
tmpAngles[2] = 0; // Z
tmpRotationQuat.fromAngles(tmpAngles);
// multiply the players current rotation with the rotation
// we want to do in this update cycle
playerNode.getLocalRotation().multLocal(tmpRotationQuat);
}
}
tho whole thing:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingBox;
import com.jme.bounding.CollisionTree;
import com.jme.bounding.CollisionTreeManager;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.intersection.CollisionData;
import com.jme.intersection.CollisionResults;
import com.jme.intersection.TriangleCollisionResults;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.scene.CameraNode;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.shape.Box;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.model.converters.FormatConverter;
import com.jmex.model.converters.ObjToJme;
public class HelloModelLoading extends SimpleGame {
private final float ROTATION_STEP = 45;
private Node playerNode = new Node("player Node");
private Spatial map;
private CollisionResults results;
private CollisionData oldData;
// player run speed
private float playerSpeed = 3f;
// player rotation speed
private float rotationSpeed = 100f;
private Vector3f lastPosition;
// temporary float array to store rotation angles
private float[] tmpAngles = new float[3];
// temporary quaternion used to rotate
private Quaternion tmpRotationQuat = new Quaternion();
// are we rotationg currently ?
private boolean isRotating = false;
// degrees to rotate
private float toRotate = 0;
private enum Direction {
RIGHT,
LEFT;
}
Direction dir;
public static void main(String[] args) {
HelloModelLoading app = new HelloModelLoading();
app.setConfigShowMode(ConfigShowMode.AlwaysShow);
Logger.getLogger("").setLevel(Level.SEVERE);
app.start();
}
protected void simpleInitGame() {
display.setTitle("test dungeon");
CollisionTreeManager.getInstance().setTreeType(CollisionTree.Type.AABB);
results = new TriangleCollisionResults();
URL folder= HelloModelLoading.class.getClassLoader().getResource("data/");
URL model = HelloModelLoading.class.getClassLoader().getResource("data/test01.obj");
FormatConverter converter=new ObjToJme();
converter.setProperty("mtllib", folder);
converter.setProperty("texdir", folder);
ByteArrayOutputStream BO=new ByteArrayOutputStream();
try {
//mapNode = new Node("map node");
converter.convert(model.openStream(), BO);
map=(Spatial) BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
map.setLocalScale(.1f);
map.setModelBound(new BoundingBox());
map.updateModelBound();
//player = new Cylinder("box", 10, 25, 1, 1,true);
//player.setLocalRotation( new Quaternion().fromAngleAxis( - FastMath.PI/2, new Vector3f(1,0,0)) );
Spatial player = new Box("box", new Vector3f(0,5,0), 1, 1 ,1);
player.setLocalScale(0.1f);
player.setModelBound(new BoundingBox());
player.updateModelBound();
playerNode.getLocalRotation().set(new Quaternion().fromAngleAxis( - FastMath.PI/2, new Vector3f(0,1,0)) );
playerNode.setLocalTranslation(0, 0.1f, 0);
playerNode.attachChild(player);
// attach player and map to the scene
rootNode.attachChild(playerNode);
rootNode.attachChild(map);
} catch (Exception e) { // Just in case anything happens
System.out.println("Damn exceptions! O_o n" + e);
e.printStackTrace();
System.exit(0);
}
KeyBindingManager.getKeyBindingManager().set("moveFwd", KeyInput.KEY_W);
KeyBindingManager.getKeyBindingManager().set("moveBwd", KeyInput.KEY_S);
KeyBindingManager.getKeyBindingManager().set("rotateLeft", KeyInput.KEY_A);
KeyBindingManager.getKeyBindingManager().set("rotateRight", KeyInput.KEY_D);
KeyBindingManager.getKeyBindingManager().set("strafeLeft", KeyInput.KEY_Q);
KeyBindingManager.getKeyBindingManager().set("strafeRight", KeyInput.KEY_E);
KeyBindingManager.getKeyBindingManager().set("return", KeyInput.KEY_RETURN);
// create a Camera Node and attach it to the player node
// move the camera a bit behind and above the player
CameraNode camNode = new CameraNode("", cam);
playerNode.attachChild(camNode);
camNode.setLocalTranslation(0, 0.7f, -0.5f);
lastPosition = new Vector3f();
//disable mouselook:
//input = new InputHandler();
//prevent "look through walls glitch
cam.setFrustumPerspective(45.0f, (float) display.getWidth() / (float) display.getHeight(), 0.002f, 350);
}
protected void simpleUpdate() {
//make collision box invisible
//player.setCullHint(CullHint.Always);
//collision stuff
results.clear();
playerNode.findCollisions(rootNode, results);
if (results.getNumber() <= 0) {
System.out.printf("don't cross the dungeon limits dammitn");
System.exit(0);
}
oldData = results.getCollisionData(0);
if (oldData.getTargetTris().size() == 0) {
//store player last known working location
lastPosition.set(playerNode.getLocalTranslation());
// the boolean at the end is for keypress repeat
if (KeyBindingManager.getKeyBindingManager().isValidCommand("moveFwd", true)) {
playerNode.getLocalTranslation().x += cam.getDirection().x * playerSpeed * timer.getTimePerFrame();
playerNode.getLocalTranslation().z += cam.getDirection().z * playerSpeed * timer.getTimePerFrame();
}
if (KeyBindingManager.getKeyBindingManager().isValidCommand("moveBwd", true)) {
playerNode.getLocalTranslation().x -= cam.getDirection().x * playerSpeed * timer.getTimePerFrame();
playerNode.getLocalTranslation().z -= cam.getDirection().z * playerSpeed * timer.getTimePerFrame();
}
if (KeyBindingManager.getKeyBindingManager().isValidCommand("strafeLeft", true)) {
Vector3f sideways = cam.getLeft();
playerNode.getLocalTranslation().x += sideways.x * playerSpeed * timer.getTimePerFrame();
playerNode.getLocalTranslation().z += sideways.z * playerSpeed * timer.getTimePerFrame();
}
if (KeyBindingManager.getKeyBindingManager().isValidCommand("strafeRight", true)) {
Vector3f sideways = cam.getLeft();
playerNode.getLocalTranslation().x -= sideways.x * playerSpeed * timer.getTimePerFrame();
playerNode.getLocalTranslation().z -= sideways.z * playerSpeed * timer.getTimePerFrame();
}
// left rotation code
if (KeyBindingManager.getKeyBindingManager().isValidCommand("rotateLeft", false)) {
if (isRotating) {
System.out.println("ignoring keypress while rotating");
} else {
isRotating = true;
toRotate = ROTATION_STEP;
dir = Direction.LEFT;
System.out.println("Target Direction set to: " +dir
+"toRoate set to" +ROTATION_STEP);
}
}
// right rotation code
if (KeyBindingManager.getKeyBindingManager().isValidCommand("rotateRight", false)) {
if (isRotating) {
System.out.println("ignoring keypress while rotating");
} else {
isRotating = true;
toRotate = ROTATION_STEP;
dir = Direction.RIGHT;
System.out.println("Target Direction set to: " +dir
+"toRoate set to" +ROTATION_STEP);
}
}
// check if we should turn
if (isRotating) {
float value = 0;
// look in which direction we turn, and calculate
// how much we should turn in this update cycle
if (dir == Direction.RIGHT) {
value = rotationSpeed*tpf*-1;
toRotate += value;
} else {
value = rotationSpeed*tpf;
toRotate -= value;
}
System.out.println("Degrees toRotate: " +toRotate);
// have we finished rotating ?
if (toRotate <= 0) {
// rotation has reached its end
isRotating = false;
} else {
// not yet reached the end position, continue rotation
// create a Quaternion which represents the Rotation
tmpAngles[0] = 0; // X
tmpAngles[1] = value * FastMath.DEG_TO_RAD; // Y
tmpAngles[2] = 0; // Z
tmpRotationQuat.fromAngles(tmpAngles);
// multiply the players current rotation with the rotation
// we want to do in this update cycle
playerNode.getLocalRotation().multLocal(tmpRotationQuat);
}
}
if (KeyBindingManager.getKeyBindingManager().isValidCommand("return", true)) {
//report current angle
playerNode.getLocalRotation().toAngles(tmpAngles);
float currentAngle = tmpAngles[1] * FastMath.RAD_TO_DEG;
System.out.println("current angle: " +currentAngle);
}
}
if (oldData.getTargetTris().size() > 0) {
System.out.println("Collission - reset position");
playerNode.getLocalTranslation().set(lastPosition);
}
}
}