当前位置: 首页 > 知识库问答 >
问题:

使命令行驱动的基于回合的rpg适应Swing的事件驱动范例

终翔
2023-03-14

背景:

在过去的几个月里,我在空闲时间里一直在用Java开发一个回合制的RPG。我只做了大约一年的编程,所以我的专业知识主要局限于命令行应用程序和面向对象的编程原则,这些都是我在基本的CS课上学到的。

开发一直进展顺利,直到我开始调整游戏,从命令行输入到使用我开始使用Swing构建的定制UI。这在很大程度上是因为基于命令行的输入允许我停止正在做的一切,并等待扫描仪或类似的输入,但从我在这里读到的线程来看(等待Java Swing中的多个按钮输入,直到按钮被按下),Swing的事件驱动性质并不允许您在不中断EDT和冻结GUI的情况下等待任何事情,这对我来说是一件坏事。

问题是:

虽然Swing对我来说相当新奇,但我已经将它用于主菜单,并看看它如何方便地应用于数据相对集中在几个对象之间的游戏,这些对象利用用户的简单命令来移动或攻击或其他东西。我的问题是,我的RPG在战斗场景中有2到16个活跃的角色,可以由用户控制或人工智能控制,可以使用任意数量的不同命令(包括类似16个不同的技能),玩家角色必须能够访问所有角色之间的公共库存。可以说,我的游戏非常依赖菜单。例如,我将发布一个从战斗期间运行的循环调用的方法:

//initializes a turn; written as a function to cut down on duplicate code
public battleData initializeTurn(battleData toInitialize){
    if(toInitialize.initializeSkill()) {
        if(toInitialize.initializeTarget(playerParty, playerMinions, 1) == 0)
            return initializeTurn(toInitialize); //recursive call if the user cancelled
    }                                            //the skill they selected.
    else {
        if(toInitialize.initializeTarget(enemyParty, enemyMinions, -1) == 0)
            return initializeTurn(toInitialize); //see above
    }
    return toInitialize;
}

此方法调用gameCharacter类中编写的两个函数initializeTarget和initializeSkill从两个传递目标数组中选择一个目标,并从角色的两个技能列表中选择一个技能。从gameCharacter类派生的是playerCharacter和Monster类,它们分别根据用户输入和基本的AI计算方法的返回值。由于我有很多关于技能和项目的数据存储在不同的类中,用户输入的行为取决于输入的角色,无论他们是选择目标还是选择技能,以及他们在技能选择菜单范围内的位置,我发现很难制定一个算法来使整个事情成为事件驱动的,因为事件可能意味着许多不同的事情,这取决于当前正在查看菜单的哪个部分。

我读过一些东西,比如swingworkers被用来处理后台任务,状态被用来向不同的地方提供输入,计时器被用来定期更新图形组件,但我对Swing不够熟悉,无法真正知道在这一点上最好的路线是什么。我更多的是寻找一个通用算法来实现,而不是一个神奇的解决方案,它可以让我在不改变代码的情况下解决我的问题。我非常愿意对我写的东西进行修改,所以不要害怕告诉我,如果你认为这会使程序更好,我将不得不重做很多东西。

谢谢你对我的宽容;如果您需要更多的上下文,我很乐意解释或发布更多的代码。一开始我会发布更多,但我提到的大多数菜单都是1-200行,比实际复制更容易解释。

共有1个答案

胡璞瑜
2023-03-14

首先,您可以将GUI看作是在更新屏幕时不做任何事情的东西,而不是命令行在等待输入时不做任何事情,这样可以稍微简化这个问题。因为这是一个回合为基础的游戏,必须有要求什么时候回合被认为是准备好计算。通常,当用户完成输入时,就会发生这种情况。在您的例子中,从我收集到的信息来看,输入基本上是对不同游戏角色的命令。因此,每次用户命令做某事(单击游戏角色的命令按钮)时,都必须进行类似于isreadytoCompute()的检查。当方法返回true时,可以调用computeTurn()。下面是一些粗略的代码表示。你需要添加一些与游戏相关的检查,但它应该给出一个从哪里开始的想法

skillButton1.addActionListener(e -> {
    // change cursor to "select" type cursor
    skill1 = true;
});

public class Mouse implements MouseListener {
    public void mouseClicked(MouseEvent e) {
         // get mouse x y
         // find target game character at x y or if none then return
         // remember the character as target
         // of skill1 of selected character
         // and count this as order complete for selected character
         skill1 = false;
         // change cursor to normal

         if (isReadyToCompute()) computeTurn();
    }
}

总体思路是,您不需要循环,因为GUI已经有了自己的内部循环,并且在EDT上运行。EDT捕获并分派由动作和鼠标侦听器处理的事件。当使用命令行时,您等待侦听输入事件的扫描器,类似地,在GUI中,您等待前面提到的侦听器,后者反过来侦听按钮按下或鼠标事件。有关如何编写侦听器的更多信息,请参阅官方的Oracle教程:

https://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html

 类似资料:
  • 我正在用Java创建我的第一个游戏。游戏是大富翁。我在纠结如何设计游戏,使其基于回合的结构模型(管理玩家回合)。我想允许一个单一的人控制和一个或多个人工智能控制的玩家玩游戏。 我的具体问题是,我不知道是否要实现一个游戏循环,这意味着一个循环可以管理玩家和与大富翁游戏直接相关的变量,(想想这样的事情,比如提示每个玩家进行他们的回合,增加回合到下一个玩家,或者从每个玩家那里获得骰子滚动--依次)。我指

  • 对手转向 游戏等待用户 用户将文本键入JtextField并按Enter键 游戏执行玩家命令 对手再次转向..

  • 目前是否已知 Google 云端硬盘 API 示例命令行应用(云端硬盘命令行)可以正常工作?我已经下载了 Java 客户机库,并编译了示例应用程序(插入通过指定“已安装的应用程序”和“其他”创建的应用程序的客户机标识和密钥)。它运行并通知我在浏览器中访问以下链接: https://accounts.google.com/o/oauth2/auth?access_type=online (显然我的实

  • fmu 源代码: drivers/px4fmu 说明 该模块负责驱动输出以及读取输入引脚。对于没有单独IO芯片的飞控板(例如Pixracer),它使用主通道。在具有IO芯片(例如Pixhawk)的飞控板上,它使用辅助通道,px4io驱动程序使用主通道。 它通过监听actuator_controls主题,实现混控以及PWM输出。此外,它还进行RC输入解析并自动选择解析方法。支持的方法有: PPM S

  • 本文向大家介绍Node.js事件驱动,包括了Node.js事件驱动的使用技巧和注意事项,需要的朋友参考一下 Node.js事件驱动实现概览 虽然在ECMAScript的标准里并没有(也没有必要)明确规定“事件”,但是在浏览器中,事件作为一个极为重要的机制,给予JavaScript响应用户操作与DOM变化的能力;在Node.js中,异步事件驱动模型则是其高并发能力的基础。 学习JavaScript也

  • 8.1.3 事件驱动 图形构件组成了图形界面的可见部分,在这些可见构件的背后,还有不可见的程序逻辑。 就好比家用电器都提供操作面板,用户通过操作面板控制、使用电器功能,在面板的背后是 实现功能的电路逻辑。 GUI 应用程序的特点是注重与用户的交互,因此程序的执行取决于与用户的实时交互情 况。例如 Word 程序启动后,并非一路执行到程序结束,而是在做了必要的初始化工作后就 停下来,等待用户的下一步