Camera Trouble With Nifty

Hi There,

I’ve been trying to get my nifty GUI to interact correctly with my game. It works just fine if I run it without the GUI and run it straight from simpleInitApp.

When I add the GUI it will run only if I remove the lines 305 and 306.

It has to do with the loop update and attatching the camera to the player.

By removing those lines I am in free cam flying around my model. My model has it’s physics and will jump when I press space. The spheres will shoot on click from the fly cam and interact correctly with the environment.

Any ideas why attaching the fly cam to the player isn’t working?

[java]package mygame;

import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.animation.LoopMode;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.TextureKey;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
import com.jme3.font.BitmapText;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Ray;
import com.jme3.math.Vector3f;
import com.jme3.niftygui.NiftyJmeDisplay;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Sphere;
import com.jme3.scene.shape.Sphere.TextureMode;
import com.jme3.texture.Texture;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;

public class Main extends SimpleApplication implements ActionListener, ScreenController {

Material stone_mat;
private static Sphere sphere;
private Node model;
private Geometry mark;
private Node shootables;
private Spatial sceneModel;
private RigidBodyControl PinShape;
private RigidBodyControl ball_phy;
private RigidBodyControl PinPhys;
private Spatial BowlingPin;
private BulletAppState bulletAppState;
private RigidBodyControl landscape;
private CharacterControl player;
private Vector3f walkDirection = new Vector3f();
private boolean left = false, right = false, up = false, down = false;
private AnimChannel channel;
private AnimControl control;

//Temporary vectors used on each frame.
//They here to avoid instanciating new vectors on each frame
private Vector3f camDir = new Vector3f();
private Vector3f camLeft = new Vector3f();

//Nifty Stuff
private Nifty nifty;
private Screen screen;
private SimpleApplication app;

public static void main(String[] args) {
Main app = new Main();
app.start();
}
static {
/** Initialize the cannon ball geometry */
sphere = new Sphere(32, 32, 0.4f, true, false);
sphere.setTextureMode(TextureMode.Projected);
}

@Override
public void simpleInitApp() {
NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(
assetManager, inputManager, audioRenderer, guiViewPort);
Nifty nifty = niftyDisplay.getNifty();
nifty.fromXml(“Interface/Nifty/GameGUI.xml”, “start”, this);
guiViewPort.addProcessor(niftyDisplay);
nifty.loadControlFile(“nifty-default-controls.xml”);
flyCam.setDragToRotate(true);

}

public void gameStart() {

nifty.gotoScreen("");


/** Set up Physics */
bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
//bulletAppState.getPhysicsSpace().enableDebug(assetManager);

// We re-use the flyby camera for rotation, while positioning is handled by physics
flyCam.setDragToRotate(false);
viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
flyCam.setMoveSpeed(100);
setUpKeys();
setUpLight();
initCrossHairs();



shootables = new Node("Shootables");
    rootNode.attachChild(shootables);
    shootables.attachChild(MakePin());

// We load the scene from the zip file and adjust its size.
sceneModel = assetManager.loadModel("Scenes/Village/Village.j3o");
sceneModel.setLocalTranslation(5f, 0f, 1f);

// We set up collision detection for the scene by creating a
// compound collision shape and a static RigidBodyControl with mass zero.
CollisionShape sceneShape =
CollisionShapeFactory.createMeshShape((Node) sceneModel);
landscape = new RigidBodyControl(sceneShape, 0);
sceneModel.addControl(landscape);


// We set up collision detection for the player by creating
// a capsule collision shape and a CharacterControl.
// The CharacterControl offers extra settings for
// size, stepheight, jumping, falling, and gravity.
// We also put the player in its starting position.
CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(.9f, 1.0f, 1);
player = new CharacterControl(capsuleShape, .05f);
model = (Node) assetManager.loadModel("Models/MeshMan/MeshMan.j3o");
model.setLocalScale(.5f);
model.addControl(player);
player.setUpAxis(1);
player.setMaxSlope(.1f);
player.setJumpSpeed(20);
player.setFallSpeed(30);
player.setGravity(60);
player.setPhysicsLocation(new Vector3f(0, 10, 0));
// We attach the scene and the player to the rootnode and the physics space,
// to make them appear in the game world.
rootNode.attachChild(sceneModel);
rootNode.attachChild(model);
bulletAppState.getPhysicsSpace().add(landscape);
bulletAppState.getPhysicsSpace().add(player);

}

//These are the bowling Pin Physics
private Spatial MakePin(){
BowlingPin = assetManager.loadModel(“Models/BowlingPin/BowlingPin.j3o”);
BowlingPin.setLocalTranslation(15f, 0f, 15f);
BowlingPin.setLocalScale(.5f);
rootNode.attachChild(BowlingPin);
CollisionShape PinShape =
CollisionShapeFactory.createDynamicMeshShape(BowlingPin);
PinPhys = new RigidBodyControl(PinShape);
BowlingPin.addControl(PinPhys);
PinPhys.setMass(1f);
PinPhys.setKinematic(false);
bulletAppState.getPhysicsSpace().add(PinPhys);
return BowlingPin;
}

private void setUpLight() {
// We add light so we see the scene
AmbientLight al = new AmbientLight();
al.setColor(ColorRGBA.White.mult(1.3f));
rootNode.addLight(al);

DirectionalLight dl = new DirectionalLight();
dl.setColor(ColorRGBA.White);
dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal());
rootNode.addLight(dl);

}

/** We over-write some navigational key mappings here, so we can

  • add physics-controlled walking and jumping: */
    private void setUpKeys() {
    inputManager.addMapping(“Left”, new KeyTrigger(KeyInput.KEY_A));
    inputManager.addMapping(“Right”, new KeyTrigger(KeyInput.KEY_D));
    inputManager.addMapping(“Up”, new KeyTrigger(KeyInput.KEY_W));
    inputManager.addMapping(“Down”, new KeyTrigger(KeyInput.KEY_S));
    inputManager.addMapping(“Jump”, new KeyTrigger(KeyInput.KEY_SPACE));
    inputManager.addMapping(“Shoot”, new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
    inputManager.addListener(this, “Shoot”);
    inputManager.addListener(this, “Left”);
    inputManager.addListener(this, “Right”);
    inputManager.addListener(this, “Up”);
    inputManager.addListener(this, “Down”);
    inputManager.addListener(this, “Jump”);
    }

/** These are our custom actions triggered by key presses.

  • We do not walk yet, we just keep track of the direction the user pressed. */
    public void onAction(String binding, boolean isPressed, float tpf) {
    if (binding.equals(“Left”)) {
    left = isPressed;
} else if (binding.equals("Right")) {
  right= isPressed;
  
} else if (binding.equals("Up")) {
  up = isPressed;
  
} else if (binding.equals("Down")) {
  down = isPressed;
  
} else if (binding.equals("Jump")) {
  if (isPressed) { player.jump(); }
  
} else if (binding.equals("Shoot") && !isPressed) {

    makeCannonBall();
    }

}

 public void makeCannonBall() {
/** Create a cannon ball geometry and attach to scene graph. */
Geometry ball_geo = new Geometry("cannon ball", sphere);
stone_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG");
key2.setGenerateMips(true);
Texture tex2 = assetManager.loadTexture(key2);
stone_mat.setTexture("ColorMap", tex2);
ball_geo.setMaterial(stone_mat);
rootNode.attachChild(ball_geo);
/** Position the cannon ball  */
ball_geo.setLocalTranslation(cam.getLocation());
/** Make the ball physcial with a mass > 0.0f */
ball_phy = new RigidBodyControl(1f);
/** Add physical ball to physics space. */
ball_geo.addControl(ball_phy);
bulletAppState.getPhysicsSpace().add(ball_phy);
/** Accelerate the physcial ball to shoot it. */
ball_phy.setLinearVelocity(cam.getDirection().mult(25));

}

/** A centred plus sign to help the player aim. */
protected void initCrossHairs() {
setDisplayStatView(false);
guiFont = assetManager.loadFont(“Interface/Fonts/Default.fnt”);
BitmapText ch = new BitmapText(guiFont, false);
ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);
ch.setText("+"); // crosshairs
ch.setLocalTranslation( // center
settings.getWidth() / 2 - ch.getLineWidth()/2, settings.getHeight() / 2 + ch.getLineHeight()/2, 0);
guiNode.attachChild(ch);
}

public void backToStart(String start){
  nifty.gotoScreen("start");
}

public void bind(Nifty nifty, Screen screen) {
this.nifty = nifty;
this.screen = screen;

}

public void onStartScreen() {

}

public void onEndScreen() {

}
/**

  • This is the main event loop–walking happens here.

  • We check in which direction the player is walking by interpreting

  • the camera direction forward (camDir) and to the side (camLeft).

  • The setWalkDirection() command is what lets a physics-controlled player walk.

  • We also make sure here that the camera moves with player.
    */
    @Override
    public void simpleUpdate(float tpf) {
    camDir.set(cam.getDirection()).multLocal(0.6f);
    camLeft.set(cam.getLeft()).multLocal(0.4f);
    walkDirection.set(0, 0, 0);
    if (left) {
    walkDirection.addLocal(camLeft);
    }
    if (right) {
    walkDirection.addLocal(camLeft.negate());
    }
    if (up) {
    walkDirection.addLocal(camDir);
    }
    if (down) {
    walkDirection.addLocal(camDir.negate());
    }

    //player.setWalkDirection(walkDirection);
    //cam.setLocation(player.getPhysicsLocation());
    }
    }

Sorry about that… I thought it would make a code screen, I don’t think I can edit.

Here’s a paste bin.

The lines are

//player.setWalkDirection(walkDirection);
//cam.setLocation(player.getPhysicsLocation());

That are causing it not to work.