Coordinating global game mechanics

Now you know three modular ways of running code as part of the main update loop: you can implement the simpleUpdate() method in the main class, you can add controls to spatials, and you can attach AppState objects.

You can activate or deactivate an individual chunk of behavior by adding or removing a control, or by attaching and detaching an AppState object. You can move whole chunks of the scene graph out of the main simpleInitApp() method, and make them part of an AppState object. For example, a hypothetical OutdoorsAppState object's initialize() method attaches bright lights and a forest sound loop; its cleanup() method detaches what the AppState object brought, so you can switch to the IndoorsAppState object, which itself brings dim fluorescent lights and a factory sound loop. This modularization helps you keep your code reusable and maintainable.

Since your game behavior interacts, you have to be aware of the order in which its pieces execute during the update phase of the listen-update-render loop:

  1. jMonkeyEngine calls the update() methods of all AppState objects in the order in which you attached them.
  2. jMonkeyEngine calls the controlUpdate() methods of all controls in the order in which you added them.
  3. jMonkeyEngine calls the simpleUpdate() method of the main SimpleApplication class.

You must call all code that modifies the scene graph from one of these three methods that hook into the update loop. This ensures that your changes are in sync with the main thread.

Outside the main loop, you can always use multi-threading and run other calculations that do not (directly or indirectly) modify the scene graph in threads of their own. Especially when you solve more complex tasks, be careful that one long-running algorithm (such as path finding) does not block the whole main thread. Start a new thread so that you don't slow down the whole application, and break up long-running tasks into self-contained, parallel-running Callables and use the returned results.

Tip

What happens if you modify the scene graph from an external thread? Well, your code will work as expected most of the time—but in seemingly random intervals, the engine will inexplicably complain that the scene graph is out of date. If you cannot avoid making modifications to the scene graph outside the main thread, you must enqueue these Callables in the main application using the app.enqueue() method to these calls in the main application! Find more about concurrency in jMonkeyEngine applications on our wiki at http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:multithreading.