[SOLVED] Gravity isn't working?

Aight, so, gravity doesn’t seem to be working. I tried replicating the hello collision project and it hasn’t worked. I’ve done a lot of debugging, and now I’ve been stuck for almost a week with no progress. Here is what I’ve tried (after fixing multiple NPEs).

  • moving the initialization of physics to the main method and passing it down to every other class that needs it.
  • I’ve tried checking to see if the movement commands are working, they weren’t, I fixed it, still nothing.
  • I made sure that I wasn’t creating a new BulletAppState instead of pulling the active one from the AppStateManager.
  • I checked to see if the physics was working on the hex pieces I am adding collision to by giving them a mass (I initially thought it was just a first person issue) and still nothing.
  • I checked the camera to see if it was getting “left behind” by the CharacterControl, nope.

So, what other stupid mistake have I forgotten to check. Here is my code, this is a version where I create the physics state and the character control in the same class, so it shouldn’t have an issue passing it down (but it does). I guess I’ll also include my main method in case something else is being done up the chain that messes it up.

[java]package mygame;

import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.asset.AssetManager;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.input.ChaseCamera;
import com.jme3.input.InputManager;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
/**

  • This AppState deals with the game world itself, it initializes the physics and calls other

  • game related classes, like AI, or day/night cycle.

  • @author Isaac
    */
    public class GameAppState extends AbstractAppState implements ActionListener {

    // Passed variables for physics, and camera.
    protected Camera _cam;
    protected ChaseCamera chaseCam;
    protected Application _app;
    private InputManager inputManager;
    private Node _rootNode;
    private BulletAppState bulletAppState;
    private AppStateManager _appStateManager;
    private CharacterControl player;
    private Vector3f walkDirection = new Vector3f();
    private boolean left = false, right = false, up = false, down = false;

    @Override
    public void initialize(AppStateManager stateManager, Application app) {
    super.initialize(stateManager, app);
    this._app = (SimpleApplication) app;
    }

    @Override
    public void cleanup() {
    super.cleanup();
    }

    @Override
    public void setEnabled(boolean enabled) {
    super.setEnabled(enabled);
    if(enabled){
    initKeys();
    } else {

     }
    

    }

    // Retrieves variables from main and assigns them internally.
    public GameAppState(Application app, AppStateManager appStateManager, InputManager inputManager, AssetManager assetManager, Node rootNode, Camera cam) {
    this.assetManager=assetManager;
    this._rootNode=rootNode;
    this.inputManager=inputManager;
    this._appStateManager=appStateManager;
    this._app=app;
    this._cam=cam;

     /** Set up Physics */
     bulletAppState = new BulletAppState();
     _appStateManager.attach(bulletAppState);
     //bulletAppState.getPhysicsSpace().enableDebug(assetManager);
     
     // Creates player and loads hex model to represent it. Attaches physics to character
     // and sets gravity/jump values.
     hexModel = assetManager.loadModel("Models/hexfade_02/hexfade_02.j3o");
     rootNode.attachChild(hexModel);
     CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1);
     player = new CharacterControl(capsuleShape, 0.05f);
     hexModel.addControl(player);
     player.setJumpSpeed(20f);
     player.setFallSpeed(30f);
     player.setGravity(30f);
     player.setPhysicsLocation(new Vector3f(20, 10, 20));
     
     // creates chase cam for convienient troubleshooting
     chaseCam = new ChaseCamera(cam, hexModel, inputManager);
     
     //bulletAppState.getPhysicsSpace().add(landscape);
     bulletAppState.getPhysicsSpace().add(player);
    

    }

    // alternate constructor to allow other classes to access physics.
    public GameAppState(AppStateManager appStateManager, InputManager inputManager, AssetManager assetManager, Node rootNode, Camera cam) {
    this.assetManager=assetManager;
    this._rootNode=rootNode;
    this.inputManager=inputManager;
    this._appStateManager=appStateManager;
    this._cam=cam;

     if(_rootNode==null) {
         System.out.println("cam null 2");
     }
     if(_cam==null) {
         System.out.println("cam null 2");
     }
     if(_cam==null) {
         System.out.println("cam null 2");
     }
     
     bulletAppState = _appStateManager.getState(BulletAppState.class);
    

    }

    // Initializes key controls
    private void initKeys() {
    if(inputManager!=null) {
    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.addListener(this, new String[]{"Left"});
         inputManager.addListener(this, new String[]{"Right"});
         inputManager.addListener(this, new String[]{"Up"});
         inputManager.addListener(this, new String[]{"Down"});
         inputManager.addListener(this, new String[]{"Jump"});
     }
    

    }

    private boolean keyPressed = false;

    // Checks for key presses and sets bool if key is triggered.
    @Override
    public void onAction(String binding, boolean value, float tpf) {
    switch (binding) {
    case “Left”:
    if (value) { left = true; } else { left = false; }
    break;
    case “Right”:
    if (value) { right = true; } else { right = false; }
    break;
    case “Up”:
    if (value) { up = true; } else { up = false; }
    break;
    case “Down”:
    if (value) { down = true; } else { down = false; }
    break;
    case “Jump”:
    player.jump();
    break;
    }
    }

    // adds object to bullet instance.
    public void addCol(Object obj) {
    bulletAppState.getPhysicsSpace().add(obj);
    }

    // gets bullet.
    public BulletAppState getAppState() {
    return bulletAppState;
    }

    // gets player, used for debug
    public CharacterControl getPlayer() {
    return player;
    }

    // moves the character (or should, anyways). Currently isn’t working even
    // though the update loop is working, seems to be physics issue.
    @Override
    public void update(float tpf) {

     if(_cam!=null) {
         Vector3f camDir = _cam.getDirection().clone().multLocal(0.6f);
         System.out.println(camDir);
         Vector3f camLeft = _cam.getLeft().clone().multLocal(0.4f);
         System.out.println(camLeft);
         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);
         System.out.println(walkDirection);
         _cam.setLocation(player.getPhysicsLocation());
         //System.out.println(player.getPhysicsLocation());
         //System.out.println(_cam.getDirection().clone().mult(0.6f));
     }
    

    }

}
[/java]

Here is my main,

[java]package mygame;

import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.AppStateManager;
import com.jme3.bullet.BulletAppState;
import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Node;

/**

  • Main class, calls app states to start game.

  • @author Isaac
    */
    public class Main extends SimpleApplication {

    protected static Application _app;
    protected Camera _cam;
    protected AppStateManager appStateManager;
    protected BulletAppState bulletAppState;
    protected Node _rootNode;

    public static void main(String[] args) {

     Main app = new Main();
     app.start();
     _app = app;
    

    }

    // Sets up essential functions and components
    @Override
    public void simpleInitApp() {

     assetManager = getAssetManager(); 
     inputManager = getInputManager();
     appStateManager = new AppStateManager(_app);
     
     _cam = cam;
     _rootNode = rootNode;
     
     //flyCam.setEnabled(false);
     flyCam.setMoveSpeed(100);
     flyCam.setEnabled(false);
    

    }

    boolean mainMenu = false;
    boolean gameState = false;

    @Override
    public void simpleUpdate(float tpf) {

     if (gameState == false) // attach appstate only once
     {
         GameAppState g = new GameAppState(_app, appStateManager, inputManager, assetManager, _rootNode, _cam);
         stateManager.attach(g);
         g.initialize(stateManager, this);
         g.setEnabled(true);
         
         gameState = true;
     }
     
     if (mainMenu == false) // attach appstate only once
     {
         MenuAppState x = new MenuAppState(_app, appStateManager, inputManager, assetManager, _rootNode, _cam);
         stateManager.attach(x);
         x.initialize(stateManager, this);
         x.setEnabled(true);
         
         mainMenu = true;
     }
    

    }

    @Override
    public void simpleRender(RenderManager rm) {
    //TODO: add render code
    }
    }
    [/java]

To anyone that can help, thank you!

Just a quick read through:
Never (and I mean never ever ever) call initialize() on an app state yourself. AppStateManager does that for you.

Also, simplify your code by attaching the app states in simpleInit() instead of simpleUpdate() then you can avoid all of the flag nonsense.

1 Like

Thanks for the tips!

Today I also tried importing the JME physics library ( bullet was already imported but I thought “why not try”). Didn’t work either.

…oh my god, I feel like such an idiot.

In my main,
[java]appStateManager = new AppStateManager(_app);[/java]

Please, nobody, ever do this to yourself, its embarrassing :stuck_out_tongue:

2 Likes

Hehe, don’t worry, the better a coder you get the meaner and less obvious these fuckups get :wink:

1 Like
@ASAAR said: .......oh my god, I feel like *such* an idiot.

In my main,
[java]appStateManager = new AppStateManager(_app);[/java]

Please, nobody, ever do this to yourself, its embarrassing :stuck_out_tongue:

And just in case, note that you also pass that bogus app state manager to your app states on their constructors… which is totally unnecessary for a few reasons.

  1. you don’t need to pass these to an app states constructor since they will get it on initialize and this only gives you the chance of doing something wrong.
  2. as you’ve discovered, it wasn’t even the right state manager… see last half of (1) right above. :slight_smile: