【问题标题】:Waiting for touch input without blocking game thread等待触摸输入而不阻塞游戏线程
【发布时间】:2015-06-27 03:19:52
【问题描述】:

我最近一直在为安卓开发一款游戏。该游戏与经典口袋妖怪游戏的格式相似(相当复杂)。我已经走了很远,没有任何问题。但是,我发现很难开发当有人说话时出现在屏幕底部的对话(打字机文本)框。我一直在等待任何输入而不阻塞渲染和更新方法(因为它们都在同一个线程上运行)。

这是我的游戏循环的简化版本,概述了结构和我每帧的操作。显示的更新方法是通过 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),例如,当按下向上按钮时,输入数据会通过游戏传递到现有的对话或战斗或任何需要的地方。这些按钮依赖于主 Activity 的触摸事件,其中 MotionEvent 是从 onDraw 方法运行游戏循环的结果,它与游戏本身在同一线程上进行调谐。以下是我处理对话框的方式:

  1. 我使用 javascript(rhino 解析器)如下(将对话框对象传递给变量 'dialog' 中的脚本): var d = dialog.show("你好!你好吗。");

  2. 为了获得输入,我调用 getInput 方法,该方法接受对话框,最多 4 个字符串作为选择选项。该方法应该返回一个整数值。这可以通过脚本调用,如下所示: var response = dialog.getInput(d, "I'm fine, thank you!", "Who wants to know.");

  3. getInput方法在我的Dialog类中如下:

    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 的值。

如果对我想在这个问题中提出的问题有任何疑问,请发表评论,因为我很累并且花了一些时间试图解决这个问题。

编辑:

我曾考虑在单独的线程上运行输入,但这仍然会导致阻止调用其他输入方法(例如更改对话框中的选定选项)。

【问题讨论】:

    标签: java android game-engine


    【解决方案1】:

    如果你不想停止线程并且你已经完成了一半

    方法一:使用 ConcurrentLinkedQueue、ArrayBlockingQueue 及其家族作为静态变量,并将你的值放入其中。

    方法 2: 您可以使用 TCP/UDP 套接字 使用 localhost 适配器,如消息队列系统,并尝试使用相同的 ConcurrentLinkedQueue、ArrayBlockingQueue 技术

    尝试参考任何开源 Java 游戏引擎源代码并确定它们是如何实现的,或者您可以使用这些游戏引擎,例如“jMonkeyEngine”“LWJGL”...等

    【讨论】:

    • 感谢您的帮助并理解您的意思,但这并不能解决等待值而不阻塞线程的问题。
    【解决方案2】:

    我决定通过一种事件处理程序来解决这个问题。当所需的输入关闭时,游戏会运行指定的脚本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-19
      • 1970-01-01
      相关资源
      最近更新 更多