BaseGame into gamestates

Hi,



I have been using BaseGame for my program so far. At the moment I have a chase camera, that follows and md5 model, a few lights, and input system, a model for the level and am using simplePhysics to create and octree for collsion detection.



So I want to move onto using game stats for having a start menu, pause menu and other stuff lik that.



I looked at TestGameStateSystem, was happy to see that it used BaseGame, so for a test I tried to keep the menu state as it was and change the ingamestate to be my current game.



I copied all the code from initGame from my program into the IngameState's constuctor, then put all the methods that it needed, then the update stufff from my program into the stateUpdate. I also changed the TestGameStateSystem's initsystem method to have my own programs setting.



So, when I run this, I get the original MenuState come up fine, but when I press enter to go to ingamestate, it seems to load everything fine looking at the console, also its updateing my plaers positions etc, I can see this in the console. But I'm not seeing anything being rendered.



I think this is a camera issue, but I'm not really sure,



Can anyone give me some pointers based on the info I have provided?





Edit - ok so I had to add and extra part to the ingamestates constructor to attach my scene to the rootnode. Cameras not working properly but at least I have somthing I can see to work with.

Good to see you made some progress!

Which part did you add? Got the same problem… Everything attached correctly, but I cannot see anything…

/*
 * Copyright (c) 2003-2006 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package prototyp2;

import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.HashMap;

import javax.swing.ImageIcon;

import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.ChaseCamera;
import com.jme.input.FirstPersonHandler;
import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.light.PointLight;
import com.jme.math.FastMath;
import com.jme.math.Matrix3f;
import com.jme.math.Plane;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.renderer.pass.BasicPassManager;
import com.jme.renderer.pass.RenderPass;
import com.jme.scene.Node;
import com.jme.scene.SceneElement;
import com.jme.scene.Skybox;
import com.jme.scene.Spatial;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.CullState;
import com.jme.scene.state.FogState;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.util.GameTaskQueue;
import com.jme.util.GameTaskQueueManager;
import com.jme.util.TextureManager;
import com.jme.util.Timer;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.effects.water.WaterRenderPass;
import com.jmex.game.state.CameraGameState;
import com.jmex.game.state.GameStateManager;
import com.jmex.terrain.TerrainBlock;
import com.jmex.terrain.util.ProceduralTextureGenerator;
import com.jmex.terrain.util.RawHeightMap;

import prototyp2.Main;
import prototyp2.SurfBoardHandler;


public class WaterState extends CameraGameState {

   private WaterRenderPass waterEffectRenderPass;
   private Skybox skybox;
   private Quad waterQuad;
   private float farPlane = 10000.0f;
   private float textureScale = 0.02f;
   protected LightState lightState;
   private TerrainBlock tb;   
   protected Timer timer;
   private Camera cam;
   private Node rootNode;
   protected BasicPassManager pManager;
   private DisplaySystem display;
   private Surfboard player;
    private float agl;
   private Vector3f normal = new Vector3f();
   private ChaseCamera chaser;
   protected InputHandler input2;
   
   public WaterState(String name) {
      super(name);
      
      pManager = new BasicPassManager();
      rootNode = new Node( "rootNode" );
      
      display = DisplaySystem.getDisplaySystem();
        ZBufferState buf = display.getRenderer().createZBufferState();
        buf.setEnabled( true );
        buf.setFunction( ZBufferState.CF_LEQUAL );
        rootNode.setRenderState( buf );

        PointLight light = new PointLight();
        light.setDiffuse( new ColorRGBA( 0.75f, 0.75f, 0.75f, 0.75f ) );
        light.setAmbient( new ColorRGBA( 0.5f, 0.5f, 0.5f, 1.0f ) );
        light.setLocation( new Vector3f( 100, 100, 100 ) );
        light.setEnabled( true );

        lightState = display.getRenderer().createLightState();
        lightState.setEnabled( true );
        lightState.attach( light );
        rootNode.setRenderState( lightState );
       
        cam = display.getRenderer().createCamera( display.getWidth(),
                display.getHeight() );
            
        cam.setFrustumPerspective( 45.0f, (float) display.getWidth() / (float) display.getHeight(), 1f, farPlane );
      cam.setLocation( new Vector3f( 100, 50, 100 ) );
      cam.lookAt( new Vector3f( 0, 0, 0 ), Vector3f.UNIT_Y );
      cam.update();

       FirstPersonHandler firstPersonHandler = new FirstPersonHandler( cam, 50,
                   1 );
           input2 = firstPersonHandler;

      setupFog();
      buildTerrain();
      buildPlayer();
      buildChaseCamera();
      buildInput();
      
      
      
      Node reflectedNode = new Node( "reflectNode" );

      buildSkyBox();
      reflectedNode.attachChild( skybox );
      rootNode.attachChild( reflectedNode );

      waterEffectRenderPass = new WaterRenderPass( cam, 4, false, true );
      waterEffectRenderPass.setWaterPlane( new Plane( new Vector3f( 0.0f, 1.0f, 0.0f ), 0.0f ) );

      waterQuad = new Quad( "waterQuad", 1, 1 );
      FloatBuffer normBuf = waterQuad.getNormalBuffer( 0 );
      normBuf.clear();
      normBuf.put( 0 ).put( 1 ).put( 0 );
      normBuf.put( 0 ).put( 1 ).put( 0 );
      normBuf.put( 0 ).put( 1 ).put( 0 );
      normBuf.put( 0 ).put( 1 ).put( 0 );

      waterEffectRenderPass.setWaterEffectOnSpatial( waterQuad );
      rootNode.attachChild( waterQuad );

      waterEffectRenderPass.setReflectedScene( reflectedNode );
      waterEffectRenderPass.setSkybox( skybox );
      pManager.add( waterEffectRenderPass );

      RenderPass rootPass = new RenderPass();
      rootPass.add( rootNode );
      pManager.add( rootPass );

      rootNode.setCullMode( SceneElement.CULL_NEVER);
      rootNode.setRenderQueueMode( Renderer.QUEUE_OPAQUE );
       
        rootNode.updateGeometricState( 0.0f, true );
        rootNode.updateRenderState();
      
   }
   /**
    * Gets called every time the game state manager switches to this game state.
    * Sets the window title.
    */
   public void onActivate() {
      DisplaySystem.getDisplaySystem().
         setTitle("Test Game State System - Ingame State");
      super.onActivate();
   }
   

   
   protected void stateUpdate(float tpf) {
      //input.update(tpf);
      if (KeyBindingManager.getKeyBindingManager().
            isValidCommand("exit", false)) {
         // Here we switch to the menu state which is already loaded
         GameStateManager.getInstance().activateChildNamed("menu");
         // And remove this state, because we don't want to keep it in memory.
         GameStateManager.getInstance().detachChild("ingame");
      }
      
      skybox.getLocalTranslation().set( cam.getLocation() );
      skybox.updateGeometricState( 0.0f, true );

      Vector3f transVec = new Vector3f( cam.getLocation().x, waterEffectRenderPass.getWaterHeight(), cam.getLocation().z );

      setTextureCoords( 0, transVec.x, -transVec.z, textureScale );

      setVertexCoords( transVec.x, transVec.y, transVec.z );
      
      GameTaskQueueManager.getManager().getQueue(GameTaskQueue.UPDATE).execute();
      
      chaser.update(tpf);
      
      System.out.println(player.getLocalTranslation());
      
      
      //We don't want the chase camera to go below the world, so always keep
        //it 2 units above the level.
        if(cam.getLocation().y < (tb.getHeight(cam.getLocation()))) {
            cam.getLocation().y = tb.getHeight(cam.getLocation()) ;
            cam.update();
        }
        //make sure that if the player left the level we don't crash. When we add collisions,
        //the fence will do its job and keep the player inside.
        float characterMinHeight = 0.0f + agl;
        if (!Float.isInfinite(characterMinHeight) && !Float.isNaN(characterMinHeight)) {
            player.getLocalTranslation().y = characterMinHeight;
        }
        //get the normal of the terrain at our current location. We then apply it to the up vector
        //of the player.
        tb.getSurfaceNormal(player.getLocalTranslation(), normal);
        if(normal != null) {
            player.rotateUpTo(normal);
        }
       
        input2.update( tpf );
             
      rootNode.updateGeometricState(tpf, true);
      pManager.updatePasses(tpf);
   }
   
   private void buildSkyBox() {
      skybox = new Skybox( "skybox", 10, 10, 10 );

      String dir = "data/skybox/";
      Texture north = TextureManager.loadTexture(
            Main.class.getClassLoader().getResource(
                  dir + "1.jpg" ),
            Texture.MM_LINEAR,
            Texture.FM_LINEAR );
      Texture south = TextureManager.loadTexture(
            Main.class.getClassLoader().getResource(
                  dir + "3.jpg" ),
            Texture.MM_LINEAR,
            Texture.FM_LINEAR );
      Texture east = TextureManager.loadTexture(
            Main.class.getClassLoader().getResource(
                  dir + "2.jpg" ),
            Texture.MM_LINEAR,
            Texture.FM_LINEAR );
      Texture west = TextureManager.loadTexture(
            Main.class.getClassLoader().getResource(
                  dir + "4.jpg" ),
            Texture.MM_LINEAR,
            Texture.FM_LINEAR );
      Texture up = TextureManager.loadTexture(
            Main.class.getClassLoader().getResource(
                  dir + "6.jpg" ),
            Texture.MM_LINEAR,
            Texture.FM_LINEAR );
      Texture down = TextureManager.loadTexture(
            Main.class.getClassLoader().getResource(
                  dir + "5.jpg" ),
            Texture.MM_LINEAR,
            Texture.FM_LINEAR );

      skybox.setTexture( Skybox.NORTH, north );
      skybox.setTexture( Skybox.WEST, west );
      skybox.setTexture( Skybox.SOUTH, south );
      skybox.setTexture( Skybox.EAST, east );
      skybox.setTexture( Skybox.UP, up );
      skybox.setTexture( Skybox.DOWN, down );
      skybox.preloadTextures();

      CullState cullState = display.getRenderer().createCullState();
      cullState.setCullMode( CullState.CS_NONE );
      cullState.setEnabled( true );
      skybox.setRenderState( cullState );

      ZBufferState zState = display.getRenderer().createZBufferState();
      zState.setEnabled( false );
      skybox.setRenderState( zState );

      FogState fs = display.getRenderer().createFogState();
      fs.setEnabled( false );
      skybox.setRenderState( fs );

      skybox.setLightCombineMode( LightState.OFF );
      skybox.setCullMode( SceneElement.CULL_NEVER );
      skybox.setTextureCombineMode( TextureState.REPLACE );
      skybox.updateRenderState();

      skybox.lockBounds();
      skybox.lockMeshes();
   }

   private void buildTerrain(){
       
      RawHeightMap heightMap = new RawHeightMap(Main.class.getClassLoader().getResource(
      "data/terrain/heights2.raw").getFile(), 129,
      RawHeightMap.FORMAT_16BITLE, false);

      Vector3f terrainScale = new Vector3f(20, 0.001f, 20);
      heightMap.setHeightScale(0.0001f);
        // create a terrainblock
         tb = new TerrainBlock("Terrain", heightMap.getSize(), terrainScale,
                heightMap.getHeightMap(), new Vector3f(0, -9, 0), false);

        tb.setModelBound(new BoundingBox());
        tb.updateModelBound();
       
          
        // generate a terrain texture with 2 textures
        ProceduralTextureGenerator pt = new ProceduralTextureGenerator(
                heightMap);
        pt.addTexture(new ImageIcon(Main.class.getClassLoader()
                .getResource("data/texture/nicegrass.jpg")), -128, 0, 384);
       
        pt.createTexture(128);
              
        rootNode.attachChild(tb);
             
   }
   
   private void setVertexCoords( float x, float y, float z ) {
      FloatBuffer vertBuf = waterQuad.getVertexBuffer( 0 );
      vertBuf.clear();

      vertBuf.put( x - farPlane ).put( y ).put( z - farPlane );
      vertBuf.put( x - farPlane ).put( y ).put( z + farPlane );
      vertBuf.put( x + farPlane ).put( y ).put( z + farPlane );
      vertBuf.put( x + farPlane ).put( y ).put( z - farPlane );
   }

   private void setTextureCoords( int buffer, float x, float y, float textureScale ) {
      x *= textureScale * 0.5f;
      y *= textureScale * 0.5f;
      textureScale = farPlane * textureScale;
      FloatBuffer texBuf;
      texBuf = waterQuad.getTextureBuffer( 0, buffer );
      texBuf.clear();
      texBuf.put( x ).put( textureScale + y );
      texBuf.put( x ).put( y );
      texBuf.put( textureScale + x ).put( y );
      texBuf.put( textureScale + x ).put( textureScale + y );
   }

   private void setupFog() {
      FogState fogState = display.getRenderer().createFogState();
      fogState.setDensity( 1.0f );
      fogState.setEnabled( true );
      fogState.setColor( new ColorRGBA( 1.0f, 1.0f, 1.0f, 1.0f ) );
      fogState.setEnd( farPlane );
      fogState.setStart( farPlane / 10.0f );
      fogState.setDensityFunction( FogState.DF_LINEAR );
      fogState.setApplyFunction( FogState.AF_PER_VERTEX );
      rootNode.setRenderState( fogState );
   }

   private void buildPlayer(){
       Spatial model = null;
           try {
               java.net.URL bikeFile = Main.class.getClassLoader().getResource("data/model/bike.jme");
               BinaryImporter importer = new BinaryImporter();
               model = (Spatial)importer.load(bikeFile.openStream());
               model.setModelBound(new BoundingBox());
               model.updateModelBound();
               //scale it to be MUCH smaller than it is originally
               model.setLocalScale(.015f);
           } catch (IOException e) {
              
           }
          
           //set the vehicles attributes (these numbers can be thought
           //of as Unit/Second).
           player = new Surfboard("Player Node", model);
           player.setAcceleration(15);
           player.setTurnSpeed(4.5f);
           player.setWeight(25);
           player.setMaxSpeed(155);
           player.setMinSpeed(0);
           player.setLocalRotation(new Matrix3f(0,0,1.0f,0,1.0f,0,-1.0f,0,0));
           player.setLocalTranslation(new Vector3f(0,0, (float)display.getWidth()* 1.4f));
           rootNode.attachChild(player);
           rootNode.updateGeometricState(0, true);
           //we now store this initial value, because we are rotating the wheels the bounding box will
           //change each frame.
           agl = ((BoundingBox)player.getWorldBound()).yExtent;
           player.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
   }

   private void buildChaseCamera() {
        HashMap<String, Object> props = new HashMap<String, Object>();
        props.put(ChaseCamera.PROP_INITIALSPHERECOORDS, new Vector3f(150f, 0, 30 * FastMath.DEG_TO_RAD));
        props.put(ChaseCamera.PROP_DAMPINGK, "4");
        props.put(ChaseCamera.PROP_SPRINGK, "9");
    //    props.put(ChaseCamera.DEFAULT_STAYBEHINDTARGET, true);
        props.put( ChaseCamera.PROP_TARGETOFFSET, new Vector3f(0f, 0f, 0f) );
        chaser = new ChaseCamera(cam, player, props);
      
        chaser.getMouseLook().setEnabled(false);
        chaser.setMaxDistance(25);
        chaser.setMinDistance(0);
       // chaser.getMouseLook().setLookMouseButton( 1 );
    }

   private void buildInput() {
        input2 = new SurfBoardHandler(player, display.getDisplayRenderer());
    }
   
}



package prototyp2;

import java.util.logging.Level;
import java.util.logging.Logger;
import prototyp2.MenuState;

import com.jme.app.AbstractGame;
import com.jme.app.BaseGame;
import com.jme.input.KeyInput;
import com.jme.input.MouseInput;
import com.jme.renderer.Camera;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.Timer;
import com.jmex.game.state.GameState;
import com.jmex.game.state.GameStateManager;


public class Main extends BaseGame{
   private static final Logger logger = Logger.getLogger(Main.class.getName());
   
   private static AbstractGame instance;
   private Timer timer;
   private float tpf;
   public Camera cam;
   
   protected final void update(float inerpolation){
      timer.update();
      tpf = timer.getTimePerFrame();
      
      
      //Update the current game state
      GameStateManager.getInstance().update(tpf);
   }
   
   protected final void render(float interpolation){
      display.getRenderer().clearBuffers();
      GameStateManager.getInstance().render(tpf);
   }
   
   
   protected final void initSystem(){
      try{
         display = DisplaySystem.getDisplaySystem(properties.getRenderer());
         
         display.createWindow(
               properties.getWidth(),
               properties.getHeight(),
               properties.getDepth(),
               properties.getFreq(),
               properties.getFullscreen());
      } catch (JmeException e){
         logger.log(Level.SEVERE, "Could not create displaySystem", e);
         System.exit(1);
      }
      
      timer = Timer.getTimer();
      cam = display.getRenderer().createCamera( display.getWidth(),
                 display.getHeight() );

      }
   
   protected final void initGame(){
      instance = this;
      display.setTitle("Pororoca - Surfing Different Prototyp2");
      
      
      
      GameStateManager.create();
      
      GameState menu = new MenuState("menu");
      menu.setActive(true);
      GameStateManager.getInstance().attachChild(menu);
      
      
   }

   protected void reinit() {
   }
   
   protected void cleanup(){
      logger.info("Cleaning up resources.");
      
      GameStateManager.getInstance().cleanup();
      
      KeyInput.destroyIfInitalized();
      MouseInput.destroyIfInitalized();
   }
   
   public static void main(String[] args){
      Main app = new Main();
      app.setDialogBehaviour(AbstractGame.ALWAYS_SHOW_PROPS_DIALOG);
      app.start();
   }
   
   public static void exit() {
      instance.finish();
   }
   
}



So I got a Main class and a WaterState class which is basically the IngameState!  But when I start the Main class I get the menu, pressing enter starts the game (WaterState).... but I can't see anything! Should work, because when I press W A S or D the player gets different translations values...

it must be something with the light ?!?!

I don't see in your code where you instantiate and attach the WaterState. Where is that?

Well I have in MenuHandler this code:


 private class EnterAction extends InputAction {
        public void performAction( InputActionEvent evt ) {
            GameState ingame = new WaterState("Pororocas Ingame");
            ingame.setActive(true);
            GameStateManager.getInstance().attachChild(ingame);
            myState.setActive(false); // Deactivate this (the menu) state.
        }
    }



So when I press the enter button it creates the WaterState and attaches it to the GameStateManager! Thought this was enough?!?

Can you give me a little hint about where to find add the missing instantiate?

Lets focus on your WaterState first. You define a node named rootNode and attach everything in your WaterState scene to it. I see your updateState() method to update your scene, but where do you render your rootNode?

So is it right to add 



rootNode.updateRenderState(); 



somewhere?  Really not getting it ;-(  Sorry!  I added it to the init and update part but still black screen!  Is it another method?



Thanks

doy ou do anywhere DisplaySystem.GetDisplaySystem().GetRenderer().draw(yournode) in the render funktion?

Hi,



I tried adding the DisplaySystem stuff and the display.getRenderer().draw stuff, but nothing really happens. Still staying black! Added it first in the WaterState class and after this not working in the render() of the Main function. Maybe it is a problem with my light?



Thanks again, Rapidm

Hi again…



I honestly been trying to get this to work in the past few days! I just can't find the problem! Maybe someone could look over the code and help me out? Would really really love that :wink:


package prototyp2;

import java.util.logging.Level;
import java.util.logging.Logger;
import prototyp2.MenuState;

import com.jme.app.AbstractGame;
import com.jme.app.BaseGame;
import com.jme.input.KeyInput;
import com.jme.input.MouseInput;
import com.jme.renderer.Camera;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.Timer;
import com.jmex.game.state.GameState;
import com.jmex.game.state.GameStateManager;


public class Main extends BaseGame{
   private static final Logger logger = Logger.getLogger(Main.class.getName());
   
   private static AbstractGame instance;
   private Timer timer;
   private float tpf;
   public Camera cam;
   private WaterState ingame;
   
   protected final void update(float interpolation){
      timer.update();
      tpf = timer.getTimePerFrame();
      
      //Update the current game state
      GameStateManager.getInstance().update(tpf);
      
      
   }
   
   protected final void render(float interpolation){
      display.getRenderer().clearBuffers();
      GameStateManager.getInstance().render(tpf);
   }
   
   
   protected final void initSystem(){
      try{
         display = DisplaySystem.getDisplaySystem(properties.getRenderer());
         
         display.createWindow(
               properties.getWidth(),
               properties.getHeight(),
               properties.getDepth(),
               properties.getFreq(),
               properties.getFullscreen());
      } catch (JmeException e){
         logger.log(Level.SEVERE, "Could not create displaySystem", e);
         System.exit(1);
      }
      
      timer = Timer.getTimer();
      cam = display.getRenderer().createCamera( display.getWidth(),
                 display.getHeight() );

      }
   
   protected final void initGame(){
      instance = this;
      display.setTitle("Pororoca - Surfing Different Prototyp2");
            
      GameStateManager.create();
      
      GameState menu = new MenuState("menu");
      menu.setActive(true);
      GameStateManager.getInstance().attachChild(menu);
      
      GameState gameover = new GameOverState("gameover");
      gameover.setActive(false);
      GameStateManager.getInstance().attachChild(gameover);
      
      GameState ingame = new WaterState("ingame");
      ingame.setActive(false);
      GameStateManager.getInstance().attachChild(ingame);
   }

   protected void reinit() {
   }
   
   protected void cleanup(){
      logger.info("Cleaning up resources.");
      
      GameStateManager.getInstance().cleanup();
      
      KeyInput.destroyIfInitalized();
      MouseInput.destroyIfInitalized();
   }
   
   public static void main(String[] args){
      Main app = new Main();
      app.setDialogBehaviour(AbstractGame.ALWAYS_SHOW_PROPS_DIALOG);
      app.start();
   }
   
   public static void exit() {
      instance.finish();
   }
      
}



MenuState

/*
 * Copyright (c) 2003-2006 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package prototyp2;

import com.jme.image.Texture;
import com.jme.input.AbsoluteMouse;
import com.jme.input.InputHandler;
import com.jme.input.Mouse;
import com.jme.math.Vector3f;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.Text;
import com.jme.scene.state.AlphaState;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jmex.game.state.CameraGameState;
import com.jmex.game.state.GameState;


public class MenuState extends CameraGameState {
   
   /** The cursor node which holds the mouse gotten from input. */
   private Node cursor;
   
   /** Our display system. */
   private DisplaySystem display;

    private Text text;

    private InputHandler input;
    private Mouse mouse;

    public MenuState(String name) {
        super(name);

        display = DisplaySystem.getDisplaySystem();
        initInput();
        initCursor();
        initText();

        rootNode.setLightCombineMode(LightState.OFF);
        rootNode.setRenderQueueMode(Renderer.QUEUE_ORTHO);
        rootNode.updateRenderState();
        rootNode.updateGeometricState(0, true);
    }
   
   /**
    * @see com.jmex.game.state.CameraGameState#onActivate()
    */
   public void onActivate() {
      display.setTitle("Test Game State System - Menu State");
      super.onActivate();
   }
   
   /**
    * Inits the input handler we will use for navigation of the menu.
    */
   protected void initInput() {
      input = new MenuHandler( this );

        DisplaySystem display = DisplaySystem.getDisplaySystem();
        mouse = new AbsoluteMouse("Mouse Input", display.getWidth(),
                display.getHeight());
        mouse.registerWithInputHandler( input );
   }
   
   /**
    * Creates a pretty cursor.
    */
   private void initCursor() {      
      Texture texture =
           TextureManager.loadTexture(
                  MenuState.class.getClassLoader().getResource(
                  "jmetest/data/cursor/cursor1.png"),
                  Texture.MM_LINEAR_LINEAR,
                  Texture.FM_LINEAR);
      
      TextureState ts = display.getRenderer().createTextureState();
      ts.setEnabled(true);
      ts.setTexture(texture);
      
      AlphaState alpha = display.getRenderer().createAlphaState();
      alpha.setBlendEnabled(true);
      alpha.setSrcFunction(AlphaState.SB_SRC_ALPHA);
      alpha.setDstFunction(AlphaState.DB_ONE);
      alpha.setTestEnabled(true);
      alpha.setTestFunction(AlphaState.TF_GREATER);
      alpha.setEnabled(true);
      
      mouse.setRenderState(ts);
        mouse.setRenderState(alpha);
        mouse.setLocalScale(new Vector3f(1, 1, 1));
      
      cursor = new Node("Cursor");
      cursor.attachChild( mouse );
      
      rootNode.attachChild(cursor);
   }
   
   /**
    * Inits the button placed at the center of the screen.
    */
   private void initText() {
        text = Text.createDefaultTextLabel( "info" );
        text.print( "Please press enter to start the game" );
        text.getLocalTranslation().set( 100, 100, 0 );
      
        rootNode.attachChild( text );
   }
   
   /**
    * Updates input and button.
    *
    * @param tpf The time since last frame.
    * @see GameState#update(float)
    */
   protected void stateUpdate(float tpf) {
      input.update(tpf);
      // Check if the button has been pressed.
      rootNode.updateGeometricState(tpf, true);
   }
   
}








RapidM

And the WaterState file (I guess there should be the problem): 


/*
 * Copyright (c) 2003-2006 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package prototyp2;

import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.HashMap;

import javax.swing.ImageIcon;

import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.ChaseCamera;
import com.jme.input.FirstPersonHandler;
import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.light.PointLight;
import com.jme.math.FastMath;
import com.jme.math.Matrix3f;
import com.jme.math.Plane;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.renderer.pass.BasicPassManager;
import com.jme.renderer.pass.RenderPass;
import com.jme.scene.Node;
import com.jme.scene.SceneElement;
import com.jme.scene.Skybox;
import com.jme.scene.Spatial;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.CullState;
import com.jme.scene.state.FogState;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.util.GameTaskQueue;
import com.jme.util.GameTaskQueueManager;
import com.jme.util.TextureManager;
import com.jme.util.Timer;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.effects.water.WaterRenderPass;
import com.jmex.game.state.CameraGameState;
import com.jmex.game.state.GameStateManager;
import com.jmex.terrain.TerrainBlock;
import com.jmex.terrain.util.ProceduralTextureGenerator;
import com.jmex.terrain.util.RawHeightMap;

import prototyp2.Main;
import prototyp2.SurfBoardHandler;


public class WaterState extends CameraGameState {

   private WaterRenderPass waterEffectRenderPass;
   private Skybox skybox;
   private Quad waterQuad;
   private float farPlane = 10000.0f;
   private float textureScale = 0.02f;
   protected LightState lightState;
   private TerrainBlock tb;   
   protected Timer timer;
   private Camera cam;
   private Node rootNode;
   protected BasicPassManager pManager;
   private DisplaySystem display;
   private Surfboard player;
    private float agl;
   private Vector3f normal = new Vector3f();
   private ChaseCamera chaser;
   protected InputHandler input2;
   
   public WaterState(String name) {
      super(name);
      
      pManager = new BasicPassManager();
      rootNode = new Node( "rootNode" );
      
      display = DisplaySystem.getDisplaySystem();
        ZBufferState buf = display.getRenderer().createZBufferState();
        buf.setEnabled( true );
        buf.setWritable(true);
        buf.setFunction( ZBufferState.CF_LEQUAL );
        rootNode.setRenderState( buf );

        PointLight light = new PointLight();
        light.setDiffuse( new ColorRGBA( 0.75f, 0.75f, 0.75f, 0.75f ) );
        light.setAmbient( new ColorRGBA( 0.5f, 0.5f, 0.5f, 1.0f ) );
        light.setLocation( new Vector3f( 100, 100, 100 ) );
        light.setEnabled( true );

        lightState = display.getRenderer().createLightState();
        lightState.setEnabled( true );
        lightState.attach( light );
        rootNode.setRenderState( lightState );
       
        cam = display.getRenderer().createCamera( display.getWidth(),
                display.getHeight() );
            
        cam.setFrustumPerspective( 45.0f, (float) display.getWidth() / (float) display.getHeight(), 1f, farPlane );
      cam.setLocation( new Vector3f( 100, 50, 100 ) );
      cam.lookAt( new Vector3f( 0, 0, 0 ), Vector3f.UNIT_Y );
      cam.update();

       FirstPersonHandler firstPersonHandler = new FirstPersonHandler( cam, 50,
                   1 );
           input2 = firstPersonHandler;

      setupFog();
      buildTerrain();
      buildPlayer();
      buildChaseCamera();
      buildInput();

      Node reflectedNode = new Node( "reflectNode" );

      buildSkyBox();
      reflectedNode.attachChild( skybox );
      rootNode.attachChild( reflectedNode );

      waterEffectRenderPass = new WaterRenderPass( cam, 4, false, true );
      waterEffectRenderPass.setWaterPlane( new Plane( new Vector3f( 0.0f, 1.0f, 0.0f ), 0.0f ) );

      waterQuad = new Quad( "waterQuad", 1, 1 );
      FloatBuffer normBuf = waterQuad.getNormalBuffer( 0 );
      normBuf.clear();
      normBuf.put( 0 ).put( 1 ).put( 0 );
      normBuf.put( 0 ).put( 1 ).put( 0 );
      normBuf.put( 0 ).put( 1 ).put( 0 );
      normBuf.put( 0 ).put( 1 ).put( 0 );

      waterEffectRenderPass.setWaterEffectOnSpatial( waterQuad );
      rootNode.attachChild( waterQuad );

      waterEffectRenderPass.setReflectedScene( reflectedNode );
      waterEffectRenderPass.setSkybox( skybox );
      pManager.add( waterEffectRenderPass );

      RenderPass rootPass = new RenderPass();
      rootPass.add( rootNode );
      pManager.add( rootPass );

      rootNode.setCullMode( SceneElement.CULL_NEVER);
      rootNode.setRenderQueueMode( Renderer.QUEUE_OPAQUE );
        rootNode.updateGeometricState( 0, true );
        rootNode.updateRenderState(); 
       
        rootNode.draw(display.getRenderer());
   }
   /**
    * Gets called every time the game state manager switches to this game state.
    * Sets the window title.
    */
   public void onActivate() {
      DisplaySystem.getDisplaySystem().
         setTitle("Test Game State System - Ingame State");
      super.onActivate();
   }
   

   
   protected void stateUpdate(float tpf) {
      //input.update(tpf);
      if (KeyBindingManager.getKeyBindingManager().
            isValidCommand("exit", false)) {
         // Here we switch to the menu state which is already loaded
         GameStateManager.getInstance().activateChildNamed("menu");
         // And remove this state, because we don't want to keep it in memory.
         GameStateManager.getInstance().detachChild("ingame");
      }
      if (KeyBindingManager.getKeyBindingManager().
            isValidCommand("gameover", false)) {
         // Here we switch to the menu state which is already loaded
         GameStateManager.getInstance().activateChildNamed("gameover");
         // And remove this state, because we don't want to keep it in memory.
         GameStateManager.getInstance().detachChild("ingame");
      }
      
      skybox.getLocalTranslation().set( cam.getLocation() );
      skybox.updateGeometricState( 0.0f, true );

      Vector3f transVec = new Vector3f( cam.getLocation().x, waterEffectRenderPass.getWaterHeight(), cam.getLocation().z );

      setTextureCoords( 0, transVec.x, -transVec.z, textureScale );

      setVertexCoords( transVec.x, transVec.y, transVec.z );
      
      GameTaskQueueManager.getManager().getQueue(GameTaskQueue.UPDATE).execute();
      
      chaser.update(tpf);
      
      System.out.println(player.getLocalTranslation());
      
      
      //We don't want the chase camera to go below the world, so always keep
        //it 2 units above the level.
        if(cam.getLocation().y < (tb.getHeight(cam.getLocation()))) {
            cam.getLocation().y = tb.getHeight(cam.getLocation()) ;
            cam.update();
        }
        //make sure that if the player left the level we don't crash. When we add collisions,
        //the fence will do its job and keep the player inside.
        float characterMinHeight = 0.0f + agl;
        if (!Float.isInfinite(characterMinHeight) && !Float.isNaN(characterMinHeight)) {
            player.getLocalTranslation().y = characterMinHeight;
        }
        //get the normal of the terrain at our current location. We then apply it to the up vector
        //of the player.
        tb.getSurfaceNormal(player.getLocalTranslation(), normal);
        if(normal != null) {
            player.rotateUpTo(normal);
        }
       
        input2.update( tpf );
       
             
      rootNode.updateGeometricState(tpf, true);
      pManager.updatePasses(tpf);
      
      rootNode.updateRenderState();
      display.getRenderer().draw(rootNode);
   }
   
   private void buildSkyBox() {
      skybox = new Skybox( "skybox", 10, 10, 10 );

      String dir = "data/skybox/";
      Texture north = TextureManager.loadTexture(
            Main.class.getClassLoader().getResource(
                  dir + "1.jpg" ),
            Texture.MM_LINEAR,
            Texture.FM_LINEAR );
      Texture south = TextureManager.loadTexture(
            Main.class.getClassLoader().getResource(
                  dir + "3.jpg" ),
            Texture.MM_LINEAR,
            Texture.FM_LINEAR );
      Texture east = TextureManager.loadTexture(
            Main.class.getClassLoader().getResource(
                  dir + "2.jpg" ),
            Texture.MM_LINEAR,
            Texture.FM_LINEAR );
      Texture west = TextureManager.loadTexture(
            Main.class.getClassLoader().getResource(
                  dir + "4.jpg" ),
            Texture.MM_LINEAR,
            Texture.FM_LINEAR );
      Texture up = TextureManager.loadTexture(
            Main.class.getClassLoader().getResource(
                  dir + "6.jpg" ),
            Texture.MM_LINEAR,
            Texture.FM_LINEAR );
      Texture down = TextureManager.loadTexture(
            Main.class.getClassLoader().getResource(
                  dir + "5.jpg" ),
            Texture.MM_LINEAR,
            Texture.FM_LINEAR );

      skybox.setTexture( Skybox.NORTH, north );
      skybox.setTexture( Skybox.WEST, west );
      skybox.setTexture( Skybox.SOUTH, south );
      skybox.setTexture( Skybox.EAST, east );
      skybox.setTexture( Skybox.UP, up );
      skybox.setTexture( Skybox.DOWN, down );
      skybox.preloadTextures();

      CullState cullState = display.getRenderer().createCullState();
      cullState.setCullMode( CullState.CS_NONE );
      cullState.setEnabled( true );
      skybox.setRenderState( cullState );

      ZBufferState zState = display.getRenderer().createZBufferState();
      zState.setEnabled( false );
      skybox.setRenderState( zState );

      FogState fs = display.getRenderer().createFogState();
      fs.setEnabled( false );
      skybox.setRenderState( fs );

      skybox.setLightCombineMode( LightState.OFF );
      skybox.setCullMode( SceneElement.CULL_NEVER );
      skybox.setTextureCombineMode( TextureState.REPLACE );
      skybox.updateRenderState();

      skybox.lockBounds();
      skybox.lockMeshes();
   }

   private void buildTerrain(){
       
      RawHeightMap heightMap = new RawHeightMap(Main.class.getClassLoader().getResource(
      "data/terrain/heights2.raw").getFile(), 129,
      RawHeightMap.FORMAT_16BITLE, false);

      Vector3f terrainScale = new Vector3f(20, 0.001f, 20);
      heightMap.setHeightScale(0.0001f);
        // create a terrainblock
         tb = new TerrainBlock("Terrain", heightMap.getSize(), terrainScale,
                heightMap.getHeightMap(), new Vector3f(0, -9, 0), false);

        tb.setModelBound(new BoundingBox());
        tb.updateModelBound();
       
          
        // generate a terrain texture with 2 textures
        ProceduralTextureGenerator pt = new ProceduralTextureGenerator(
                heightMap);
        pt.addTexture(new ImageIcon(Main.class.getClassLoader()
                .getResource("data/texture/nicegrass.jpg")), -128, 0, 384);
       
        pt.createTexture(128);
              
        rootNode.attachChild(tb);
             
   }
   
   private void setVertexCoords( float x, float y, float z ) {
      FloatBuffer vertBuf = waterQuad.getVertexBuffer( 0 );
      vertBuf.clear();

      vertBuf.put( x - farPlane ).put( y ).put( z - farPlane );
      vertBuf.put( x - farPlane ).put( y ).put( z + farPlane );
      vertBuf.put( x + farPlane ).put( y ).put( z + farPlane );
      vertBuf.put( x + farPlane ).put( y ).put( z - farPlane );
   }

   private void setTextureCoords( int buffer, float x, float y, float textureScale ) {
      x *= textureScale * 0.5f;
      y *= textureScale * 0.5f;
      textureScale = farPlane * textureScale;
      FloatBuffer texBuf;
      texBuf = waterQuad.getTextureBuffer( 0, buffer );
      texBuf.clear();
      texBuf.put( x ).put( textureScale + y );
      texBuf.put( x ).put( y );
      texBuf.put( textureScale + x ).put( y );
      texBuf.put( textureScale + x ).put( textureScale + y );
   }

   private void setupFog() {
      FogState fogState = display.getRenderer().createFogState();
      fogState.setDensity( 1.0f );
      fogState.setEnabled( true );
      fogState.setColor( new ColorRGBA( 1.0f, 1.0f, 1.0f, 1.0f ) );
      fogState.setEnd( farPlane );
      fogState.setStart( farPlane / 10.0f );
      fogState.setDensityFunction( FogState.DF_LINEAR );
      fogState.setApplyFunction( FogState.AF_PER_VERTEX );
      rootNode.setRenderState( fogState );
   }

   private void buildPlayer(){
       Spatial model = null;
           try {
               java.net.URL bikeFile = Main.class.getClassLoader().getResource("data/model/bike.jme");
               BinaryImporter importer = new BinaryImporter();
               model = (Spatial)importer.load(bikeFile.openStream());
               model.setModelBound(new BoundingBox());
               model.updateModelBound();
               //scale it to be MUCH smaller than it is originally
               model.setLocalScale(.015f);
           } catch (IOException e) {
              
           }
          
           //set the vehicles attributes (these numbers can be thought
           //of as Unit/Second).
           player = new Surfboard("Player Node", model);
           player.setAcceleration(15);
           player.setTurnSpeed(4.5f);
           player.setWeight(25);
           player.setMaxSpeed(155);
           player.setMinSpeed(0);
           player.setLocalRotation(new Matrix3f(0,0,1.0f,0,1.0f,0,-1.0f,0,0));
           player.setLocalTranslation(new Vector3f(0,0, (float)display.getWidth()* 1.4f));
           rootNode.attachChild(player);
           rootNode.updateGeometricState(0, true);
           //we now store this initial value, because we are rotating the wheels the bounding box will
           //change each frame.
           agl = ((BoundingBox)player.getWorldBound()).yExtent;
           player.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
   }

   private void buildChaseCamera() {
        HashMap<String, Object> props = new HashMap<String, Object>();
        props.put(ChaseCamera.PROP_INITIALSPHERECOORDS, new Vector3f(150f, 0, 30 * FastMath.DEG_TO_RAD));
        props.put(ChaseCamera.PROP_DAMPINGK, "4");
        props.put(ChaseCamera.PROP_SPRINGK, "9");
    //    props.put(ChaseCamera.DEFAULT_STAYBEHINDTARGET, true);
        props.put( ChaseCamera.PROP_TARGETOFFSET, new Vector3f(0f, 0f, 0f) );
        chaser = new ChaseCamera(cam, player, props);
      
        chaser.getMouseLook().setEnabled(false);
        chaser.setMaxDistance(25);
        chaser.setMinDistance(0);
       // chaser.getMouseLook().setLookMouseButton( 1 );
    }

   private void buildInput() {
        input2 = new SurfBoardHandler(player, display.getDisplayRenderer());
    }
   
}



I get this output:



And after pressing I get this screen (can you see the little gray corner on the upper left side?) Here should be the game!



Rapidm