I have recently been developing a game for android. The game is of a similar format to the classic Pokemon games (quite complex). I have got quite far without any problems. However, I am finding it difficult to develop the dialogue (typewriter text) boxes that appear at the bottom of the screen when someone is talking. I am stuck on waiting for any input without blocking the render and update methods (as they all run on the same thread).
This is a simplified version of my game loop, outlining the structure and what I do each frame. The update method shown is called through the View#onDraw method.
public static void update(Canvas canvas, GameView view){
//time operations (calculating delta etc.)
long cTime = System.currentTimeMillis();
delta = cTime - time;
time = cTime;
globals.put("time", time);
globals.put("delta", delta);//set vars for scripts
camera.applyToCanvas(canvas);//apply camera matrix to canvas
if(map != null)map.update();
if(battle != null)map.update();
Effect.updateAll();//update everything (game logic)
render.load(canvas);//load the canvas into my custom render engine
render();//call render method (shown below)
view.invalidate();//reset view for redraw
}
public static void render(){
render.reset();//clears the canvas using canvas.setColor(Color.BLACK)
if(map != null)map.draw();
if(battle != null)battle.draw();
if(dialog != null)dialog.draw();
if(gui != null)gui.draw(); //draw everything using the renderengine
}
As you can see, these operations update all the game components (map, battles, guis etc.) and then renders them to the screen. By looking at the code, it's clear that I'm running these operations on the same thread, so this thread can obviously not be blocked (otherwise the game will just stop).
This is where my problem is. I use an in game gui with a few buttons. These buttons are assigned to 8 integers (0-8) and when the up button is pressed for example, that input data is passed through the game to the existing dialog or battle or whatever needs it. These buttons rely on the main activity's touch events where the MotionEvent which, as a result of running the game loop off of the onDraw method, tuns on the same thread as the game itself. Here is how I handle dialogs:
I use javascript (rhino parser) as follows (passing a dialog object to the script in the variable 'dialog'): var d = dialog.show("Hello! How are you.");
To get the input, I call the getInput method which takes in the dialog, and up to 4 strings as selection options. This method is supposed to return an integer value. This can be called through the script as follows:
var response = dialog.getInput(d, "I'm fine, thank you!", "Who wants to know.");
The getInput method is as follows in my Dialog class:
public static int getInput(Dialog d, String... args){ d.waitingForInput = true; d.lastInput = -1; while(d.waitingForInput || d.lastInput == -1){ //render options //main thread is obviously blocked here. } return d.getLastInput();//returns the d.lastInput and resets waitingForInput and lastInput. The script can then use this value to decide what to do. }
Now my main question is how to run this method without blocking the render and update thread. More specifically setting the value of d.lastInput and d.waitingForInput when the user touches a certain region of the screen (where the gui select button is).
If there are any doubts about what I am trying to ask in this question, please leave a comment as I am quite tired and have spent some time trying to solve this.
EDIT:
I have thought about running the input on a separate thread but this will still lead to blocking other input methods from being called (such as changing the selected option in the dialog).
I have decided to approach this through a form of event handlers instead. When the required input is down, the specified script is run by the game.