V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
waibunleung
V2EX  ›  程序员

求一个 golang 下基于房间的小游戏设计思路

  •  
  •   waibunleung · 2019-02-22 14:30:06 +08:00 · 3711 次点击
    这是一个创建于 1012 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前提,之前没有相关游戏开发经验,go 也是现学,准备练手。

    准备开发一款小程序,类似于 5~10 个人在一个房间里面进行游戏,需要实时数据广播,统计等。

    假设所有用户都在一个同一个房间里面的话还挺好处理,但是如果要分房间的话,不是没有思路,而是不知道有没有更好的。

    目前想到的是 一个房间用一个 goroutine 来处理,里面维持 5~10 个用户 socket,goroutine 用协程池来管理

    可能问题有点幼稚,但是想得到各位指导与启发

    第 1 条附言  ·  2019-02-22 17:13:05 +08:00
    ps:就沒有人提一下 MQTT 的相关东西吗???
    30 条回复    2019-03-21 16:30:21 +08:00
    waibunleung
        1
    waibunleung   2019-02-22 15:17:38 +08:00
    默默收藏了几个,然而没有人回复,我是不是投错节点了?
    jsun
        2
    jsun   2019-02-22 15:29:09 +08:00
    C++和 node.js 的游戏写过,go 没接触过,但是一般不都是每个玩家绑定根据玩家 ID 绑定一个 socket,协程池管理是什么鬼。另外是不是应该先做出点东西,再考虑多人游戏这部分。
    xkeyideal
        3
    xkeyideal   2019-02-22 15:36:14 +08:00
    这还不简单,按照房间进行分组,每个分组里面的成员与服务器保持一个长连接,建议使用 websocket,消息的传播可以分为:组内广播,组内 /跨组单播,跨组广播,跨组指定成员广播。

    看一下 golang websocket 的操作即可,姿势正确,代码很好写
    hehe12dyo
        4
    hehe12dyo   2019-02-22 15:40:23 +08:00
    你怕是想做棋牌的哦
    ahmcsxcc
        5
    ahmcsxcc   2019-02-22 15:48:02 +08:00
    你根本没有做游戏的思想,还想着用 web 那一套去搞
    waibunleung
        6
    waibunleung   2019-02-22 16:03:48 +08:00
    @ahmcsxcc 我前提已经说过了,请这位童鞋好好审题。
    另外思想这些东西也是需要学习的,不是一想就来。
    我发这个主题的意思就是想得到大家的指点,而不是告诉我一些我已经知道的东西(没有做游戏的思想,还想着用 web 那一套去搞),不过还是谢谢你指出的问题
    waibunleung
        7
    waibunleung   2019-02-22 16:04:43 +08:00
    @hehe12dyo 不是噢,不过就是有点类似,不知道有没有好的办法
    waibunleung
        8
    waibunleung   2019-02-22 16:09:50 +08:00
    @jsun 小程序前端这一块进度已经是 80%,差与后台重要部分的对接,这部分就是我在问题上面问的,可能这点没在问题上说清楚,我的锅。
    协程池是基于我在问题上面描述的思路提出来的,不具有普遍性。
    另外回复上面你只告诉我每个玩家根据 ID 绑定一个 socket,这个是必然的,但是房间的话怎么处理呢?
    希望能具体说说你们一般是怎么做的,感谢~
    waibunleung
        9
    waibunleung   2019-02-22 16:14:42 +08:00
    @xkeyideal 感动,你是第一位审题正确的同学!
    但是我有几个问题想问:
    1.房间的载体可以是什么? map?channel?goroutine?
    2.感觉你说的思路跟我在问题里面提出来的差不多,不知道是否有改进空间?
    zjsxwc
        10
    zjsxwc   2019-02-22 16:20:35 +08:00 via Android
    对实时性要求不高的话,简单粗暴 http json 接口解决,搞个 golang 的 web 开发框架就行。

    如果是王者荣耀这种实时要求高的,用 kcp 协议基于 udp 也不用 tcp 长连接。
    tcfenix
        11
    tcfenix   2019-02-22 16:21:31 +08:00
    传统的游戏服务器是 gateway 集群负责维护长连接,然后登陆到 homeserver,之后创建房间就是在 roomserver 上建立一个 room 结构体,把人放进去
    单线程死循环遍历 room 结构体做各种超时之类的处理
    每次房间内有什么变化就广播给房间里面所有人,这边用协程处理挺不错的

    golang 中要实现看你是打算改动多少,你要是想把时间什么的事件化那倒是可以不需要死循环
    tcfenix
        12
    tcfenix   2019-02-22 16:22:00 +08:00
    tcfenix
        13
    tcfenix   2019-02-22 16:23:21 +08:00
    @zjsxwc
    kcp 本身也是长连接啊,而且关于 rudp 这个问题其实争议非常多
    tcfenix
        14
    tcfenix   2019-02-22 16:24:56 +08:00
    @waibunleung
    一般房间的载体就是一个结构体,放在一个定长,比如 10000 或者 10000 的数组里面
    然后通过一个 map 对这个数组做一个索引,不要想得太复杂
    waibunleung
        15
    waibunleung   2019-02-22 16:27:23 +08:00
    @tcfenix 很好~但是现在我手上就一台可调用的服务器,不过参照你的说法,我感觉有点小小的眉目,谢谢你~
    mosliu
        16
    mosliu   2019-02-22 16:28:16 +08:00
    和聊天室一样的吧 维护一个在线结构体 这个结构体放入一个 ws 和相应的用户信息就可以
    然后在定义一个聊天室的结构体 内存储相应的在线用户, 收发广播消息时候 循环发送给所有用户不就可以了?


    是我想简单了吧?
    mosliu
        17
    mosliu   2019-02-22 16:30:02 +08:00
    多个房间的话。 每个房间一个携程 阻塞一个或多个 channel 有消息扔 channel 不就可以了。
    tcfenix
        18
    tcfenix   2019-02-22 16:30:06 +08:00
    @waibunleung
    这里的各个服务器其实指的是进程,比如 gateway 开个几个进程,homeserver 开几个进程,你想分开就分开部署在不同服务器上,不过这个架构也许对你的业务场景来说有点重,可以合并起来,以后有必要再切分
    xkeyideal
        19
    xkeyideal   2019-02-22 16:48:04 +08:00
    @waibunleung 知道我为啥审题正确么?虽然不是做游戏,但类似这种需求的项目我写过好多个了。

    你说的载体我不是很明白,定义一个 struct,把 ws 长连接的 conn 放进去,然后另开 goroutine 搞呗。

    如果还不懂,去找个 example 看看,学起来轻松一点。

    友情提示:自己玩玩 websocket 随便搞,考虑性能和功能的话,很多事情要做
    waibunleung
        20
    waibunleung   2019-02-22 16:54:08 +08:00
    @xkeyideal 好的,非常感谢~
    waibunleung
        21
    waibunleung   2019-02-22 16:55:55 +08:00
    @mosliu 你这个想法好像跟我问题里面提出的差不多,谢谢你的回复~我去试一下
    waibunleung
        22
    waibunleung   2019-02-22 17:23:31 +08:00
    @tcfenix 另外,不需要关心 ws 过多以及 MQTT 相关的问题吗?
    pubby
        23
    pubby   2019-02-22 17:40:55 +08:00   ❤️ 2
    做过一些类似的

    有些是房间无关的:
    1. 比如 websocket 建立后,首先需要用户认证,让服务端识别这个连接对应的用户。认证可以用类似 access_token 的方式,客户端建立连接后第一个消息发送 access_token,让服务端识别用户,并绑定连接和用户 ID 之间的关系。
    2. 移动端掉线、网络切换、进入后台连接断开都比较频繁,需要定时往返一些心跳消息让服务端知道用户是否还在线。
    3. 游戏的话可能涉及到时间同步,可以在心跳消息中带上用于计算客户端和服务端时间误差的一些信息。

    房间相关的:
    其实很简单,客户和服务端发送房间相关的消息都带上房间 id 就行了。
    服务端每个房间开一个 goroutine,维护房间里的用户列表,处理房间相关的消息
    服务端根据消息中的房间 id,把消息写入房间 goroutine 对应的消息 channel 就行了。


    思路其实很简单,就是细节还很多,做了才知道。


    长连接是比较耗资源的,如果游戏火爆,长连接服务做分布式接入比 http 麻烦很多,就不多说了。

    另外记得用 github.com/gorilla/websocket 这个包,不要用 go 标准库里的那个残废。
    jeremaihloo
        24
    jeremaihloo   2019-02-22 19:42:13 +08:00 via Android
    github mqant 项目,官方有例子,原生支持 mqtt
    vlyonline
        25
    vlyonline   2019-02-22 20:01:08 +08:00
    哈哈,我也在搞这个,不过我在搞麻将,有点头大,我准备用结构体 room 里面放个数组,数组里面放房间里面的人~~~~~~广播很简单的,你去实现一个聊天室,然后基于这个聊天室做分房间功能就可以了,只是结构体和数据放一起有点恶心
    tairan2006
        26
    tairan2006   2019-02-22 20:32:38 +08:00
    楼主可以看一下 leaf 这个项目,每个房间一个协程没问题的
    waibunleung
        27
    waibunleung   2019-02-23 14:46:15 +08:00
    @pubby 真的十分感谢你的提点
    waibunleung
        28
    waibunleung   2019-02-23 15:19:17 +08:00
    @jeremaihloo 你好我想问一下为什么多数都推荐游戏服务器走 mqtt 协议?它是一个物联网协议,在游戏领域应用有什么意义或者优势吗?
    SmallSir
        29
    SmallSir   2019-03-21 16:14:03 +08:00
    @xkeyideal 我想知道如何实现组内广播,跨组广播这种呢
    xkeyideal
        30
    xkeyideal   2019-03-21 16:30:21 +08:00
    @SmallSir 按组存储,遍历发送
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2456 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 15:20 · PVG 23:20 · LAX 07:20 · JFK 10:20
    ♥ Do have faith in what you're doing.