Waiting for touch input without blocking game thread

675 Views Asked by At

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:

  1. 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.");

  2. 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.");

  3. 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).

2

There are 2 best solutions below

0
On BEST ANSWER

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.

1
On

If you don't want to stop the threads and you are already half way through

Method1: Use ConcurrentLinkedQueue, ArrayBlockingQueue and its families as static variable and put your values inside it.

Method2: you use can use TCP/UDP sockets using localhost adapter like a message queue system and try to get those values with the same ConcurrentLinkedQueue, ArrayBlockingQueue technique

Try to refer any opensource java game engine source codes and identify how they did or you can use those game engines, like "jMonkeyEngine" "LWJGL" ...etc