背包以及装备模块封装的思考

由于最近项目原因,负责了背包模块兼顾装备模块。起初由于装备和道具要分别进行管理,并且装备存在随机属性的问题,最直接的思考就是生成物品UID的方式来进行区分,并且通过UID来作为map的主键来进行存储。现在仔细思考下来,其实不用map,改用vector数组来存储会更好一些。UID只需要作为装备的唯一标示信息就可以了,用位置信息来作为唯一性的操作定位。可能说起来有点空白。看下图,原来是这么设计的:

EquipManager和ItemManager分别管理了道具和装备的内存信息以及具体的操作,并且PackageManager来做位置信息的生成,UID生成排序等工作并不包含内存信息的副本还是借助于EquipManager和ItemManager来操作。初看下来也没有什么大问题,加上由于策划将装备,道具分成了两个表并且提出了一个通用的基类给PackageManager提供了公共的函数接口,存储的数据结构采用map方式,为了操作方便用UID来做主键,取操作同样也会很便捷,并且也可以装上的装备位置信息为0,这样内存信息还是保持在EquipManager方便了内存的管理。

但是面对了几个问题。

1.背包的排序问题,由于map本身并没有排序的性质,不能说不能排只是没数组方便,所以还是在排序的时候,暂时放入了一个数组当中

2.放入一个背包物品的时候,位置信息生成,UID的时候PackageManager来管理,但是UID的生成还好理解,位置信息的生成就感觉很不自然

3.PackageManager其实具有了ItemManager以及EquipManager的一些特征了,只是采用了调用的方式进行了操作。

反思:

1.为了保证服务器类层级设计的扁平化和模块的独立性上,PackageObj反而使得继承树复杂化了,不是一个很好的代码范例结构。应当让Item和Equip各自持有各自的背包信息数据,做到和数据库策划表的一一对应。这样的策划的更改或者数据库的更改优化,留有的更改余地更大,不会存在嵌套的问题。

2.PackageManager具有了ItemManager和EquipManager这两者的所有特征,只是逻辑层面上的理解进行了划分将函数分离了出来。所以PackageManager应该是ItemManager和EquipManager的友元函数声明,反而比在PackageManager持有一份两个对象指针效率更高也更加的优化。

3.采用的数据结构而言,采用map显然得不偿失。对单个玩家而言背包的位置信息就具有了唯一性,然而UID的唯一性是在同种装备不同属性的逻辑区分,为其他地方的取操作提供便利。装备在装上卸下的时候,玩家身上的那个已装备格子的数组应该保持该装备的所有信息,在装备当中添加相应的字段做数据库存储,背包数组就不再保持这个已经不在背包里的装备数据了。这么做有以下几个优势

(1),使用数组排序比用map排序效率更高,更方便

(2),在选择角色界面,不需要分开查找数据库,那个时候可以保证数据库查询的步调统一,而不需要得先查询所有的装备信息做取操作或者做一个单独查询的操作。

(3),数组容量直接反应背包大小,不需要循环遍历map来做统计

(4),存储方式天然带位置信息,不需要额外算法的生成,空位也更容易找出

(5),在做道具叠加问题涉及到的背包容量问题时,背包容量问题以及空位问题更容易获取,减少了一些不必要的代码

需要注意的几点

(1),数组的越界检查

(2),背包里面的数组以及玩家身上的装备栏数组的对象释放

(3),位置是否重复的排查

思考:

1.应当对应策划表的形式,并给出程序上建议。保证策划填表的阅读性的基础上,程序在抽象上尽量做到对应,并且直接关系到数据库的列设计

2.注意类设计的扁平化,尽量少的继承,防止后续代码维护的不方便,出现“头重脚轻”的问题

3.存储内存的数据结构,不一定万事而皆准的采用“通用”的结构,而是应当根据实际情况进行调整,从而能够高效的反映到算法层面优化上来。

4.数据库设计尽量仔细考虑一下反范式的设计方式,游戏数据库而言主要做的还是登陆时候的查询,在游戏过程当中的更新,删除,插入。然而游戏过程当中查询很少,登陆查询在多分表的情况下反而防止了一个表过大的情况,插入,更新,删除等由于数据库表设计的反范式更加的方便操作了。但是列明显还是增加的,但是对于单表查询而言比起一个表的行数几何级递增的情况下,反范式设计的,通过逻辑上的区分纵向分表不见得不是一种优势,这样的设计也变相说明了Key-value数据库在游戏数据库上级当中的设计方式!

时间: 2025-01-09 11:08:53

背包以及装备模块封装的思考的相关文章

简易的highcharts公共绘图模块封装--基于.net mvc

运行效果: 之所以选择这个图表插件,是因为它较其他同类插件轻量且中文文档详细完整,Demo丰富,配置使用简单.具体内容请登录中文官网:http://www.hcharts.cn/ 项目详细: 项目环境:win10+visual studio 2015 +.net framework 4.5 后台技术:.net mvc + c# 前端技术:Matrixadmin(国外的一款基于bootstrap的后台模板框架)+jquery+highcharts 代码实现: 设定系统目前支持的图表类型:EnumC

Node.js模块封装及使用

Node.js中也有一些功能的封装,类似C#的类库,封装成模块这样方便使用,安装之后用require()就能引入调用. 一.Node.js模块封装 1.创建一个名为censorify的文件夹 2.在censorify下创建3个文件censortext.js.package.json.README.md文件 1).在censortext.js下输入一个过滤特定单词并用星号代替的函数. var censoredWorlds=["sad","bad","mad&

一种控制智能卡模块封装尺寸的UV封装设备

本实用新型公开了一种控制智能卡模块封装尺寸的UV封装设备,包括工作台和安装在所述工作台上方的滴胶装置和UV固化炉,所述UV固化炉位于所述滴胶装置的右边,所述UV封装设备还包括低温装置,所述低温装置设置在所述滴胶装置和UV固化炉之间,且靠近所述滴胶装置,所述低温装置为朝向下端开口的中空箱体,所述低温装置的左侧面的底部和右侧面的底部各设一缺口,所述低温装置的下端扣合在所述工作台上,所述低温装置的后端通过第一支架与所述工作台连接.本实用新型的控制智能卡模块封装尺寸的UV封装设备,利用UV胶的黏度随温度

React-Native开发之原生模块封装(Android)升级版

 本文主题:如何实现原生代码的复用,即如何将原生模块封装. 有时候我们的应用需要进行访问原生平台系统的API接口,但是React Native可能还没有封装相应功能组件.还有可能我们需要 去复用一些原生java代码而不是让JavaScript重新去实现一遍.或者我们可能需要些一些更加高级的功能代码,所线程相关的.例如: 图片处理,数据库以及一些高级功能扩展之类的. React Native平台的开发其实本身也是可以让你写纯原生代码并且还可以让你访问原生平台的功能.这是一个比较高级的功能不 过官方

适用于带fifo接口的存储器和显示器测试模块封装 挑战cb

cb说完美是没有极限的,对此我表示赞同,自从用了cb的板子,玩开cmos,fpga,sdram,vga等. 不断涌现的是,双端口sdram,四端口sdram,各式各样的封装,但是大同小异,但总是有些不同,对于初学的我,感觉还是挺费事,玩转各种例程发现,cb的sdram驱动程序很强大但并不完美,其中对sdram有挑选作用,如hy57v641620ftp-7很ok的使用,换成hy57v641620ftp-6就有问题,但是使用其他版本程序测试,这两个ic均ok. 这个问题一度困扰过cb良久,最终cb偶

【p2】·python中嵌套列表list元素输出·模块封装·发布上传(pigeon详细说)

如果你也正在学习<Head First Python>,可以相互学习.接下来将记录如何完成书本的这一章以及遇到的问题如何解决. 一.简单访问列表数据 [1]通过位置访问具体数据,0表示第一位[如下图] [2]计算列表长度[使用len] [3]列表末尾增加--删除元素,append增肌,pop删除,注意不同用法 append括号里放想添加元素,列表.pop()就能删除 [4]extend添加多个元素[如想在后面添加5,6,7],留意跟append区别 append保留着数据项中括号,缺陷 ---

Vivado将模块封装为IP的方法(网表文件)【转】

. https://blog.csdn.net/u011435907/article/details/78233375 在给别人用自己的工程时可以封装IP,Vivado用封装IP的工具,可以得到像xilinx的ip一样的可以配置参数的IP核,但是用其他工程调用后发现还是能看到源文件,如何将工程源文件加密,暂时没有找到方法,如果知道还请赐教.而直接用.edif网表文件作为ip的方法如下: 1.建立工程设置顶层模块 将需要封装的模块设置为顶层模块.(shift_bus模块) 2.综合待封装模块 vi

python--MyRequest请求模块封装

MyRequest import requests import nnlog class MyRequest: log_file_name = 'MyRequest.log' #日志文件名 time_out = 10 #请求超时时间 def __init__(self,url,data=None,headers=None,file=None): self.url = url self.data = data self.headers = headers self.files = file def

request模块封装

import requests import hashlib import time import os import json class requestsTools: def __init__(self, basePath): self._basePath = basePath self._headers = {} self._cookies = {} self._file_suffix = '.html' @property def basePath(self): return self.