如何在按下键之前暂停JavaScript中的主循环处理?

时间:2014-05-24 08:34:41

标签: javascript input suspend

我正在将旧的终端模式文本游戏转换为JavaScript。

游戏转换很简单,差不多完成了。但是UI的一部分 - 获得用户输入 - 证明是如此困难,以至于我转向StackOverflow上的专家寻求帮助。我已经详尽地通过了SO,并找到了类似的答案,但没有直接适用。

我的目标之一是保留游戏20世纪70年代的输入风格:

  1. 所有文字都显示在一个屏幕上(没有弹出对话框或隔离/可见输入框)。
  2. 通过显示提示信息,然后等待玩家输入回复来获得用户输入。
  3. 用户响应的个别字符显示在屏幕上。
  4. 按Backspace键可以按相反的顺序删除输入的字符。
  5. 可输入的字符数有限。
  6. 所有其他游戏处理暂停,直到用户按下Return键。
  7. 按下Return键时,输入的所有字符将作为字符串返回给调用函数。
  8. 当调用函数获得结果字符串时,主游戏代码中的处理将恢复。
  9. 我已经成功找到了第1步和第3-5步。我在HTML中创建一个Input元素,在CSS中将其移出屏幕,并将焦点设置为该元素。当按下某个键时,如果它是一个字母数字,我使用appendChild()将它作为文本节点添加到内容元素,以便它显示在主屏幕上;如果是Backspace键,我删除尾子节点以从屏幕上删除字符;如果它是Return键,我将输入字段中的文本复制到局部变量,以将其返回到调用程序并清除输入字段。

    经过一番努力,内容区域中打印和退格字符的代码正常工作。我一直无法弄清楚的是如何暂停其他处理,直到用户键入一些键并点击Return。

    我花了最近三天的时间搜索StackOverflow以及我能找到的所有其他网站,这些网站都提到了这种东西,再加上尝试我能想到的每一个信号组合。提示对话框或可见输入框无法满足要求#1。天真的while循环会停止处理,但它也会阻止按键被识别。定时器和间隔可能会丢失按键。而且我宁愿避免yield()以支持旧浏览器。 (我希望尽可能保持跨浏览器的兼容性。)

    类似的问题产生了引用异步(通过回调)的答案,但这正是我不想要的 - 我希望主要的游戏代码停止运行,但仍然允许检测到按键,直到用户按下返回键,之后主游戏循环可以恢复。

    有没有办法实现这个目标?如果没有相对简洁的方法在JavaScript中模拟提示对话框的模态文本条目,我愿意重新思考主要游戏循环的结构。

    注意:如果提供示例代码,直接HTML / CSS / JavaScript中的示例对我来说比jQuery更有帮助。谢谢!


    编辑:正在运行的程序部分是为按键创建一个监听器并在内容区域显示字母数字字符:

    form.addEventListener("keydown", function (e) {
        if (e.keyCode == 13) {
            istr = inputBox.value; // save user's text as a string
            inputBox.value = ""; // clear input element
        }
        else if (e.keyCode == 8)
            backspace(); // remove last char from content area
        else if (e.keyCode >= 48 && e.keyCode <= 90)
            printCharST(String.fromCharCode(e.keyCode)); // put char in content area
        inputBox.focus(); // bring focus back to input textbox
    }, false);
    

    这不是我要问的代码的一部分。 (我把它包括在这里,以便我确实有代码来检测按键并对它们进行操作。)

    我遇到问题的部分是调用程序 - 如何在用户按下Return之前将其挂起,然后将其字符串放入istr并将其返回给正在等待的调用者用户输入?简单地告诉调用者重复轮询istr(或由密钥监听器设置的任何其他标志变量),直到它不为空,这会扼杀如此多的CPU以防止密钥被识别。

    我很乐意提供任何有助于澄清我想要实现的目标的其他信息。此外,如果有关于如何更好地格式化此问题的任何特定评论,我将很乐意对其进行修改。

1 个答案:

答案 0 :(得分:1)

最简单,最快捷,最容易实现的方法是使用...一个回调处理程序。而不是解释它,它更容易看到它在行动:

  • 创建一个onkeydown处理程序(请参阅此答案以了解如何执行此操作:https://stackoverflow.com/a/4929676/2167545
  • 在onkeydown处理程序中创建一个函数,该函数将获取最近单击的键并将其附加到输入区域。
  • 让该函数返回一个布尔值,表示该键是否是&#39; return&#39; (true)与否(false)
  • 如果该函数返回true,则将当前输入传递给解释器并逐步执行游戏
    • 这将涉及打印更多文字,更新敌人,对话等。

这种作用的原因是因为你所描述的游戏的本质。每次玩家有选项时,游戏必须停止并等待输入。这些暂停中的每一个都自然地将游戏分成具有明确定义的操作的部分。例如,在对话中,这些操作将管理对玩家输入的NPC响应的创建。同样的例子可以扩展到战斗场景,描述,导航等。你甚至可以添加超时(如果你小心),以便玩家必须快速准确地输入以继续。如果在提示和返回键之间的持续时间内暂停除用户输入之外的所有操作,则无法执行这些超时。

编辑:问题似乎仍然出现在您展示的事件处理程序中。目前,它只是监听输入并将该输入分配给值。这意味着您在代码中的某个位置有一个主游戏循环,它会检查istr每个tick的值,然后对其进行响应。此设计对您的用途无用,效率低下。

考虑到您尝试编写的游戏的性质,游戏将长时间处于不活动状态,游戏只是等待用户完成他的回复输入。接下来是用户点击返回键时的短暂活动。主要的游戏循环方法对此来说太过分了。更简单的设计可以提高代码的简单性和健壮性。我在上面指定的设计比游戏循环方法要好得多,因为它的控制流程与上一段中的描述相匹配。

Example implementation

编辑:如果您有一个游戏循环,因为您需要在用户输入时对输入执行某些操作,那么也可以轻松添加。小提琴已经更新了评论和示例扩展点。