@Override
    public void simpleInitApp() {
        flyCam.setEnabled(false);
        cam.setLocation(new Vector3f(0.0f, 12.0f, 21.0f));
        viewPort.setBackgroundColor(new ColorRGBA(0.2118f, 0.0824f, 0.6549f, 1.0f));
        
        // init physics
        BulletAppState bulletState = new BulletAppState();
        stateManager.attach(bulletState);
        PhysicsSpace space = bulletState.getPhysicsSpace();
        space.addCollisionListener(this);
        
        // create light
        DirectionalLight sun = new DirectionalLight();
        sun.setDirection((new Vector3f(-0.7f, -0.3f, -0.5f)).normalizeLocal());
        System.out.println("Here We Go: " + sun.getDirection());
        sun.setColor(ColorRGBA.White);
        rootNode.addLight(sun); 
        
        // create materials
        Material materialRed = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
        materialRed.setBoolean("UseMaterialColors",true);
        materialRed.setBoolean("HardwareShadows", true);
        materialRed.setColor("Diffuse", new ColorRGBA(0.9451f, 0.0078f, 0.0314f, 1.0f));
        materialRed.setColor("Specular", ColorRGBA.White);
        materialRed.setFloat("Shininess", 64.0f);
        
        Material materialGreen = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
        materialGreen.setBoolean("UseMaterialColors",true);
        materialGreen.setBoolean("HardwareShadows", true);
        materialGreen.setColor("Diffuse", new ColorRGBA(0.0431f, 0.7725f, 0.0078f, 1.0f));
        materialGreen.setColor("Specular", ColorRGBA.White);
        materialGreen.setFloat("Shininess", 64.0f);
        
        Material logoMaterial = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
        logoMaterial.setBoolean("UseMaterialColors",true);
        logoMaterial.setBoolean("HardwareShadows", true);
        logoMaterial.setTexture("DiffuseMap", assetManager.loadTexture("com/jme3/app/Monkey.png"));
        logoMaterial.setColor("Diffuse", ColorRGBA.White);
        logoMaterial.setColor("Specular", ColorRGBA.White);
        logoMaterial.setFloat("Shininess", 32.0f);
        
        Material materialYellow = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
        materialYellow.setBoolean("UseMaterialColors",true);
        materialYellow.setBoolean("HardwareShadows", true);
        materialYellow.setColor("Diffuse", new ColorRGBA(0.9529f, 0.7843f, 0.0078f, 1.0f));
        materialYellow.setColor("Specular", ColorRGBA.White);
        materialYellow.setFloat("Shininess", 64.0f);
        
        // create level spatial
        // TODO: create your own level mesh
        Node level = new Node("level");
        level.setShadowMode(ShadowMode.CastAndReceive);
        
        Geometry floor = new Geometry("floor", new Box(22.0f, 0.5f, 22.0f));
        floor.setShadowMode(ShadowMode.Receive);
        floor.setLocalTranslation(0.0f, -0.5f, 0.0f);
        floor.setMaterial(materialGreen);
        
        Geometry wallNorth = new Geometry("wallNorth", new Box(22.0f, 2.0f, 0.5f));
        wallNorth.setLocalTranslation(0.0f, 2.0f, 21.5f);
        wallNorth.setMaterial(materialRed);
        
        Geometry wallSouth = new Geometry("wallSouth", new Box(22.0f, 2.0f, 0.5f));
        wallSouth.setLocalTranslation(0.0f, 2.0f, -21.5f);
        wallSouth.setMaterial(materialRed);
        
        Geometry wallEast = new Geometry("wallEast", new Box(0.5f, 2.0f, 21.0f));
        wallEast.setLocalTranslation(-21.5f, 2.0f, 0.0f);
        wallEast.setMaterial(materialRed);
        
        Geometry wallWest = new Geometry("wallWest", new Box(0.5f, 2.0f, 21.0f));
        wallWest.setLocalTranslation(21.5f, 2.0f, 0.0f);
        wallWest.setMaterial(materialRed);
        
        level.attachChild(floor);
        level.attachChild(wallNorth);
        level.attachChild(wallSouth);
        level.attachChild(wallEast);
        level.attachChild(wallWest);
        
        // The easy way: level.addControl(new RigidBodyControl(0));
        
        // create level Shape
        CompoundCollisionShape levelShape = new CompoundCollisionShape();
        BoxCollisionShape floorShape = new BoxCollisionShape(new Vector3f(22.0f, 0.5f, 22.0f));
        BoxCollisionShape wallNorthShape = new BoxCollisionShape(new Vector3f(22.0f, 2.0f, 0.5f));
        BoxCollisionShape wallSouthShape = new BoxCollisionShape(new Vector3f(22.0f, 2.0f, 0.5f));
        BoxCollisionShape wallEastShape = new BoxCollisionShape(new Vector3f(0.5f, 2.0f, 21.0f));
        BoxCollisionShape wallWestShape = new BoxCollisionShape(new Vector3f(0.5f, 2.0f, 21.0f));
        
        levelShape.addChildShape(floorShape, new Vector3f(0.0f, -0.5f, 0.0f));
        levelShape.addChildShape(wallNorthShape, new Vector3f(0.0f, 2.0f, -21.5f));
        levelShape.addChildShape(wallSouthShape, new Vector3f(0.0f, 2.0f, 21.5f));
        levelShape.addChildShape(wallEastShape, new Vector3f(-21.5f, 2.0f, 0.0f));
        levelShape.addChildShape(wallEastShape, new Vector3f(21.5f, 2.0f, 0.0f));
        
        level.addControl(new RigidBodyControl(levelShape, 0));
        
        rootNode.attachChild(level);
        space.addAll(level);
        
        // create Pickups
        // TODO: create your own pickUp mesh
        //       create single mesh for all pickups
        // HINT: think particles.
        pickUps = new Node("pickups");
        
        Quaternion rotation = new Quaternion();
        Vector3f translation = new Vector3f(0.0f, PICKUP_SIZE * 1.5f, -PICKUP_RADIUS);
        int index = 0;
        float amount = FastMath.TWO_PI / PICKUP_COUNT;
        for(float angle = 0; angle < FastMath.TWO_PI; angle += amount) {
            Geometry pickUp = new Geometry("pickUp" + (index++), new Box(PICKUP_SIZE,PICKUP_SIZE, PICKUP_SIZE));
            pickUp.setShadowMode(ShadowMode.CastAndReceive);
            pickUp.setMaterial(materialYellow);
            pickUp.setLocalRotation(rotation.fromAngles(
                    FastMath.rand.nextFloat() * FastMath.TWO_PI,
                    FastMath.rand.nextFloat() * FastMath.TWO_PI,
                    FastMath.rand.nextFloat() * FastMath.TWO_PI));
            
            rotation.fromAngles(0.0f, angle, 0.0f);
            rotation.mult(translation, pickUp.getLocalTranslation());
            pickUps.attachChild(pickUp);
            
            pickUp.addControl(new GhostControl(new SphereCollisionShape(PICKUP_SIZE)));
            
            
            space.addAll(pickUp);
            //space.addCollisionListener(pickUpControl);
        }
        rootNode.attachChild(pickUps);
        
        // Create player
        // TODO: create your own player mesh
        Geometry playerGeometry = new Geometry("player", new Sphere(16, 32, PLAYER_RADIUS));
        playerGeometry.setShadowMode(ShadowMode.CastAndReceive);
        playerGeometry.setLocalTranslation(PLAYER_START.clone());
        playerGeometry.setMaterial(logoMaterial);
        
        // Store control for applying forces
        // TODO: create your own player control
        player = new RigidBodyControl(new SphereCollisionShape(PLAYER_RADIUS), PLAYER_MASS);
        player.setRestitution(PLAYER_REST);
        
        playerGeometry.addControl(player);
        
        rootNode.attachChild(playerGeometry);
        space.addAll(playerGeometry);
        
        inputManager.addMapping(INPUT_MAPPING_FORWARD, new KeyTrigger(KeyInput.KEY_UP)
                , new KeyTrigger(KeyInput.KEY_W));
        inputManager.addMapping(INPUT_MAPPING_BACKWARD, new KeyTrigger(KeyInput.KEY_DOWN)
                , new KeyTrigger(KeyInput.KEY_S));
        inputManager.addMapping(INPUT_MAPPING_LEFT, new KeyTrigger(KeyInput.KEY_LEFT)
                , new KeyTrigger(KeyInput.KEY_A));
        inputManager.addMapping(INPUT_MAPPING_RIGHT, new KeyTrigger(KeyInput.KEY_RIGHT)
                , new KeyTrigger(KeyInput.KEY_D));
        inputManager.addMapping(INPUT_MAPPING_RESET, new KeyTrigger(KeyInput.KEY_R));
        inputManager.addListener(this, INPUT_MAPPING_FORWARD, INPUT_MAPPING_BACKWARD
                , INPUT_MAPPING_LEFT, INPUT_MAPPING_RIGHT, INPUT_MAPPING_RESET);
        
        // init UI
        BitmapText infoText = new BitmapText(guiFont);
        infoText.setText(INFO_MESSAGE);
        guiNode.attachChild(infoText);
        
        scoreText = new BitmapText(guiFont);
        scoreText.setText("Score: 0");
        guiNode.attachChild(scoreText);
        
        messageText = new BitmapText(guiFont);
        messageText.setText(MESSAGE);
        messageText.setLocalScale(0.0f);
        guiNode.attachChild(messageText);
        
        infoText.setLocalTranslation(0.0f, cam.getHeight(), 0.0f);
        scoreText.setLocalTranslation((cam.getWidth() - scoreText.getLineWidth()) / 2.0f,
                scoreText.getLineHeight(), 0.0f);
        messageText.setLocalTranslation((cam.getWidth() - messageText.getLineWidth()) / 2.0f,
                (cam.getHeight() - messageText.getLineHeight()) / 2, 0.0f);
        
        // init shadows
        FilterPostProcessor processor = new FilterPostProcessor(assetManager);
        DirectionalLightShadowFilter filter = new DirectionalLightShadowFilter(assetManager, 2048, 1);
        filter.setLight(sun);
        processor.addFilter(filter);
        viewPort.addProcessor(processor);
        
    }
Physics based marble game.

@author SkidRunner (Mark E. Picknell)
jme3-examples/src/main/java/jme3test/games/RollingTheMonkey.java