15、探索 JR 与 GUI 的融合:Balls and Boxes 游戏实践

探索 JR 与 GUI 的融合:Balls and Boxes 游戏实践

1. GUI 与 JR 的融合趋势

在当今的软件开发领域,图形用户界面(GUI)正变得越来越普遍、强大、灵活且易于使用。例如,Swing 和 AWT 工具包使 Java 程序能够轻松地包含 GUI 元素。GUI 不仅提升了用户体验,还在可视化并发程序的执行过程中发挥着重要作用。下面将通过一个名为“Balls and Boxes”(简称 BnB)的简单游戏,详细介绍如何将 JR 与 Swing 结合使用。

2. BnB 游戏概述

2.1 游戏基本信息

BnB 是一款多人游戏,可在多个系统上进行,每个系统对应一名玩家。当然,它也支持单系统单玩家模式,在单系统中既可以只显示一个窗口,也可以显示多个窗口。玩家通过系统的键盘和鼠标与游戏进行交互。

2.2 游戏界面与元素

游戏窗口包含菜单、按钮和棋盘区域。每个窗口都有唯一的标识符(0, 1, 2, …),并按标识符从左到右排列。棋盘区域包含两种“玩具”:球和盒子,还有一条随机移动的文本消息。具体操作及元素规则如下:
|操作/元素|规则|
| ---- | ---- |
|菜单|每次点击菜单会创建一个绿色或橙色的球|
|按钮|每次点击按钮会创建一个蓝色球和一个红色球|
|球|自动从左到右移动,在窗口的顶部和底部之间曲折移动,碰到顶部或底部会反弹。初始位置随机选择,到达右边界后会移动到右侧的下一个窗口或回到第一个窗口,移动一定次数后消失|
|盒子|在用户键盘控制下移动,到达左或右边界时会移动到前一个或下一个窗口,不能超出顶部或底部边界,在游戏期间一直存在|

2.3 游戏窗口示例

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A(窗口 0):::process --> B(窗口 1):::process
    B --> C(窗口 2):::process
    C --> A
    A -->|球和盒子移动| B
    B -->|球和盒子移动| C
    C -->|球和盒子移动| A

3. BnB 代码概述

3.1 代码结构

BnB 程序由以下几个主要类组成:
- Main :主程序,为每个玩家创建一个窗口,并将它们放置在各自的虚拟机上。
- Window :代表一个窗口,创建游戏所需的图形组件,如菜单、按钮和棋盘。
- SwingApplication :创建按钮。
- Board :棋盘类,创建并控制棋盘上的玩具。
- Toy :所有玩具的基类,其派生类包括 Ball、Box 和 Mtext。
- KeyInput :处理键盘输入。
- MouseInput :处理鼠标输入。

3.2 图形组件绘制

在使用 Swing 的程序中,每个图形组件都提供了 paintComponent 方法,该方法在框架重绘时被调用。在 BnB 程序中, Board 类提供了 paintComponent 方法,负责绘制棋盘上的所有玩具。按钮和菜单有预定义的 paintComponent 方法。框架在检测到内容变化(如按钮被点击)或接收到显式的重绘请求时会重绘自身。不过,由于 Swing 的事件驱动特性,重绘请求不一定会立即执行,多个重绘请求可能会被合并为一个。Swing 还提供了 paintImmediately 方法,用于需要立即绘制的情况。

3.3 各主要类详细分析

3.3.1 Main 类

Main 类为每个玩家创建一个 Window ,并将它们放置在各自的虚拟机上。虚拟机可以在命令行指定的物理机上创建,若未指定则在本地主机上创建。然后,它为每个棋盘提供所有棋盘的远程引用,以便棋盘之间可以传递球和盒子。与其他类似代码不同的是,这里使用了额外的 goahead 操作,确保所有棋盘在启动 ballManager 之前都已收到它们的链接,并且向每个棋盘发送了所有棋盘的引用,方便后续添加新功能。

3.3.2 Window 类

Window 类创建游戏所需的图形组件,包括棋盘、按钮和菜单。代码较为详细,以指定所有所需的图形特性。它将按钮和棋盘放置在一个名为 mainPanel 的 JPanel 中,并设置了用于退出游戏和将焦点设置到棋盘的监听器。通过传递棋盘的 startBall 操作的能力,使按钮和菜单能够创建新球。

3.3.3 Button 类

SwingApplication 类创建按钮,该代码对参考代码进行了轻微修改。按钮会记录点击次数,每次点击会创建一个蓝色球和一个红色球,使用棋盘的 startBall 操作来创建球。

3.3.4 Board 类

Board 类创建棋盘并控制玩具的移动,使用 myToys 列表来管理棋盘上的玩具。当玩具从一个棋盘移动到另一个棋盘时,会从当前棋盘的 myToys 中移除,并添加到新棋盘的 myToys 中。棋盘代码还包含一个启动过程,用于处理棋盘的启动(接收所有棋盘的远程引用)并创建初始的球和盒子。对于每种玩具,棋盘提供一个管理器来控制其移动。
- MtextManager :最简单的管理器,因为每个棋盘上只有一个 Mtext 对象,且该对象不会移动到其他棋盘。它首先创建一个 Mtext 对象,然后进入一个无限循环,随机选择文本的新位置,通知对象更新位置,请求重绘棋盘,然后随机休眠一段时间。
- BallManager :创建和控制球的代码较为复杂。 Board 类为球提供了 start restart 操作。 start 操作用于创建新球, restart 操作在球从一个棋盘移动到另一个棋盘时使用。 ballManager 进程最多循环 iters 次,每次循环计算球的新位置,处理边界情况,如球到达顶部或底部时反弹,到达左右边界时发送消息到相邻棋盘的 restartBall 操作。
- BoxManager :盒子的创建和控制与球类似,但 boxManager 接收字符输入来确定盒子的移动方向。当盒子离开当前棋盘时,当前棋盘上的管理器终止,盒子被传递到相邻棋盘,由新的 boxManager 管理。

3.3.5 Toy 类

Toy 类是所有玩具的抽象基类,提供了玩具共有的字段和方法,并且是可序列化的,以便在不同虚拟机上的棋盘之间传递玩具。 Ball Box 类继承自 Toy 类,每个类都有一个 mydraw 方法,用于在玩具的当前位置绘制球或盒子。

3.3.6 Input 类

KeyInput MouseInput 类用于向棋盘提供输入。 KeyInput 类接收一个字符输入能力,只发送有意义的字符并处理游戏退出。 MouseInput 类结构类似,但在这个游戏中,棋盘不使用鼠标点击事件,因此传递了一个空操作能力作为鼠标点击参数。

3.4 代码同步与重绘

myToys 集合被声明为 synchronizedList paintComponent 方法使用 Java 的 synchronized 语句来提供对 myToys 集合的互斥访问,确保在重绘时其他进程不会修改 myToys 。不过,一般不建议混合使用 Java 和 JR 的同步机制,但这里的操作简单且安全,因为被 synchronized 语句阻塞的线程不会无限阻塞,也不会干扰 JR 的静止检测。

4. BnB 程序的其他要点

4.1 常量与焦点设置

BnB 代码中有许多常量,如用于指定窗口和玩具大小的常量。这些常量本可以通过命令行参数指定,但为了简化代码展示而未采用。在 BnB 中,由于棋盘由包含另一个面板(棋盘)和按钮的主面板组成,键盘焦点会在这两个组件之间切换。可以通过按 Tab 键在组件间更改焦点,并且当窗口激活(鼠标移入窗口)时,代码会将焦点设置到棋盘区域。不过,是否需要设置焦点取决于程序所使用组件的具体结构。

4.2 JR 与 Swing 的交互问题

JR 的正常行为是在程序静止时终止程序。但当前 JR 实现无法感知 Swing(或 AWT)事件,这些事件与 JR 程序异步发生。例如,当一个使用 Swing 的 JR 程序阻塞等待键盘字符输入(如 boxManager 中)或鼠标点击,且程序中没有其他进程时,JR 实现会认为程序静止并终止它。BnB 程序不会终止,因为其 MtextManager 执行一个无阻塞(除了休眠)的无限循环,JR 实现能感知到这种情况。为防止此类终止,有两种方法:
- 使用命令行选项(具体细节可参考相关文档)。
- 使用一个额外的“休眠”进程,让其休眠时间长于程序执行时间,或在无限循环中进行任意时长的休眠。

4.3 Swing 的其他有用特性

Swing 包含许多其他有用的特性,以下是一些在编写 JR 程序时可能有用的部分特性列表:
|特性|描述|
| ---- | ---- |
|多种按钮和菜单|提供丰富的界面元素选择|
|键盘菜单选择|可使用“加速器”通过键盘选择菜单|
|其他类型的框架|如文本框架可实现不同系统用户间的聊天,或在每个窗口中显示小状态窗口展示所有棋盘情况|
|图像支持|可以用图片替代简单图形,如用猫的图片替代盒子的矩形|
|动画定时器|用于实现动画效果|

4.4 Swing 与 AWT 的比较

BnB 程序使用了 Swing,但也可以用 AWT 编写。Swing 非常灵活,但由于选项众多而较为复杂;AWT 是较低级的工具包,可能更容易学习。不过,Swing 似乎是更推荐的选择,因为 Swing 程序在任何系统上都能呈现相同的图形显示,而 AWT 程序依赖于主机的本地窗口系统,不能保证这一点,这种可移植性在许多应用中非常重要。

5. 扩展与优化建议

5.1 游戏功能扩展

可以对 BnB 程序进行多种修改以增加游戏的趣味性,以下是一些具体的扩展建议:
1. 球的移动方向
- 让球可以随机选择从右到左或从左到右移动。
- 扩展菜单,让用户可以选择球的移动方向,菜单创建的球按所选方向移动。
2. 盒子的移动规则
- 允许盒子从棋盘顶部到底部或从底部到顶部环绕移动。
- 当没有按键输入时,盒子保持最后指定的方向移动。
3. 添加障碍物 :在棋盘上添加障碍物,球可以穿过障碍物,而盒子不能。
4. 新玩具 :添加三角形玩具,整个游戏中只有一个三角形玩具,在每个棋盘的相同位置显示,它会随机且定期(如每秒一次)移动。
5. 特殊按键功能
- 按下 ‘c’ 键,盒子直接移动到其初始创建的棋盘。
- 按下 ‘p’ 键,游戏在所有窗口中暂停,直到在同一窗口再次按下任意键。
6. 鼠标交互
- 在棋盘内点击鼠标,将盒子移动到鼠标位置,如果盒子在其他棋盘,移动到指定位置。
- 在棋盘内点击鼠标,将键盘焦点设置到该棋盘。

5.2 计分系统

可以修改 BnB 程序,为每个玩家设置计分系统,并在每个玩家的显示屏上显示当前分数。例如,当满足以下条件时奖励分数:
- 盒子与球在屏幕上碰撞。
- 盒子与另一个盒子碰撞,且第一个盒子不在其主棋盘上。
- 盒子发射的子弹击中球,这需要让盒子能够发射子弹,并进行其他相关更改,如改变盒子形状以指示射击方向,允许盒子旋转(如通过 ‘a’ 键逆时针旋转,’s’ 键顺时针旋转)以调整射击角度。

5.3 其他应用开发

除了扩展 BnB 游戏,还可以开发其他包含 GUI 的分布式 JR 程序进行动画或可视化,以下是一些可能的应用示例:
- 游戏类 :如扑克、乒乓球、海战、大富翁、吃豆人等。
- 严肃应用类 :如最短路径查找、分布式编译、缓存模拟、多处理器可视化等。

开发时可先构建一个简单的原型,展示所选应用的基本并发方面,然后逐步完善并添加更多功能。

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A(初始原型):::process --> B(功能添加):::process
    B --> C(完善优化):::process
    C --> D(最终应用):::process

通过以上对 BnB 游戏的介绍和扩展建议,我们可以看到 JR 与 GUI 结合的强大潜力,无论是在游戏开发还是其他应用领域,都能为用户带来丰富的交互体验。希望这些内容能为开发者提供一些思路,激发更多创新的应用开发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值