先给大家一些不爱看的东西:
以上全部内容出现在同一个类里面
部分类似的方法我没有全部放出来,如果放出来了,大家的眼睛应该会更痛苦。
有的时候我的阅读速度过快,以至于我的大脑知道我读了什么的时候已经来不及了.jpg
这个类,应该不需要我多说什么,但凡做代码的应该都看不下去了。
其实对于我而言,还好。
毕竟我只需要调用方法就好了,至于问题,等什么时候程序跑不动了再说。
现在,问题出现了,程序跑不动了。
其实也并不是跑不动了,而是这个抽象的类(并非抽象类,我可没加关键字),非常不方便进行修改。
这个类读取的数据是很多的,毕竟它是完全地对本地JSON文件进行序列化和反序列化的一个类,字典里保存的也是一个反序列化后的object,但是问题就出在这里。
字典里保存的是个object,是个弱类型(AI说的),虽然我搞不清楚什么是弱类型,但是当我尝试给一坨东西加些方法的时候,然后,就红了
而且,这个类跟背包相关得非常紧,再就是跟整体的保存逻辑(游戏进程的保存)之间有着非常大的关系。
在此之前,背包也是一个字典,是一个更加抽象的字典,这个字典存在于一个专门的背包类里,这个背包类是一个实例类,是一个在构造函数里接受一个字符串(通常是地址或者背包名称),然后在本地文件内生成一个背包(如果没有),或者打开一个本地背包,后,才能加载一个存储物品名称和数量的字典(谁知道我当时怎么想的)。
至于背包里物品的其他信息?没关系,调用物品类获取它吧。
这就很抽象了,首先,这些分散的背包作为游戏中数据的一环,在进行游戏进程保存的时候肯定是需要保存下来的,但是这些背包又都是分散的(甚至有一个专门的空背包,用于处理构造函数无参数的情况),也就是说,想要保存,就必须先进行遍历,但又不是每一个背包都需要进行保存(毕竟全局仓库也可以视作一种背包,而它会自动保存),总之就是小脑踹大脑,有些勃勃生机,万物竞发了。
而想要保存逻辑正常,首先背包的存储得正常,背包想要正常一点,这个狗日的物品就要正常一点,那就从物品开始改!
在暑假期间,我完成了对于人物数据的管理方法的封装和统一实现。
这是全部的类文件
大致上可以这么说,每个类管理一部分数据,这些静态类一般不加载,这些类管理的数据都是构成“人物”这个巨大数据所必须的,每个不同数据提供了单独的保存和加载逻辑,同时还提供了初始化,修改,删除,对于法术还专门设计了施法的逻辑,之后,再到PlayerClass这个总管理里调用这些方法,其余的程序和代码只需要调用PlayerClass内部的方法即可,无需进一步调用被封装好的的各个数据管理类内部的方法。
在具体实现中,PlayerClass类里存储了一个巨大的“人物”数据字典,这使得可以只对这个字典进行访问就能得到我们想要的数据,但是设计到修改或者创建等逻辑,必须遵循以下逻辑。
修改/创建指令->数据管理类执行方法,对数据进行修改后保存->数据管理类返回修改后的数据到总管理类->总管理类修改自身的数据并保存
按照这个思路,我首先将一串结构体从ThingsClass内扯出来,扔到了全局域当中。
这里在AI的指导下将所有的数据结构换成了类,便于继承
之后,在这个基础抽象类的基础上,创建了若干子类,并设置了它们的克隆方法
这些是全局物品类们,其实按照之前的逻辑到这里已经高枕无忧了。
这个时候,我的一个朋友(暑假期间一直在跟我学C#)提出了一个疑问,如果我们手上有一把名叫“圣剑”的铁剑,但是其属性还真就是铁剑,那么该怎么去生成呢?
我已经设置了Text属性,可以支持这样的操作,但是没有这样的方法罢了,其实也好办,毕竟这些东西已经成为了一个类,类可以生成实例,无非只是生成一个特殊的实例罢了。
问题出在下一个地方,也就是背包逻辑上面。
按照AI的说法,继承于某一个基类的子类,可以在字典存储的时候使用基类来作为键(大致就是这么个意思),但是,我们并不能直接让这个背包字典存储Items(上图中的物品基类)。
首先,字典是一个哈希表,其次,字典是一个哈希表,对于两个基本类似的物品来说(例如一把铁剑和一把伪装成“圣剑”的铁剑),在我们看来它们是一样的,但是它们不一样,至少在哈希函数看来这两个东西就不一样,所以,它们两个不能堆叠。
其实不能堆叠还是小事,毕竟有的时候可能真的不需要堆叠,比如任务物品和非任务物品,一把非任务物品的铁剑自然不能跟任务物品短剑堆叠在一起。
而且,对于这些用来存储物品的抽象类和子类而言让它们提供一个生成实例的方法会使代码重现变回上面的那种莫名其妙的状态(其实最主要的原因是背包大改了,而且是一种奇怪的方式改变了)。
一切始于一个下午,我询问了AI如何才能做到以下的事情:
创建物品,然后在我需要的时候生成这些物品的实例。
是的,实例,在进行保存或者说本地化的物品里有一个属性是不需要的。
Text,Text只会在物品实例诞生后出现,在物品实例诞生前完全不需要,甚至都可以不设置,或者干脆为null。
保存时不需要这个Text属性,在未实例化前这个Text也不需要,需要这个Text的时候,是对物品进行实例化的时候。
于是AI向我提议:设置物品模板。
设置物品模板,为了迎合我的需求,最终选择了设置两种不同的模板。
一种模板叫做物品配置模板。
配置模板内对于Text这个不需要的属性留空,只参与保存
另一个模板是物品运行模板:
物品运行模板提供一个抽象方法创建实例
同时,我设置了两者间的转换方法:
通过这两个方法,实现两种模板之间的转换。
接下来就是神奇而且逻辑清晰,令大家感到舒服的部分了
在运行时,遵循以下逻辑:
从本地JSON文件内读取数据
这是读取逻辑的其中一部分
这一步,读取JSON文件内的数据,并原封不动地注入一个字典,然后返回这个字典给之后的逻辑
对读取数据进行处理
第一个方法我们之后会提到
这一步将获取的JSON反序列化的结果转换成配置模板,然后,立刻将配置模板转换成运行模板,之后,立刻注册模板。
注册模板
这一步,使用图中的注册方法将运行模板注册到运行模板库(字典)内,同时,严格设置模板的ID号(根据上述图中的特殊枚举属性TypeItem来完成了保证物品的ID为xxxxx形式,每两种相邻物品类型之间的ID序号差为10000)。
到这一步,加载逻辑已经做完了,之后使用以下逻辑进行获取数据:
有时需要获取模板(多为生成某些物品,例如宝箱的初始化),有时需要获取全部的运行模板(例如开发者状态下查看物品库),总之,之后只需要获取所需的数据,再对数据进行处理,就能获得通用数据(名称,类别,价值,重量,描述),而大部分情况只需要这样数据即可(这里的情况主要指商店或者背包,你只需要知道某类东西的重量价值和描述即可)。
之后,在另一个类(背包类)里提供了专门的实例化方法,可以根据获得的模板不同实例化不同的数据。(多嘴提一句,这里的实例化如上图所示,一般都是接受一个Text=null,如果有,则实例化为Text=给定参数的实例,如果为null,则给出Text=Name的实例)
说回正题。
在完成了上述的一大堆操作后,物品模板的加载完成了,接下来就是使用,而在使用的过程中,很有可能生成一些新的模板:
这些正是之前的方法,经过修改后,用于创建模板而不是实例
这些模板仍旧需要保存,而进行保存也是一个相当麻烦的事情。
首先,这一步,我们的字典内存储的是物品的运行模板,运行模板不能直接保存,因为它不是配置模板(哪怕两者内的数据一模一样),我们需要将其进行转换,转换成配置模板再进行保存。
于是便有了这个非常麻烦的转换方法
然后便是保存方法啦
这里的保存方法本来不是这样的,是根据实际使用而专门进行微调了的。
原本长这样
原本的保存方法可以很好的进行JSON序列化,但是对于这些模板,不能直接这样做。
因为模板有很多种,它们在进行存储的时候都是以“物品运行模板”也就是基类来进行存储的,在保存的时候,也会保存下基类的通用数据,最终导致数据丢失。
每一个复杂而带着许多注释和try代码的背后,都是一次次的抓耳挠腮
这一步,也是最关键的一部。
保存模板到本地JSON文件并覆盖
有了保存,有了加载,之后只需要进行适当扩展即可。
但是到这一步,我不满意。
首先,配置模板毕竟是个模板,毕竟它是专程从本地JSON文件里读出来的,随着本地文件越来越多,那么这个读取的过程将会越来越慢。
主要问题出在加载步骤上:
现在的加载步骤按照这样的逻辑:读取本地JSON文件->转换为配置模板->配置模板注册
10个模板就需要转换10次和注册10次,100个模板就要转换100次和注册100次,非常消耗性能。
所以,我们为什么不能直接填充字典而不去干这么长的一趟工呢?(不是硬编码,我没那么闲)
于是这儿多了两个方法:
一个新的保存和加载方法!
一个特殊的,本质上也是一个JSON序列化和反序列化的方法,但是,这个方法,直接对字典进行操作,而不通过配置模板和注册方法。
这个东西便是缓存,它保存下一次运行后的字典内部数据,并且在下一次运行的时候,优先使用缓存内部数据(运行模板)直接对字典进行加载,这就省去了很多步骤,大幅加快了大量模板下的启动速度。
这个方法在哪儿调用呢?
在这里
有人应该已经发现了,在Load方法里尝试了对两个文件(缓存文件和JSON配置文件)进行比较时间,而在方法Initialize里,总是先加载缓存,发现没有缓存,或者缓存比JSON配置文件老(可以理解为有新的模板被添加了),则读取JSON配置文件,在注册运行模板完毕后,保存运行模板到缓存里,之后,只要没有添加新的模板,缓存永远比配置文件新,读取缓存。
结果:
到这里,一个舒舒服服的物品管理类算是做完了,别的不说,下辈子不会动了,而且改起来非常简单,只需要修改克隆方法,修改一下模板间的转换方法和模板数据即可。
其实到这里还是存在一些瑕疵的,但是人已经累了,要专心去做战斗系统了,如果各位大佬有什么好的建议,可以跟我说。
感谢各位的阅读
更多游戏资讯请关注:电玩帮游戏资讯专区
电玩帮图文攻略 www.vgover.com