Pause/Resume Game?

I looked on the jmonkey tutorials and they gave me a skeleton version of an appstate for settings things up for pausing a game. removing the collision from the appstate is a part of it. But does anyone have a small example of pausing resuming a game … like hello collision standards?


import com.jme3.app.SimpleApplication;
import com.jme3.asset.plugins.ZipLocator;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.collision.shapes.SphereCollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Sphere;
import com.jme3.bullet.collision.PhysicsCollisionListener;
import com.jme3.bullet.collision.PhysicsCollisionEvent;
import com.jme3.font.BitmapText;
import com.jme3.font.Rectangle;
import com.jme3.scene.shape.Box;
import com.jme3.scene.Geometry;

/**
 * Example 9 - How to make walls and floors solid.
 * This collision code uses Physics and a custom Action Listener.
 * @author normen, with edits by Zathras
 */
public class Main extends SimpleApplication
        implements ActionListener, PhysicsCollisionListener {

  private Node sphere, pausing, groundNode;
  private Geometry floorGeom;
  private Box floor;
  private BulletAppState bulletAppState;
  private RigidBodyControl landscape, enemyControl;
  private CharacterControl player;
  private Vector3f walkDirection = new Vector3f();
  private boolean left = false, right = false, up = false, down = false;
  GameStatus gameStatus = GameStatus.RUNNING;
  private BitmapText pauseMenu;
  
  //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();

  public static void main(String[] args) {
    Main app = new Main();
    app.start();
  }
  public enum GameStatus{
      RUNNING, PAUSED;
  }

  public void simpleInitApp() {
    /** 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
    viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
    flyCam.setMoveSpeed(100);
    setUpKeys();
    setUpLight();

    pauseMenu = new BitmapText(guiFont, false);
    pauseMenu.setText("Paused");
    pauseMenu.setSize(guiFont.getCharSet().getRenderedSize()*2);
    Rectangle rectangle = new Rectangle(0,0,30,300);
    pauseMenu.setBox(rectangle);
    pauseMenu.setColor(ColorRGBA.Blue);
   
    
    // We load the scene from the zip file and adjust its size.
    //assetManager.registerLocator("town.zip", ZipLocator.class);
    floorGeom = new Geometry("floor", new Box(20,1,20));
    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    floorGeom.setMaterial(mat);
    groundNode = new Node("");
    groundNode.attachChild(floorGeom);
    groundNode.setLocalTranslation(0,-1,0);

    // 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) groundNode);
    landscape = new RigidBodyControl(sceneShape, 0);
    groundNode.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(1.5f, 6f, 1);
    player = new CharacterControl(capsuleShape, 0.05f);
    player.setJumpSpeed(20);
    player.setFallSpeed(30);
    player.setGravity(30);
    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(groundNode);
    bulletAppState.getPhysicsSpace().add(landscape);
    bulletAppState.getPhysicsSpace().add(player);
  }

  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("pause", new KeyTrigger(KeyInput.KEY_P));
    inputManager.addListener(this, "Left");
    inputManager.addListener(this, "Right");
    inputManager.addListener(this, "Up");
    inputManager.addListener(this, "Down");
    inputManager.addListener(this, "Jump");
    inputManager.addListener(this, "pause");
    
  }

  /** 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 value, float tpf) {
    if (binding.equals("Left")) {
      if (value) { left = true; } else { left = false; }
    } else if (binding.equals("Right")) {
      if (value) { right = true; } else { right = false; }
    } else if (binding.equals("Up")) {
      if (value) { up = true; } else { up = false; }
    } else if (binding.equals("Down")) {
      if (value) { down = true; } else { down = false; }
    } else if (binding.equals("Jump")) {
      player.jump();
    }else if(binding.equals("pause") && gameStatus==GameStatus.RUNNING){
        pauseGame();
    }else if(binding.equals("pause") && gameStatus==GameStatus.PAUSED){
        resumeGame();
    }
  }
  public void pauseGame(){
      gameStatus = GameStatus.PAUSED;
      bulletAppState.getPhysicsSpace().removeCollisionListener(this);
      rootNode.attachChild(pausing);
      
  }
  public void resumeGame(){
      gameStatus = GameStatus.RUNNING;
      bulletAppState.getPhysicsSpace().addCollisionListener(this);
      rootNode.detachChild(pausing);
  }
  public void collision(PhysicsCollisionEvent event){
      
  }

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

A single player game? If you remove the appstate or disable it, everything should just stop.

But as a general mindset, consider using appstates and controls. They have methods to aid in cleaning up after yourself. I found them to be very helpful. BaseAppstate is the go-to extension for most cases.



import com.jme3.app.Application;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.app.SimpleApplication;
import com.jme3.scene.Node;
import com.jme3.asset.AssetManager;
import com.jme3.input.InputManager;
import com.jme3.bullet.BulletAppState;
import com.jme3.renderer.ViewPort;
import com.jme3.bullet.collision.PhysicsCollisionListener;

/**
 *
 * @author Mack
 */
public class MyAppState extends AbstractAppState implements PhysicsCollisionListener {
    
    private BulletAppState bulletAppState;
    private Node rootNode;
    private SimpleApplication app;
    private AssetManager assetManager;
    private AppStateManager stateManager;
    private InputManager inputManager;
    private ViewPort viewPort;
    
    @Override
    public void initialize(AppStateManager stateManager, Application app) {
        super.initialize(stateManager, app);
        this.app=(SimpleApplication) app;
        this.stateManager=app.getStateManager();
        this.assetManager=app.getAssetManager();
        this.bulletAppState=this.stateManager.getState(BulletAppState.class);
        this.viewPort=app.getViewPort();
        this.inputManager=app.getInputManager();
        //TODO: initialize your AppState, e.g. attach spatials to rootNode
        //this is called on the OpenGL thread after the AppState has been attached
    }
    
    @Override
    public void update(float tpf) {
        //TODO: implement behavior during runtime
    }
    
    @Override
    public void cleanup() {
        super.cleanup();
        this.app.getRootNode().detachChild(rootNode);
        
        //TODO: clean up what you initialized in the initialize method,
        //e.g. remove all spatials from rootNode
        //this is called on the OpenGL thread after the AppState has been detached
    }
    public void setEnabled(boolean enabled){
        super.setEnabled(enabled);
        if(enabled){
         
            
        }
    }
    
}

so this appstate above me here will be used inside the copied hellocollision example i have. How would i implement this class inside the setenabled method i have for the main class?

I’m gonna look at the cookbook example again. I never really trailed through it. I’ve been doing tutorials for the past two months. I’m crazy!

Yeah. It’s more of a mindset as I skimmed over initially. An appstate describes the state of an application. And so with that in mind, they can be thought of as a component of an entity system. But the importance here is that they can be encapsulated as you desire. When created you have everything (Application App). Check for other states in the initialize method if dependencies are required. Store your required objects in that appstate scope, and tidy up after yourself in the appropriate appstate methods (onDisable, cleanup).

Generally, this “plugin-style” system allows you to throw things in and out easily. Most things are designed around this pattern in JME.

Sorry, to answer your question: Initialize everything in the initialize method. You can use the onEnable and onDisable methods as needed. For example, adding and removing nodes to the scene. That way you can keep them attached and toggle them. Then use the cleanup method to destroy your appstate completely. Note that onDisable and onEnable are called automatically when attached and detached - unless you specify setEnabled(false) in the constructor - in which case it will only be enabled when you specify. Phew.

Physics, flycam, all sorts of states can just be turned on and off. If written in accordance…

import com.jme3.app.Application;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.app.SimpleApplication;
import com.jme3.scene.Node;
import com.jme3.asset.AssetManager;
import com.jme3.input.InputManager;
import com.jme3.bullet.BulletAppState;
import com.jme3.renderer.ViewPort;
import com.jme3.input.controls.ActionListener;
import com.jme3.math.Vector3f;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.material.Material;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.KeyInput;
import com.jme3.renderer.Camera;
/**
 *
 * @author Mack
 */
public class MyAppState extends AbstractAppState implements ActionListener {
    
    private BulletAppState bulletAppState;
    private Node rootNode, scene;
    private SimpleApplication app;
    private AssetManager assetManager;
    private AppStateManager stateManager;
    private InputManager inputManager;
    private ViewPort viewPort;
    private Camera cam;
    GameStatus gameStatus = GameStatus.RUNNING;
    
    private Vector3f camLeft, camDir;
    private Vector3f walkDirection = new Vector3f();
    private RigidBodyControl landscape;
    private CharacterControl player;
    private Geometry geom;
    private boolean up,down,left,right=false;
    
    public enum GameStatus{
        RUNNING, PAUSED;
    }
    public static void main(String[] args) {
    MyAppState mas = new MyAppState();
    
  }
    
    @Override
    public void initialize(AppStateManager stateManager, Application app) {
        super.initialize(stateManager, app);
        this.app=(SimpleApplication) app;
        this.cam=app.getCamera();
        this.stateManager=app.getStateManager();
        this.assetManager=app.getAssetManager();
        this.bulletAppState=this.stateManager.getState(BulletAppState.class);
        this.viewPort=app.getViewPort();
        this.inputManager=app.getInputManager();
        this.rootNode=this.app.getRootNode();
        //TODO: initialize your AppState, e.g. attach spatials to rootNode
        //this is called on the OpenGL thread after the AppState has been attached
    }
    public void simpleInitApp(){
        bulletAppState = new BulletAppState();
        stateManager.attach(this);
        
        scene = (Node)assetManager.loadModel("");
        scene.setLocalScale(5f);
        geom = new Geometry("floor", new Box(20, 1, 20));
        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        geom.setMaterial(mat);
        scene.attachChild(geom);
        rootNode.attachChild(scene);
        
        CollisionShape collShape = CollisionShapeFactory.createMeshShape((Node) scene);
        landscape = new RigidBodyControl(collShape, 0f);
        scene.addControl(landscape);
        bulletAppState.getPhysicsSpace().add(landscape);
        
        CapsuleCollisionShape capShape = new CapsuleCollisionShape(1.5f,6f,1);
        player = new CharacterControl(capShape, 0.05f);
        bulletAppState.getPhysicsSpace().add(player);
        
        setUpKeys();
    }
    
    @Override
    public void update(float tpf) {
        //TODO: implement behavior during runtime
    }
    
    @Override
    public void cleanup() {
        super.cleanup();
        this.app.getRootNode().detachChild(rootNode);
        this.app.getStateManager().detach(this);
        
        
        //TODO: clean up what you initialized in the initialize method,
        //e.g. remove all spatials from rootNode
        //this is called on the OpenGL thread after the AppState has been detached
    }
    public void setEnabled(boolean enabled){
        super.setEnabled(enabled);
        if(enabled){
         gameStatus = GameStatus.RUNNING;
         this.app.getRootNode().attachChild(rootNode);
         this.app.getStateManager().attach(this);
            
        }else{
            gameStatus = GameStatus.PAUSED;
            this.app.getStateManager().detach(this);
        }
    }
    private void setUpKeys(){
       inputManager.addMapping("up", new KeyTrigger(KeyInput.KEY_UP));
       inputManager.addMapping("down", new KeyTrigger(KeyInput.KEY_DOWN));
       inputManager.addMapping("left", new KeyTrigger(KeyInput.KEY_LEFT));
       inputManager.addMapping("right", new KeyTrigger(KeyInput.KEY_RIGHT));
       inputManager.addMapping("jump", new KeyTrigger(KeyInput.KEY_SPACE));
       inputManager.addMapping("pause", new KeyTrigger(KeyInput.KEY_P));
       inputManager.addListener(this, "up");
       inputManager.addListener(this, "down");
       inputManager.addListener(this, "left");
       inputManager.addListener(this, "right");
       inputManager.addListener(this, "jump");
       inputManager.addListener(this, "pause");
    }
    public void onAction(String binding, boolean value, float tpf){
        if (binding.equals("left")) {
      if (value) { left = true; } else { left = false; }
    } else if (binding.equals("right")) {
      if (value) { right = true; } else { right = false; }
    } else if (binding.equals("up")) {
      if (value) { up = true; } else { up = false; }
    } else if (binding.equals("down")) {
      if (value) { down = true; } else { down = false; }
    } else if (binding.equals("jump")) {
      player.jump();
    }else if(binding.equals("pause") && gameStatus!=GameStatus.PAUSED){
        pauseGame();
    }else if(binding.equals("pause") && gameStatus!=GameStatus.RUNNING){
        resumeGame();
        }
    }
    public void simpleUpdate(float tpf){
        camDir = new Vector3f();
        camLeft = new Vector3f();
        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());
    }
    
    public void pauseGame(){
        setEnabled(false);
        gameStatus = GameStatus.PAUSED;
     
    }
    
    public void resumeGame(){
        setEnabled(true);
        gameStatus = GameStatus.RUNNING;
    }
}

I hope you haven’t forgot about me. I have this appstate here with all the code written on it. I need to know how to set up my main class to this appstate so that I can remove the statemanager. Need some help here guys

node to capsuleshape, charactercontrol to capsuleshape, node to charactercontrol…
I know that. BUT. how do I set up the main class to the appstate??? that’s the real question here. I know my stuff. Its just I don’t know how to set up the main class. Do I extend the appstate? do I come up with a start method?

An application may have many app states. Your app state is not your application.

Please do the tutorials as you seem to be very confused.

Applications should extend SimpleApplication. They can have dozens of app states if they like.

Sorry about these dumb posts guys. Past few months its been kind of confusing yes. But I haven’t been scavenging. I’ve been humbly learning. Don’t wanna come off as a doodoo. And I also don’t want to come off as a smarty pants.