Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[light-game-room] 重构 room 扩展模块 - 适用桌游类的游戏 #278

Closed
iohao opened this issue May 9, 2024 · 5 comments
Closed
Assignees
Labels
enhancement;功能增强 Function enhancement;功能增强 Support extension;可扩展 Support extension;可扩展 trick;使用技巧 trick;使用技巧

Comments

@iohao
Copy link
Owner

iohao commented May 9, 2024

计划重构 room 模块,简化相关 api 的使用,并提供相关文档。在此之前,由于该模块较偏特定业务,且示例流程涉及较多,所以一直没有提供相关文档与示例。

room 模块比较适合桌游类的游戏基础搭建,基于该模型可以做一些如,炉石传说、三国杀、斗地主、麻将 ...等类似的桌游。或者说只要是房间类的游戏,该模型都适用。比如,CS、泡泡堂、飞行棋、坦克大战 ...等。


简介 - light-game-room 房间

light-game-room 房间,是 ioGame 提供的一个轻量小部件 - 可按需选择的模块。

该模块的主要职责有三个方面,分别是房间、玩家、操作。

  • 房间相关的包括,房间的创建、房间的管理及对房间内玩家的管理(如玩家退出房间、加入房间,控制房间内的人数 ...等)。
  • 玩家方面相关的包括,玩家的信息及在房间内所持有的资源(资源指的是玩家所持有的子弹、牌、道具 ...等,需根据游戏来确定)。
  • 操作方面相关,由于不同游戏之间的具体操作是不相同的,如坦克的射击,飞行棋的投骰子行走,炉石的战前选牌、出牌,麻将的吃、碰、杠、过、胡,回合制游戏的普攻、防御、技能 ...等。上述这些不同的操作,我们可以通过扩展 OperationHandler 接口,来处理具体的业务玩法;同时这种扩展方式更符合单一职责,使得我们后续的扩展与维护成本更低。

基于该模块的扩展,可以减少大量的重复工作,基本只需关注自身游戏的特定业务。

@iohao iohao self-assigned this May 9, 2024
@iohao iohao added trick;使用技巧 trick;使用技巧 enhancement;功能增强 Function enhancement;功能增强 Support extension;可扩展 Support extension;可扩展 future;将要提供 The latest version will be available;近期版本将要提供的功能 labels May 9, 2024
@iohao
Copy link
Owner Author

iohao commented May 9, 2024

桌游戏类游戏的大致流程

  • 房间创建
  • 玩家创建
  • 进入房间
  • 退出房间
  • 解散房间
  • 游戏开始

游戏开始后,就是房间内的各种操作了,即上面提到的,如坦克的射击,飞行棋的投骰子行走,炉石的战前选牌、出牌,麻将的吃、碰、杠、过、胡,回合制游戏的普攻、防御、技能 ...等。


该模块是一个较综合的实战模块,通常在制作一个游戏时,至少可能涉及以下几个点

后续计划做一个相关实战的 demo,将包括前后端。前端计划使用 FXGL 引擎,这样开发者在学习时,只需 JDK 环境就可以了,而不需要安装更多的环境。

重构之后,将提供 room 模块的详细使用文档。

@iohao iohao changed the title [light-game-room] 重构 room 扩展模块 [light-game-room] 重构 room 扩展模块 - 适用桌游类的游戏 May 10, 2024
@iohao
Copy link
Owner Author

iohao commented May 19, 2024

相关文档: room 桌游、房间类 (yuque.com)

@iohao
Copy link
Owner Author

iohao commented May 19, 2024

基于 room 模块的实战简介

现在,我们基于该 room 模块做一个实战示例,该示例整体比较简单,多名玩家在房间里猜拳(石头、剪刀、布)得分。

实战示例包括了前后端,前端使用 FXGL 引擎,这样开发者在学习时,只需 JDK 环境就可以了,而不需要安装更多的环境。


源码统计与功能介绍

image

基于 room 模块的扩展,只需要数百行代码就完成了该实战示例,包含的功能如下:

  • 登录
  • 玩家进入大厅(地图)
  • 玩家可在大厅移动
  • 玩家移动时相互可见
  • 玩家离开大厅(玩家下线)
  • 查询房间列表
  • 房间信息实时变更通知(房间内有玩家数量变化,等待中、游戏中 ...等状态)
  • 玩家创建房间
  • 玩家进入房间
  • 玩家退出房间
  • 解散房间
  • 玩家准备
  • 开始游戏
  • 玩家在房间内的玩法操作
  • 对接文档生成..等

正如开头介绍所说的,room 模块很好的帮助开发者屏蔽这些重复性的工作,并可为项目中的功能模块结构、开发流程等进行清晰的组织定义,减少了后续的项目维护成本。更重要的是有相关文档,将来当你的团队有新进成员时,可以快速的上手。


大厅

启动游戏后玩家会将加入大厅(类似地图),多名玩家相互可见,并且玩家可以在大厅内移动。

图中左边是玩家的可移动区域,右边房间列表信息。

image


大厅的玩家可以看见当前的房间列表信息,房间列表信息会实时的变化,比如游戏开始后,会由等待中变成游戏中。房间内的玩家数有变更时,也会实时的更新。

玩家可以创建一个房间,等待其他玩家的加入,也可以加入一个已经存在的房间与其他玩家共同游戏。

image

image

准备、游戏开始

image

游戏开始后,每个玩家可以选择要出的(石头、剪刀、布),选择好后会显示到左边的面板中;右边是当前房间内的得分排行,得分最高的排在前。

游戏时,每局有一定的时间供玩家选择,倒计时结束后会公布结算结果。如果倒计时结束玩家没有选择,那么服务器会强制帮未操作的玩家做出随机选择。

image

image

游戏结束

游戏结束后,玩家可以离开房间。

image

@iohao
Copy link
Owner Author

iohao commented May 19, 2024

@iohao iohao closed this as completed May 19, 2024
@iohao iohao removed the future;将要提供 The latest version will be available;近期版本将要提供的功能 label May 19, 2024
@iohao
Copy link
Owner Author

iohao commented May 19, 2024

小结、扩展玩法操作

现在我们知道了,基于 room 模块的扩展,可以帮助开发者屏蔽大量重复性的工作,减少大量的代码。并可为项目中的功能模块结构、开发流程等进行清晰的组织定义,减少了后续的项目维护成本。

此外,该模型还可以帮助我们在编码时,减少心智上的负担。以玩家的操作玩法为例,下面是我们扩展的一个操作玩法,即选择(石头、剪刀、布)其中一个。

该扩展将验证与业务逻辑分离,这样可以使得我们的代码更加的清晰。

代码之所以清晰,是因为我们的验证使用了断言机制(断言 + 异常机制 = 清晰简洁的代码)。传统的框架需要开发者疯狂 if else,且每次需要手动手动传输错误码,相关讨论可阅读传统写法或祖传代码写法

// 验证与实际业务逻辑分离
// 将玩家的选择(石头、剪刀、布)广播给房间内的其他玩家。
public class ChooseOperationHandler implements OperationHandler {
    @Override
    public void verify(PlayerOperationContext context) {
        // 玩家操作的数据
        FightOperationCommand command = context.getCommand();
        int elementIndex = command.elementIndex;
        // 验证玩家的操作数据是否合法(石头、剪刀、布)
        GameCode.illegalOperation.assertTrue(FiveElementKit.verify(elementIndex));
    }

    @Override
    public void process(PlayerOperationContext context) {
        FightRoomEntity room = context.getRoom();
        long userId = context.getUserId();

        // 将玩家的元素选择(石头、剪刀、布)保存到当前对局中
        var fightRound = room.getCurrentFightRound();
        var item = fightRound.getItemByUserId(userId);

        FightOperationCommand command = context.getCommand();
        item.setElementIndex(command.elementIndex);

        // 房间内广播 - 有玩家做了选择
        room.ofRangeBroadcast()
                .setResponseMessage(RoomCmd.of(RoomCmd.operationBroadcast), LongValue.of(userId))
                .execute();
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement;功能增强 Function enhancement;功能增强 Support extension;可扩展 Support extension;可扩展 trick;使用技巧 trick;使用技巧
Projects
None yet
Development

No branches or pull requests

1 participant