I’m developing a turn based strategy game. Right now, I have the standard core game loop provided jMonkey:
respond to input listeners
update which executes game logic
render graphics & sound
By design:
Almost everything in the game has a logical representation & a ‘viz’ representation with any jMonkey related code.
Most objects, including those responsible for step 2, are loaded at runtime from init files.
As a simplification, let’s say the game state requires the logic to evaluate a fireball - the logic would then determine the results of buffs, debuffs, determine chance to hit, damage, trigger reaction spells, etc. It updates the logical representation & queues up the corresponding graphics & sounds for the core loop & returns. Works fine.
Here’s the problem: let’s say I want ‘chance to hit’ to be a reflex based minigame rather than a percentage. This requires the inside of step 2 to reach back to the outer loop, initiate some stuff & wait for a response. Now step 2 is waiting for the outer loop to give a response & the outer loop is waiting for step 2 to finish.
It seems like threads are required to deal with this. The best I’ve come up with is:
make step 2 its own thread, spawned by the outer loop
when minigame code occurs, the logic thread makes calls to the game object to init the minigame
the logic thread then waits, polling the minigame for a response
the outer loop in turn does its thing, polling the logic thread & responding as needed
My questions are:
Is there a sane way to solve this situation without resorting to using threads?
If threads are required, is there a better way to solve the problem than what I’ve come up with?
Are there unknown unknowns I haven’t considered?
Yep. Make it event based instead of “outer and inner loops” or whatever. We don’t really know enough about your logic to go into much more detail than that.
There is always a way to do it without threads… and I’m not convinced threads are even the right way in this case.
The inner loop is the call to public void simpleUpdate(float tpf) & the outer loop is where jMonkey handles rendering, etc; are you suggesting I replace the call to simpleUpdate with events?
You can use update from AppStates or controlUpdate from controls so you can remove a lot of logic from simpleUpdate in your application. You don’t need a thread for your solution.
I can give you an example of my personal approach:
let’s say you handle the essential in simpleUpdate so for step 2 of your problem:
Initialize and attach an appState that will contain all logic you need for the minigame with a callback to your application (via variable or interface). And let simpleUpdate handle other stuff that does not require those steps.
Let the app state handle everything of the minigame and use it’s own update method in case you need it and when done, call back to the main application.
Once the callback is made, the application will detach the app state and continue to the next step.
This will not affect your performance when done right
I probably gave a poor descsription of the problem earlier. Essentially I have code at frame N that can’t proceeed until frame N+X has been rendered (where X > 0). While I’ve been mulling over this, I’ve noticed some other aspects of my design that need to be reconsidered & those may have a strong bearing on how I approach this particular part.
In all honesty, it sounds like you may simply need to rethink your design. If your code relies on things that haven’t happened yet, surely there are more intuitive ways of rewriting it? Without understanding the context it’s impossible to say. Your code can’t proceed until something happens later, but if that code is time sensitive (i.e input interaction or rendering), then any kind of threading will result in a delay in that action or event until whatever code it’s waiting on is done.