球球大作战游戏服务器
目录
- 项目简介
- 游戏实现
- 项目逻辑图
- 项目代码简介
- 粘包处理,断线重连部分
- aoi部分
- 项目演示
- 视频演示
- 分析
项目简介
本项目基于 skynet 框架开发,是一个多人对战帧同步游戏服务器,玩家通过移动自身,与其他游戏实体碰撞,吞噬其他实体来增加自身大小。
当前项目完成了游戏核心逻辑,使用大端两字节作为长度信息,服务器端使用 skynet.register_protocol
注册socket消息的拆包和dispatch逻辑来解决粘包问题,其中拆包使用的是netpack.filter方法,默认是大端两字节的方式进行拆包。
游戏战场使用九宫格算法来实现AOI,同时进行碰撞检测,已完成玩家进入战场,玩家移动和吞噬部分核心逻辑,测试环境能维持50帧左右。
服务器支持用户短暂时间断线重连机制,在一定时间内保留用户登录信息,支持重连,超过时间就删除用户信息,再次进入需要重新登录。
游戏实现
项目目录结构
主要文件夹和文件
├── etc
│ ├── config.node1 #节点1 启动文件
│ ├── config.node2
│ └── runconfig.lua #集群配置文件
├── luaclib
│ ├── cjson.so
│ └── protobuf.so
├── luaclib_src
│ ├── lua-cjson
│ └── pbc
├── lualib
│ ├── aoi.lua #aoi 核心计算文件
│ ├── cjson.so #cjson 序列化c库文件
│ ├── protobuf.lua
│ └── service.lua #服务封装文件
├── service
│ ├── agent #玩家agent服务
│ ├── agentmgr #agent管理服务
│ ├── gateway #网关服务
│ ├── login #登录服务
│ ├── main.lua #主服务
│ ├── nodemgr #actor管理服务
│ ├── admin #监控服务(暂无)
│ └── scene #游戏战场服务
├── skynet #skynet框架
└── start.sh #启动shell脚本
项目逻辑图
aoi部分
项目代码简介
粘包处理,断线重连部分
gateway服务主要用来处理玩家登录,断线重连,消息收发功能。这里需要做的就是粘包处理和消息转发。
首先是粘包处理,使用skynet.register_protocol注册socket服务,当有tcp连接的时候就会触发这里的dispatch和unpack方法
unpack方法使用netpack.filter按照默认的大端两字节长度信息的方式来获取信息,并将差分的信息放入到queue这个表里面,接着按照dispatch中触发的MSG对应方法进行消息处理,如果是多条消息就使用MSG.more.单条就MSG.data来处理
因为每次连接都会保存连接的信息到gateway服务中,所以假如用户断线,服务端可以这样处理,不立即删除用户登录连接的信息,而是设置一个定时器来进行判断,如果断线超时才真的剔出用户信息。
aoi部分
使用九宫格来处理游戏的碰撞检测核心逻辑,同步玩家aoi,采集20ms内玩家输入指令,并处理和广播。
aoi在游戏场景中使用方式是先初始化aoi管理器,并传入游戏必要参数,然后注册对应的游戏事件回调函数,例如进入游戏enter,移动move,吞噬 absorb,离开游戏leave事件,当用户在aoi中触发上述事件则会处理这些回调函数。
项目演示
视频演示
球球大作战项目演示
分析
其中play1234和play5678是静止玩家,玩家1112是移动玩家
1.刚刚进入游戏时,玩家互相发现,并且发现场景中的food
2.移动的玩家吞噬食物,并被其他视野内玩家发现
3.两个玩家被吞噬后,并不再接收到信息,这里两个玩家同时被吞噬
两个玩家被同时吞噬的原因是,这个是测试情况,我把玩家的出现位置和移动位置固定在了(10,10)这个范围内,玩家吞噬食物是会变大的,所以移动玩家会变大,你会发现移动玩家1112大小在最后吞噬两个玩家时大小是5.65,玩家1112的位置是(2,6)而玩家1234是静止的,初始位置是(1,3)。玩家5678初始位置是(2,2)
而玩家的初始大小是3,食物初始大小是1,所以很显然两个玩家会被同时吞噬,结果是正确的