<Solved>How do you set more than 1 game state?

Im trying to learn StandardGame and GameState.



For an exercise, I made 2 game states. SkyboxState that attach a skybox into its root node and TerrainState that attach a terrain into its root node.



then in my Standard game declare the two game states and set it both to active. Heres what happen, the skybox appears (for a second) then disappear and shows only the terrain.



here my little code:

public class PhinTourStandardGame {

    public static void main(String[] args){


        StandardGame game = new StandardGame("THE STANDARD GAME");
        game.start();

        SkyboxState sbState = new SkyboxState();
        GameStateManager.getInstance().attachChild(sbState);
        sbState.setActive(true);

        TerrainState terrainState = new TerrainState();
        GameStateManager.getInstance().attachChild(terrainState);
        terrainState.setActive(true);
    }

}



*I tried adding a DebugGameState, it work fine with my terrainState but again my skyboxState disappears

So guys, how do you set up multiple game states in your standard game. Im sorry im so noob  :D by the way im still using jme2

It would help to see the code from the individual game states as it sounds like you have an issue with the order of nodes here.



What you're doing in the code provided is pretty standard and correct :slight_smile:

jme2 StandardGame…Are you using jME2's skyBox if so do you have the skyBox in a GametaskQueue as displayed below, if you are then can you post your code of both terrainState and skyboxState



example from very old code


GameTaskQueueManager.getManager().update
      (new Callable<Object>() {
               public Object call() throws Exception {
               state1= new SkyBoxManager.SkyBoxGameState(); // Create our game state
               //Initiate Skybox
               GameStateManager.getInstance().attachChild(state1); // Attach it to the GameStateManager
               state1.setActive(true); // Activate it
               return state1;
               }                
      }                      
).get();

@sbook and Bonechilla, here the code for  the game states  :D



@ Bonechilla, yeah i have my skybox inside the GameTaskQueueManager. My skyboxState works fine with DebugGameState only if the terrainState is not active.



heres my code… i have separate classes that generate the skybox for me, same also for the terrain.



SkyBoxState class

public class SkyboxState extends GameState{

    Node rootNode;

    public SkyboxState(){
        rootNode = new Node("THE ROOT NODE");

        Future<Skybox> sb = GameTaskQueueManager.getManager().update(new Callable<Skybox>(){
            public Skybox call(){
                Skybox sb = new PhinTourSkyBox("THE SKYBOX", "orion", "png", 300, 300, 300);
                return sb;
            }
        });

        try {
          rootNode.attachChild(sb.get());
        } catch (Exception e) {
        }

        
    }

    @Override
    public void update(float tpf) {
        rootNode.updateGeometricState(tpf, true);
        rootNode.updateRenderState();
    }

    @Override
    public void render(float tpf) {
        DisplaySystem.getDisplaySystem().getRenderer().createBlendState();
        rootNode.draw(DisplaySystem.getDisplaySystem().getRenderer());
    }

    @Override
    public void cleanup() {
        
    }

}




and heres the class that generates my skybox for me.
public class PhinTourSkyBox extends Skybox{

   //dir, will hold the directory name
   private String dir;
   //ext, will hold the file extension of the images
   //that will be use for textures
   private String ext;

   public PhinTourSkyBox(String id, String dir, String ext,
          float xExtent, float yExtent, float zExtent){

       super(id, xExtent, yExtent, zExtent);
       this.dir = dir.toLowerCase().trim();
       this.ext = ext.trim();
       setSkyBoxTexture();
   }

   private void setSkyBoxTexture(){
       //generate a URL base on the given dir
       URL baseDir = PhinTourSkyBox.class.getClassLoader().getResource("data/skybox/" + dir + "/");

       //resource locator uses the base directory
       try {
           ResourceLocatorTool.addResourceLocator(ResourceLocatorTool.TYPE_TEXTURE,
                   new SimpleResourceLocator(baseDir));

       } catch (Exception e) {
           e.printStackTrace();
           System.exit(0);
       }

       this.setTexture(Face.North, TextureManager.loadTexture("north." + ext,
               Texture.MinificationFilter.BilinearNearestMipMap,
               Texture.MagnificationFilter.Bilinear));
       
       this.setTexture(Face.South, TextureManager.loadTexture("south." + ext,
               Texture.MinificationFilter.BilinearNearestMipMap,
               Texture.MagnificationFilter.Bilinear));

       this.setTexture(Face.East, TextureManager.loadTexture("east." + ext,
               Texture.MinificationFilter.BilinearNearestMipMap,
               Texture.MagnificationFilter.Bilinear));

       this.setTexture(Face.West, TextureManager.loadTexture("west." + ext,
               Texture.MinificationFilter.BilinearNearestMipMap,
               Texture.MagnificationFilter.Bilinear));

       this.setTexture(Face.Up, TextureManager.loadTexture("up." + ext,
               Texture.MinificationFilter.BilinearNearestMipMap,
               Texture.MagnificationFilter.Bilinear));
       
       this.setTexture(Face.Down, TextureManager.loadTexture("down." + ext,
               Texture.MinificationFilter.BilinearNearestMipMap,
               Texture.MagnificationFilter.Bilinear));

       this.preloadTextures();

   }

}


TerrainState class
public class TerrainState extends GameState{

   TerrainBlock tb;
   Node rootNode;

   public TerrainState(){
       rootNode = new Node("THE NODE");

       SpaceTerrain0 sp = new SpaceTerrain0("THE TERRAIN");
       tb = sp.getTerrain();


       rootNode.attachChild(tb);
   }

   @Override
   public void update(float tpf) {
       rootNode.updateRenderState();
       rootNode.updateGeometricState(tpf, true);
   }

   @Override
   public void render(float tpf) {
       DisplaySystem.getDisplaySystem().getRenderer().clearBuffers();
       rootNode.draw(DisplaySystem.getDisplaySystem().getRenderer());
   }

   @Override
   public void cleanup() {
       
   }

}


and the class that generate my terrain
public class SpaceTerrain0{

   private TerrainBlock tb;
   private String id;

   public SpaceTerrain0(String id){
       this.id = id;
       setTerrain();
   }


   public TerrainBlock getTerrain(){
       return tb;
   }

   private void setTerrain(){
       //set the height map
       MidPointHeightMap heightMap = new MidPointHeightMap(64, 1.0f);
       //create a vector3f for the scale value
       Vector3f terrainScale = new Vector3f(4, 0.1f, 4);

       //create the terrain block
       tb = new TerrainBlock(id, heightMap.getSize(), terrainScale,
               heightMap.getHeightMap(), new Vector3f(0,0,0));
       //set the nounding volume for the terrain block
       tb.setModelBound(new BoundingBox());
       tb.updateModelBound();

       //set the texture URL
       URL tex1 = SpaceTerrain0.class.getClassLoader().getResource("data/texture/spaceterrain/1.jpg");
       URL tex2 = SpaceTerrain0.class.getClassLoader().getResource("data/texture/spaceterrain/2.jpg");
       URL tex3 = SpaceTerrain0.class.getClassLoader().getResource("data/texture/spaceterrain/3.jpg");

       //load the texture
       ProceduralTextureGenerator pt = new ProceduralTextureGenerator(heightMap);
       pt.addTexture(new ImageIcon(tex1), -128, 0, 128);
       pt.addTexture(new ImageIcon(tex2), 0, 128, 256);
       pt.addTexture(new ImageIcon(tex3), 128, 256, 384);
       pt.createTexture(32);

       //create the base texture based on pt
       Texture baseTex = TextureManager.loadTexture(
               pt.getImageIcon().getImage(),
               Texture.MinificationFilter.BilinearNearestMipMap,
               Texture.MagnificationFilter.Bilinear,
               true);

       //create the detail texture
       URL detailImage = SpaceTerrain0.class.getClassLoader().getResource("data/texture/spaceterrain/9.jpg");
       Texture detailTex = TextureManager.loadTexture(detailImage,
               Texture.MinificationFilter.BilinearNearestMipMap,
               Texture.MagnificationFilter.Bilinear);
       detailTex.setWrap(Texture.WrapMode.Repeat);

       //combine the two textures
       //set the combination settings
       baseTex.setApply(Texture.ApplyMode.Combine);
       baseTex.setCombineFuncRGB(Texture.CombinerFunctionRGB.Modulate);
       baseTex.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
       baseTex.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
       baseTex.setCombineSrc1RGB(Texture.CombinerSource.PrimaryColor);
       baseTex.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);
       baseTex.setCombineScaleRGB(Texture.CombinerScale.One);

       detailTex.setApply(Texture.ApplyMode.Combine);
       detailTex.setCombineFuncRGB(Texture.CombinerFunctionRGB.AddSigned);
       detailTex.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
       detailTex.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
       detailTex.setCombineSrc1RGB(Texture.CombinerSource.Previous);
       detailTex.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);
       detailTex.setCombineScaleRGB(Texture.CombinerScale.One);

       //create a texture state
       TextureState ts = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
       ts.setEnabled(true);
       ts.setTexture(baseTex, 0);
       ts.setTexture(detailTex, 1);

       tb.setRenderState(ts);
       tb.setDetailTexture(1, 64);
       tb.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
       
   }

}


THANK YOU SO MUCH!  XD

Hey :slight_smile:



Just my 2 cents… (I'm more working with jME3 atm… but I have some jME2 GameState experiences :D)



Do you really have to:


        DisplaySystem.getDisplaySystem().getRenderer().clearBuffers();



I thought, that this method would clear the whole screen? I suppose that GameStateManager should take care of this, your GameStates should only draw there part of things..
At least that explains me, why your Skybox disappears, because the TerrainGameState would clear the buffers AFTER your SkyBoxState rendered.

And is it intended to create a BlendState without assigning it to any spatial? (you do it each render cycle of your SkyBoxGameState:)


        DisplaySystem.getDisplaySystem().getRenderer().createBlendState();

tim8dev said:

Hey :)

Just my 2 cents.. (I'm more working with jME3 atm.. but I have some jME2 GameState experiences :D)

Do you really have to:


        DisplaySystem.getDisplaySystem().getRenderer().clearBuffers();



I thought, that this method would clear the whole screen? I suppose that GameStateManager should take care of this, your GameStates should only draw there part of things..

At least that explains me, why your Skybox disappears, because the TerrainGameState would clear the buffers AFTER your SkyBoxState rendered.

And is it intended to create a BlendState without assigning it to any spatial? (you do it each render cycle of your SkyBoxGameState:)


        DisplaySystem.getDisplaySystem().getRenderer().createBlendState();




haha!  silly me, for always putting what's in the tutorial. yes the terrain do clear the whole screen thats why the skybox disappears. the createBlendState is supposed to be clearBuffers(), anyway i just deleted them. thanks.. im sorry i didnt notice im clearing the screens.. well this case is solved.  :D
blur said:

tim8dev said:

Hey :)

Just my 2 cents.. (I'm more working with jME3 atm.. but I have some jME2 GameState experiences :D)

Do you really have to:


        DisplaySystem.getDisplaySystem().getRenderer().clearBuffers();



I thought, that this method would clear the whole screen? I suppose that GameStateManager should take care of this, your GameStates should only draw there part of things..

At least that explains me, why your Skybox disappears, because the TerrainGameState would clear the buffers AFTER your SkyBoxState rendered.

And is it intended to create a BlendState without assigning it to any spatial? (you do it each render cycle of your SkyBoxGameState:)


        DisplaySystem.getDisplaySystem().getRenderer().createBlendState();




haha!  silly me, for always putting what's in the tutorial. yes the terrain do clear the whole screen thats why the skybox disappears. the createBlendState is supposed to be clearBuffers(), anyway i just deleted them. thanks.. im sorry i didnt notice im clearing the screens.. well this case is solved.  :D


Haha :)
I was already wondering if createBlenderState was a too fast use of Code Autocompletion :D
Happy to hear, it helped you :D