Can't get my game state running :(

Hi everyone, this is my first post and I would like to say congratulations! JmonkeyEngine its awesome!

Now my problems :slight_smile:



I'm trying to develop a game using StandardGame and Game States. Here is my code:





package paperfly.game;

import paperfly.game.state.MainMenuState;

import com.jmex.game.StandardGame;
import com.jmex.game.state.DebugGameState;
import com.jmex.game.state.GameStateManager;

public class PaperFlyGame {

   /**
    * @param args
    */
   public static void main(String[] args) {
      StandardGame game = new StandardGame("PaperFly");
      game.setDialogBehaviour(0);
      game.start();
      
      GameStateManager.create();      
      DebugGameState debug = new DebugGameState();
      MainMenuState menu = new MainMenuState("mainMenu");
      
      GameStateManager.getInstance().attachChild(menu);
      GameStateManager.getInstance().attachChild(debug);
      
      debug.setActive(true);
      menu.setActive(true);
   }

}

package paperfly.game.state;

import paperfly.game.handler.MenuHandler;

import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.renderer.Renderer;
import com.jme.scene.Text;
import com.jme.scene.state.LightState;
import com.jmex.game.state.CameraGameState;

public class MainMenuState extends CameraGameState {
   private static final String[] msg = {"Iniciar","Op

All Methods who call OpenGL functions, org.lwjgl.opengl.GL11.glMatrixMode() for example, need to be executed in the Main thread (the openGL thread) which StandardGame creates.



In your case CameraGameState.initCamera() is the cause for your problem.



But that call seems to be in the constructor of CameraGamesSate  :expressionless: hmm

That's was what I suspected too… but I looked at the jmetest and based on the TestGameStateSystem I developed these classes…

What you could do is create your MainMenuState in the GL thread by sending it to the queue, there is an example of how to do this in the Wiki:



http://www.jmonkeyengine.com/wiki/doku.php?id=standardgame_gamestates_and_multithreading_a_new_way_of_thinking



Or you can lock your game before creating it:


game.lock();   // Requests a lock on StandardGame that will pause the OpenGL thread when it starts the next update
MainMenuState menu = new MainMenuState("mainMenu");   // We can now call this in our current thread because thread-safety is no longer a concern, the OpenGL thread is paused at a safe point
game.unlock();    // Don't forget to do this as otherwise your game will be paused permanently and causes for a pretty sad gameplay experience



In your main method.

It is necessary to point out that the lock() and unlock() functionality though it does provide thread-safety is not useable in all scenarios because of the way the OpenGL code requires to be run in a specific thread sometimes as well (otherwise you get really bad breakages).

Unfortunately calling game.lock(), then creating the menu state and finally calling game.unlock() didn't make the code work :frowning:

Any other possibility???

Like I said, it doesn't work in all scenarios.  Take a look at the wiki link posted above and try putting it in GameTaskQueue instead.  That will certainly resolve the issue. :wink:

Many Thanks to all! the issue is solved :smiley:

Ok, ok, Darkfrog, you win this time… Next time I will take the time to suggest the Queue 

It's the "or" that always throws people off. :wink:

Maybe a simple question but I've always wondered, without finding it out for myself, how do you know if a method calls an OpenGL function? Or does the exception message always point to the lwjgl lib whenever you're trying to do something that should be executed in the OpenGL Thread?



Im asking because I forsee myself debugging code a long time without thinking of this possibility  :stuck_out_tongue:

This is one of the problems we currently have in jME that has yet to be totally resolved.  No, it's not always a nasty LWJGL exception thrown but in the majority of cases it is.  In most cases you can just make educated guesses of what needs to execute in the OpenGL thread based on what you're trying to do.  However, when in doubt, stick in the GameTaskQueue. :wink:

I have another question :slight_smile: I got another problem here… when I press down on the keyboard it dispatchs a lot of events… and the options become crasy… switching the scale so many times… is there a way so the keyboard could be more slow???





here is the code of the updated MainMenuState…


package paperfly.game.state;

import paperfly.game.handler.MenuHandler;

import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.renderer.Renderer;
import com.jme.scene.Text;
import com.jme.scene.state.LightState;
import com.jmex.game.state.CameraGameState;
import com.jmex.game.state.GameStateManager;

public class MainMenuState extends CameraGameState {
   private static final String[] msg = {"Sair","Opcoes","Iniciar"};

   private static final int INICIAR = 2;
   private static final int OPCOES = 1;
   private static final int SAIR = 0;
   private Text[] textos;
   private Text selectedText;
   private Text lastSelectedText;
   private InputHandler input;

   public MainMenuState(String string) {
      super(string);
      
      textos = new Text[3];
      textos[INICIAR] = Text.createDefaultTextLabel("inicio");
      textos[OPCOES] = Text.createDefaultTextLabel("opcoes");
      textos[SAIR] = Text.createDefaultTextLabel("sair");

      selectedText = textos[INICIAR];
      
      for(int i = SAIR; i < textos.length;i++){
         textos[i].updateRenderState();
         textos[i].print(msg[i]);
         textos[i].getLocalTranslation().set(100, 100*(i+1), 0);
      }
      
      rootNode.attachChild(textos[INICIAR]);
      rootNode.attachChild(textos[OPCOES]);
      rootNode.attachChild(textos[SAIR]);

      rootNode.setLightCombineMode(LightState.OFF);
      rootNode.setRenderQueueMode(Renderer.QUEUE_ORTHO);
      rootNode.updateRenderState();
      rootNode.updateGeometricState(0, true);
      input = new MenuHandler();
      
   }

   
   @Override
   protected void stateRender(float tpf) {
      selectedText.updateRenderState();
      super.stateRender(tpf);
   }

   @Override
   protected void stateUpdate(float tpf) {
      KeyBindingManager teclado = KeyBindingManager.getKeyBindingManager();
      if (teclado.isValidCommand(MenuHandler.COMANDO_BAIXO)) {
         int opcao = getIndiceSelecionado();
         lastSelectedText = selectedText;
         if (opcao < textos.length - 1) {
            selectedText = textos[opcao + 1];
         } else
            selectedText = textos[0];
         System.out.println(opcao);
      }
      if (teclado.isValidCommand(MenuHandler.COMANDO_ALTO)) {
         int opcao = getIndiceSelecionado();
         lastSelectedText = selectedText;
         if (opcao < INICIAR) {
            selectedText = textos[opcao + 1];
         } else
            selectedText = textos[SAIR];
      }
      if (teclado.isValidCommand(MenuHandler.COMANDO_SELECIONAR)) {
         if(getIndiceSelecionado() == SAIR){
            GameStateManager.getInstance().getChild("menu").setActive(false);
            cleanup();
         }
      }
      selectedText.setLocalScale(2);
      if(lastSelectedText != null){
         lastSelectedText.setLocalScale(1);
      }
      super.stateUpdate(tpf);
   }

   private int getIndiceSelecionado() {
      for (int i = 0; i < textos.length; i++) {
         if (selectedText == textos[i])
            return i;
      }
      return 0;
   }
}

I solved the problem with a Thread.sleep(100) in the stateRender method :slight_smile:

I don't know if its the best way to do it… but it's working here for now :slight_smile:

Thanks anyway

i think sleeping the Thread is not the best way.



things you can do to remedy your problems are:

a) use a Timer:


        if (lastAction+ 0.1f < Timer.getTimer().getTimeInSeconds()) { // every 100 ms
            // do your action

            lastAction= Timer.getTimer().getTimeInSeconds();
        }



b) use GameControl and ActionRepeatController, where you can define a repeat-rate:


ActionRepeatController(GameControl control, long rate, Runnable action)

Core-Dump is a smart guy…especially about option 'b'. :wink:

While this topic seems to be turning in a "I have a question about game states!"-topic I would like to ask another question concerning game states.



My scenario is that I currently have an arrow spatial that travels thru my jME world. Whenever I colide with a spatial I want the arrow to freeze.



However, Im using multiple game states (I suppose this can be interpretted as multiple threads) and it has occured to me that the arrow is half-way thru the targetted spatial before it freezes. Basically the gamestate that checks if there has been a colission is too slow because when I slow down the speed of the arrow it freezes at the right moment.



I'm guessing that the 60fps (= 60 updates per seconds) is too slow to accuratly freeze my arrow on the right position. But i've been thinking, what If a player has a slow computer who can only render 10fps? That means my arrow will probably go thru without ever getting checked.



This problem doesnt occur in non-gamestate games because everything is dumped in one big Update method. I would assume that throwing the colission checking in the openGL thread would perhaps solve it but that doesnt sound right to me.



What would be a good solution for this problem?

Thanks! :slight_smile:

You'll have to "step" or "tick" it forward along the path instead of simply updating position.  Or you could find the line from where the tip was at the previous update to the place where the tip should be at the end of this update and find out if it goes through an object?

I forgot to mention that im using Physics (AddForce()) to send the arrow flying. I suppose you could interpolate it by calculating the delta travelspeed between frames and freeze the arrow but that would be more or less reinventing the Colission detection of JME I suppose.