游戏服务器背包设计与实现

Golang语言社区 · · 1149 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

原文:https://www.cnblogs.com/wgslucky/p/6079730.html


在游戏开发中,背包是一个非常重要的功能。几乎每个复杂点的游戏都会有背包的功能。不管是手游戏还是网页游戏,不管是SLG游戏,还是ARPG游戏,背包是必不可少的。背包的功能根据策划的要求,有的简单,有的复杂。以下我们就讨论一下几种游戏服务器背包的实现。

1,简单的游戏背包设计

简单的游戏背包到底简单到什么程度呢?那么这个游戏背包只是用来存放物品,不需要记录物品在背包中的位置,只需要记录物品的id和物品的数量即可。这样的游戏背包设计起来非常方便,在数据库中一个物品占一行即可,例如:

image

当获得物品的时候,先查看这个物品是否已存在,如果不存在,则创建一个物品的对象,并插入到数据库,如果这个物品对象已存在,则只需要更新物品的数量即可。而在客户端显示的时候,是否可叠加,叠加上限是多少,由客户端自己去计算就可以了。使用物品的时候,只需要更新相应的数量即可。另外一个要求是要检测背包是否满了,我们只需要在初始化背包的时候记录一下背包的最大格子数和已使用的格子数就可以了。如果获得的物品在背包中不存在或叠加数已满,且没有剩余的格子则返回背包已满的提示。

2,有特殊物品的游戏背包设计

再复杂一些的背包是,有一些特殊的物品,比如装备,装备一般都是可以镶嵌宝石的,这样的话每个装备的id是不能相同的,即使是同一件名字一样的装备,它也要有一个唯一标识的id。这样就需要我们在放入物品的时候给物品生成一个唯一的id标识。生成唯一id的算法之前也介绍过,可以参考:http://www.youxijishu.com/h-nd-147-0_35.html(游戏服务器生成全局唯一ID的几种方法)但是这些方法感觉用在生成背包物品唯一id上有点大材小用了。我们再提供一个方法,以供参考:

唯一id用一个long类型存储,long类型有64位,我们使用它的低32位存储策划配置的物品表中的物品id,高32用来记录每获得一个物品就自增加1的序列order,即

Int itemBaseId = 10001;//配置表中的物品id

Int order = 1;//每获得一个物品这个序列自增加一,每个游戏背包都有自己的order,这样可以减少并发对order的增加。

Long itemUid = (((long)order)<< 32) + (long)itemBaseId;

那么这个order怎么记录呢?这个order不用记录,那么当玩家退出后再进入游戏怎么得到这个order呢?我们在玩家登陆时第一次初始化游戏背包时,只需要从每个itemUid中拿出来每个物品的order,然后比较一个,得到最大的order做为起始order即可。这样可以从一个itemBaseId中获得一个order:

Int order = itemUid >>> 32;

而那些可以叠加,不需要唯一id的物品,只需要把它们的配置id转化为long存储即可。

这样在内存中,我们可以把所有的物品放入一个Hashmap中,获得新物品和使用物品也不用遍历查找,速度很快。

3,带位置索引的游戏背包设计

更为复杂的背包,就是需要记录物品在背包中的位置索引。一般这样的游戏背包都会带物品的位置交换和整理功能。这种背包麻烦的是那些可以叠加的物品,因为同一个物品可能会占多个格子,而且还不连续。

我们还利用上面第二种背包的唯一id方式,不过这里会多增加一个物品在背包中的位置索引,唯一id还是long类型,而long是由:orderId + 位置索引 + 物品配置id组成。

比如:高25位为order,中间10位为位置索引(一个背包有一千多个物品也差不多了),剩余的29位存储物品的配置id,这些位数可以根据实际需要自己调整。

在内存中,我们用一个数组来存储所有的物品,每个物品占一个格子,数组索引即物品的位置索引。当获取一个新物品的时候,如果这个物品是不可叠加的,直接遍历数组,找一个空位置,利用这个索引和order,物品的配置id组成一个唯一的id放入即可。如果这个物品是可叠加的,需要用数组的0索引到最大索引和物品配置id一一组成唯一id查找对应的物品对象,找到之后判断是否叠加已达最大数,如果已达到,直接找个空格子放入,如果没有达到,直接更新数量,更新完数理再判断是否达到最大叠加数,如果达到了,需要把多余的再占一个格子。

在使用物品的时候,客户端传过来这个物品的唯一id,我们就能拿到它的数组索引,直接操作即可。这里还有个问题,就是在使用前可能需要判断是否足够,如果只用一个数组的话,需要遍历数组,计算这个物品的总数量。如果不想遍历的话,可以另外再加一个Hashmap,存储一个可叠加物品的总数量,即key物品配置id,value为当前这个物品的总数量。这样判断是否足够的时候就可以直接判断了。

目前最常见的就是这三种类型的游戏背包了,我在网上还看到有的设计是一个物品要占多个格子,这样的背包做的时候再考虑怎么设计吧。

在游戏背包中,还可能遇到一种情况,就是有些特殊物品,比如某个宝石,当把这个宝石镶嵌到装备上,会额外增加这个装备的属性加成。但是具体增加多少,是在获取宝石的时候,根据一定算法随机出来的,而且影响几个属性也是随机的。一般来说一旦随机之后,这些属性加成就不会再变化了,也就是说不会再更新了。那么在背包中我们就可以增加一个字段,存储这些数据,这些数据可以是一个单独的对象,然后序列化为byte[]存储到数据库的blob中,可是把这个对象转为json直接到text中。

image

这样就可以任意添加多个属性数据,而不用修改数据库各代码了。物品背包就可以统一管理 了。


      每天坚持学习1小时Go语言,大家加油,我是彬哥,下期见!如果文章中不同观点、意见请文章下留言或者关注下方订阅号反馈!


社区交流群:221273219
Golang语言社区论坛 :
www.Golang.Ltd
LollipopGo游戏服务器地址:
https://github.com/Golangltd/LollipopGo
社区视频课程课件GIT地址:
https://github.com/Golangltd/codeclass


Golang语言社区

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:Golang语言社区

查看原文:游戏服务器背包设计与实现

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1149 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传