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());
}
}