制作等待 JButton 事件的基于文本的游戏
Making a text based game that waits for a JButton event
我正在寻找一种方法来制作一个简单的基于文本的游戏,尽管我在事件驱动而不是游戏循环中遇到了问题。
游戏的基本玩法:
说你打的是什么怪物。
攻击。
当它被击败时,你去下一个怪物。
在使用扫描仪下一行的游戏循环中,我可以等待用户输入有效选项,然后继续代码。但是使用事件,我不确定如何设置游戏。我需要以某种方式等待用户按下按钮来执行操作,但我不知道应该在哪里注册事件侦听器,如何使用操作事件进行循环等。
抱歉,如果这有点含糊,与其说是语法问题,不如说是语义问题,我只是在学习 Java。我本质上需要一个事件驱动游戏的基本结构,它会根据您所处的游戏阶段做出不同的反应。
事件程序的关键是您根本不使用 "loop"。相反,您更改 "state"。
这个 "state machine" 的最简单版本是字符串的线性 ArrayList,其中您的程序保存一个代表 ArrayList 中当前项目的 int 变量,您在按下按钮时递增索引,然后显示到列表中的下一个字符串给用户。该系统的美妙之处在于您可以将它用于更复杂的逻辑旅程,几乎是无限的变化,每一种都取决于游戏的当前状态和用户所做的选择。
对于更复杂的游戏,您不会使用线性脚本,而是会创建多个具有行为(方法)和状态(变量)的 classes,并让它们相互交互。这些将包括您的怪物 classes、物品 classes 和位置 classes,以及控制一切的游戏 class。
在我过去做过的事件驱动程序中,一般来说,你希望每个 class 将要执行某事并生成事件的程序都有一个内部侦听器列表,可以向该列表注册/被注册 class。把它想象成有人在互联网上订阅你的推文。您响应某种类型的刺激并向每个人 subscribed/registered 发送通知到您的提要。然后这些听众可以采取行动并向他们自己的听众发送通知等。
一个简单的实现是拥有一个 TweetListener 接口,订阅 classes 将实现该接口。作为 TweetProducer,您将拥有一组 register/unregister 方法,这些方法由所有 TweetListener 实例的内部列表支持,这些实例希望在您发出 "event" 时得到通知。当您准备好发送推文时,您将循环浏览该列表的防御副本,并且对于其中的每个对象,您将调用 TweetListener 接口中定义的方法,即 aListener.doTweetReceivedAction("Here's my tweet")
。 (防御性副本,因为听众的一个可能操作是 unregister/stop 关注您的推文,您不希望同时修改列表)。显然,您必须非常注意后续操作如何从 concurrency/multi-threaded 意义上和操作顺序意义上影响您的程序。
就引导整个事情而言,在您的 public void static main
方法中,您基本上会实例化各种对象并将它们连接在一起作为侦听器等。
Tweeter me = new Tweeter()
SomeDude dude = new SomeDude() // implements TweetListener interface
SomeDude bob = new SomeDude()
me.addListener(dude);
me.addListener(bob);
me.tweet("hi!");
显然,您还需要一个 KeyTyped 侦听器,它会等待按键事件,确定它们是什么,并向程序中的各种侦听器发送适当的事件通知。在某些时候,按键监听器将不得不坐下来等待输入。或者,您可以在不同的线程中拥有该按键侦听器和程序的其他部分 运行。这实际上是 Java 中 Swing 线程模型的工作方式。您有一个主程序线程和一个摆动线程,并且您在两者之间来回发送事件通知(即 SwingUtilities.invokeLater();)
这是一篇较旧的文章,但实际上对于如何在 java 中进行事件驱动编程的基础知识非常有用。我认为它适用于你正在尝试做的事情。 https://community.oracle.com/docs/DOC-982960 它讨论了防御性复制、发送不可变事件对象等内容,以及您为什么需要这样做和担心此类事情。
我正在寻找一种方法来制作一个简单的基于文本的游戏,尽管我在事件驱动而不是游戏循环中遇到了问题。
游戏的基本玩法: 说你打的是什么怪物。 攻击。 当它被击败时,你去下一个怪物。
在使用扫描仪下一行的游戏循环中,我可以等待用户输入有效选项,然后继续代码。但是使用事件,我不确定如何设置游戏。我需要以某种方式等待用户按下按钮来执行操作,但我不知道应该在哪里注册事件侦听器,如何使用操作事件进行循环等。
抱歉,如果这有点含糊,与其说是语法问题,不如说是语义问题,我只是在学习 Java。我本质上需要一个事件驱动游戏的基本结构,它会根据您所处的游戏阶段做出不同的反应。
事件程序的关键是您根本不使用 "loop"。相反,您更改 "state"。
这个 "state machine" 的最简单版本是字符串的线性 ArrayList,其中您的程序保存一个代表 ArrayList 中当前项目的 int 变量,您在按下按钮时递增索引,然后显示到列表中的下一个字符串给用户。该系统的美妙之处在于您可以将它用于更复杂的逻辑旅程,几乎是无限的变化,每一种都取决于游戏的当前状态和用户所做的选择。
对于更复杂的游戏,您不会使用线性脚本,而是会创建多个具有行为(方法)和状态(变量)的 classes,并让它们相互交互。这些将包括您的怪物 classes、物品 classes 和位置 classes,以及控制一切的游戏 class。
在我过去做过的事件驱动程序中,一般来说,你希望每个 class 将要执行某事并生成事件的程序都有一个内部侦听器列表,可以向该列表注册/被注册 class。把它想象成有人在互联网上订阅你的推文。您响应某种类型的刺激并向每个人 subscribed/registered 发送通知到您的提要。然后这些听众可以采取行动并向他们自己的听众发送通知等。
一个简单的实现是拥有一个 TweetListener 接口,订阅 classes 将实现该接口。作为 TweetProducer,您将拥有一组 register/unregister 方法,这些方法由所有 TweetListener 实例的内部列表支持,这些实例希望在您发出 "event" 时得到通知。当您准备好发送推文时,您将循环浏览该列表的防御副本,并且对于其中的每个对象,您将调用 TweetListener 接口中定义的方法,即 aListener.doTweetReceivedAction("Here's my tweet")
。 (防御性副本,因为听众的一个可能操作是 unregister/stop 关注您的推文,您不希望同时修改列表)。显然,您必须非常注意后续操作如何从 concurrency/multi-threaded 意义上和操作顺序意义上影响您的程序。
就引导整个事情而言,在您的 public void static main
方法中,您基本上会实例化各种对象并将它们连接在一起作为侦听器等。
Tweeter me = new Tweeter()
SomeDude dude = new SomeDude() // implements TweetListener interface
SomeDude bob = new SomeDude()
me.addListener(dude);
me.addListener(bob);
me.tweet("hi!");
显然,您还需要一个 KeyTyped 侦听器,它会等待按键事件,确定它们是什么,并向程序中的各种侦听器发送适当的事件通知。在某些时候,按键监听器将不得不坐下来等待输入。或者,您可以在不同的线程中拥有该按键侦听器和程序的其他部分 运行。这实际上是 Java 中 Swing 线程模型的工作方式。您有一个主程序线程和一个摆动线程,并且您在两者之间来回发送事件通知(即 SwingUtilities.invokeLater();)
这是一篇较旧的文章,但实际上对于如何在 java 中进行事件驱动编程的基础知识非常有用。我认为它适用于你正在尝试做的事情。 https://community.oracle.com/docs/DOC-982960 它讨论了防御性复制、发送不可变事件对象等内容,以及您为什么需要这样做和担心此类事情。