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!