等待触摸输入而不阻塞游戏线程

5
我最近在开发一款Android游戏,这款游戏的格式类似于经典的宝可梦游戏(相当复杂)。我已经取得了很大的进展,没有遇到任何问题。然而,我发现很难开发出对话框(打字机文本)框,在某人说话时出现在屏幕底部。我卡在了等待任何输入但不阻塞渲染和更新方法上(因为它们都运行在同一个线程上)。
这是我的游戏循环的简化版本,概述了每帧我要做的事情以及结构。所示的更新方法是通过View#onDraw方法调用的。
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
}

正如您所看到的,这些操作会更新游戏组件(地图、战斗、GUI等),然后将它们呈现在屏幕上。通过查看代码,很明显我正在同一个线程上运行这些操作,因此这个线程显然不能被阻塞(否则游戏将停止)。
这就是我的问题所在。我在游戏中使用了一些按钮的GUI。这些按钮分配给8个整数(0-8),例如,当按下向上按钮时,输入数据就会通过游戏传递到现有对话框或战斗中,或者其他需要数据的地方。这些按钮依赖于主活动的触摸事件,其中MotionEvent由于从onDraw方法上的游戏循环运行,因此在与游戏本身相同的线程上运行。以下是我处理对话框的方式:
  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.
    }
    
现在我的主要问题是如何在不阻塞渲染和更新线程的情况下运行此方法。更具体地说,当用户触摸屏幕上特定区域(即GUI选择按钮所在的区域)时,设置d.lastInput和d.waitingForInput的值。
如果对我在这个问题中想要问什么有任何疑问,请留下评论,因为我已经很累了,花了一些时间来解决这个问题。
编辑:我考虑过在单独的线程上运行输入,但这仍然会导致阻止调用其他输入方法(例如更改对话框中选定的选项)。
2个回答

0

如果你不想停止线程,并且已经进行了一半的工作

方法1:使用ConcurrentLinkedQueue、ArrayBlockingQueue及其相关类作为静态变量,并将值放入其中。

方法2:可以使用TCP/UDP套接字,使用本地主机适配器作为消息队列系统,并尝试使用相同的ConcurrentLinkedQueue、ArrayBlockingQueue技术获取这些值。

尝试参考任何开源Java游戏引擎源代码,了解它们是如何实现的,或者您可以使用这些游戏引擎,如"jMonkeyEngine"、"LWJGL"等。


我感谢你的帮助并理解你所说的,但这并不能解决等待值而不阻塞线程的问题。 - rodit

0

我决定采用事件处理程序的形式来解决这个问题。当所需的输入被触发时,游戏将运行指定的脚本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接