Sep 4, 2014

44. Physics


Using AppState and controls, we can use the built-in Physics Engine in jMonkeyEngine.




The floor is a Box mesh of 25 square meter dimensions.


        // *** 1. Start (Create Floor)
        Box b = new Box(5,1,5);
        Geometry floor = new Geometry("floor", b);
        Material mat = new Material(assetManager, 
                "Common/MatDefs/Misc/ShowNormals.j3md");
        floor.setMaterial(mat);
        rootNode.attachChild(floor);
        // *** 1. End



We have to start the BulletAppState to use Bullet physics.


        // *** 2. Start (Physics - 3rd line debug)
        bulletAppState = new BulletAppState();
        stateManager.attach(bulletAppState);
        bulletAppState.getPhysicsSpace().enableDebug(assetManager);
        // *** 2. End



We set a RigidBodyControl object to the floor, so it is immovable.


        // *** 3. Start (floor is rigid)
        scenePhy = new RigidBodyControl(0f);
        floor.addControl(scenePhy);
        bulletAppState.getPhysicsSpace().add(floor);
        // *** 3. End



The player is a BetterCharacterControl object to use the Physics.


        // *** 4. Start (invisible player)
        playerNode = new Node("the player");
        playerNode.setLocalTranslation(
                new Vector3f(0, 1, 0));
        rootNode.attachChild(playerNode);
        playerControl = new BetterCharacterControl(
                1.5f, 4, 30f);
        playerControl.setJumpForce(new Vector3f(0, 300, 0));
        playerControl.setGravity(new Vector3f(0, -10, 0));
        playerNode.addControl(playerControl);
        bulletAppState.getPhysicsSpace().add(playerControl);
        // *** 4. End



A camera is created, fixed to our player.


        // *** 5. Start (Camera attached to Player)
        camNode = new CameraNode("CamNode", cam);
        camNode.setControlDir(CameraControl.
                              ControlDirection.SpatialToCamera);
        camNode.setLocalTranslation(new Vector3f(0, 4, -6));
        Quaternion quat = new Quaternion();
        quat.lookAt(Vector3f.UNIT_Z, Vector3f.UNIT_Y);
        camNode.setLocalRotation(quat);
        playerNode.attachChild(camNode);
        camNode.setEnabled(true);
        flyCam.setEnabled(false);
        // *** 5. End



The four arrow keys are registered.


        // *** 6. Start (Arrow Keys)
        inputManager.addMapping("Forward",
                new KeyTrigger(KeyInput.KEY_UP));
        inputManager.addMapping("Back",
                new KeyTrigger(KeyInput.KEY_DOWN));
        inputManager.addMapping("Left",
                new KeyTrigger(KeyInput.KEY_LEFT));
        inputManager.addMapping("Right",
                new KeyTrigger(KeyInput.KEY_RIGHT));
        inputManager.addListener(this, "Left", 
                "Right","Forward", "Back");
        // *** 6. End



In simpleUpdate(), the booleans are checked to update player position, and the attached camera.


    // *** 7. Start (Walk character)
    @Override
    public void simpleUpdate(float tpf) {
        Vector3f ForwardDir = Vector3f.UNIT_Z;
        Vector3f LeftDir = Vector3f.UNIT_X;
        walkDirection.set(0, 0, 0); 
        if (forward) {
            walkDirection = walkDirection.add(ForwardDir);
        } else if (backward) {
            walkDirection = walkDirection.subtract(ForwardDir);
        }
        if (Left) {
            walkDirection = walkDirection.add(LeftDir);
        } else if (Right) {
            walkDirection = walkDirection.subtract(LeftDir);
        }
        playerControl.setWalkDirection(walkDirection);
        vy = playerControl.getVelocity().y;
        if (vy<-10f) {
            System.out.println("Game over");
        }
    }
    // *** 7. End



When an action, arrow key press or release, occurs, the booleans will be set true or false.


    // *** 8. Start (Which key 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("Forward")) {
            forward = isPressed;
        }
        else if (binding.equals("Back")) {
            backward = isPressed;
        }
    }
    // *** 8. End



// JMonkey44.java

package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.control.BetterCharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.CameraNode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.control.CameraControl;
import com.jme3.scene.shape.Box;

public class JMonkey44 extends SimpleApplication
        implements ActionListener  {
    public static void main(String[] args) {
        JMonkey44 app = new JMonkey44();
        app.start();
    }
    
    private BulletAppState bulletAppState; // physics
    private RigidBodyControl scenePhy; // rigid floor
    private Node playerNode;
    private BetterCharacterControl playerControl; // player
    private CameraNode camNode; // physics camera
    // Walking vars
    private Vector3f walkDirection = new Vector3f(0,0,0);
    private boolean Left = false, Right = false,
                    forward = false,    backward = false;
    private float vy; // Player downwad velocity    
    @Override
    public void simpleInitApp() {
        viewPort.setBackgroundColor(ColorRGBA.White);
        setDisplayFps(false);
        setDisplayStatView(false);

        // *** 1. Start (Create Floor)
        Box b = new Box(5,1,5);
        Geometry floor = new Geometry("floor", b);
        Material mat = new Material(assetManager, 
                "Common/MatDefs/Misc/ShowNormals.j3md");
        floor.setMaterial(mat);
        rootNode.attachChild(floor);
        // *** 1. End
        
        // *** 2. Start (Physics - 3rd line debug)
        bulletAppState = new BulletAppState();
        stateManager.attach(bulletAppState);
        bulletAppState.getPhysicsSpace().enableDebug(assetManager);
        // *** 2. End
        
        // *** 3. Start (floor is rigid)
        scenePhy = new RigidBodyControl(0f);
        floor.addControl(scenePhy);
        bulletAppState.getPhysicsSpace().add(floor);
        // *** 3. End
        
        // *** 4. Start (invisible player)
        playerNode = new Node("the player");
        playerNode.setLocalTranslation(
                new Vector3f(0, 1, 0));
        rootNode.attachChild(playerNode);
        playerControl = new BetterCharacterControl(
                1.5f, 4, 30f);
        playerControl.setJumpForce(new Vector3f(0, 300, 0));
        playerControl.setGravity(new Vector3f(0, -10, 0));
        playerNode.addControl(playerControl);
        bulletAppState.getPhysicsSpace().add(playerControl);
        // *** 4. End
        
        // *** 5. Start (Camera attached to Player)
        camNode = new CameraNode("CamNode", cam);
        camNode.setControlDir(CameraControl.
                              ControlDirection.SpatialToCamera);
        camNode.setLocalTranslation(new Vector3f(0, 4, -6));
        Quaternion quat = new Quaternion();
        quat.lookAt(Vector3f.UNIT_Z, Vector3f.UNIT_Y);
        camNode.setLocalRotation(quat);
        playerNode.attachChild(camNode);
        camNode.setEnabled(true);
        flyCam.setEnabled(false);
        // *** 5. End
        
        // *** 6. Start (Arrow Keys)
        inputManager.addMapping("Forward",
                new KeyTrigger(KeyInput.KEY_UP));
        inputManager.addMapping("Back",
                new KeyTrigger(KeyInput.KEY_DOWN));
        inputManager.addMapping("Left",
                new KeyTrigger(KeyInput.KEY_LEFT));
        inputManager.addMapping("Right",
                new KeyTrigger(KeyInput.KEY_RIGHT));
        inputManager.addListener(this, "Left", 
                "Right","Forward", "Back");
        // *** 6. End
    }

    // *** 7. Start (Walk character)
    @Override
    public void simpleUpdate(float tpf) {
        Vector3f ForwardDir = Vector3f.UNIT_Z;
        Vector3f LeftDir = Vector3f.UNIT_X;
        walkDirection.set(0, 0, 0); 
        if (forward) {
            walkDirection = walkDirection.add(ForwardDir);
        } else if (backward) {
            walkDirection = walkDirection.subtract(ForwardDir);
        }
        if (Left) {
            walkDirection = walkDirection.add(LeftDir);
        } else if (Right) {
            walkDirection = walkDirection.subtract(LeftDir);
        }
        playerControl.setWalkDirection(walkDirection);
        vy = playerControl.getVelocity().y;
        if (vy<-10f) {
            System.out.println("Game over");
        }
    }
    // *** 7. End

    @Override
    public void simpleRender(RenderManager rm) {
    }

    // *** 8. Start (Which key 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("Forward")) {
            forward = isPressed;
        }
        else if (binding.equals("Back")) {
            backward = isPressed;
        }
    }
    // *** 8. End
}


Output:


No comments:

Post a Comment