在经历了17年诸般变动后,现在到了2018年。怀旧是因为之前几年发生太多,好与不好都已过去,17年迎来新的开始,所以也就有了后来些许感慨,有机会再说说这些行业感受了。今天先让我们专注于川最新解决的实际项目问题。
战争迷雾是很多带地图的游戏多少会考虑的一个功能。恰巧川在17年下半年开始做的项目也涉及到了这次的内容,而且在开始审题时,这简直是送分题啊!我们先来看看题。
“今有2D地图一张,需制作战争迷雾,地图随角色坐标与视野范围开迷雾,且被开的迷雾常亮。求实现功能。”
前人的实现:
在正式解决题目之前,这项内容本是组内一名同事先期在做的。他的思路通过动态修改迷雾图的alpha值,达到迷雾被打开的效果。具体流程可以概括为:
创建mask图->存储地图alpha数据到数组->遍历更新更新被开视野的数组数据->逐像素遍历更新mask图像素点的alpha值->刷新图片并应用
其实这就是为了实现功能而写的一段代码,实现了我们的命题,但是在扩展性以及性能方面没有丝毫值得借鉴的地方。倒是表现效果起码能让人在看过之后知道是怎么回事。
重新设计:
好吧,所谓前人的实现其实就是吐个槽,现在让我们开始改进。我们先借鉴利用二维数组存储地图数据的做法,根据地图尺寸创建一个m*n的数组,每个数据表示1平方米范围的迷雾alpha值。根据我们的测试,居然需要消耗10-30ms!这在游戏上是绝对无法容忍的。因此就需要围绕节省运算力着手。
根据编程经验,首先出问题的肯定是那个“遍历更新更新被开视野的数组数据”和“逐像素遍历更新mask图像素点的alpha值”,因为单单一步就需要遍历m*n次。假如地图是一个1000*1000的,那么每一帧就要遍历两百万次,太恐怖了!所以,根据题目的要求,我们完全可以只更新每一帧需要更新的区域,也就是角色视野范围大小的数据就可以。为此我们需要拥有一个Dictionary,专门存储不同视野值的视野范围数组,用于更新存储地图数据的二维数组。
在进行了上一步的优化之后,如果视野值为v,则我们每一帧只需要进行两次v*v的遍历就可以更新地图数据,并把更新后的数据写入到mask图中。这样我们的每一帧消耗的时间就已经控制在2-4ms。然后为了节约数据的存储空间,我们可以设置最大边长,然后等比换算,使这部分的存储不大量占用内存,唯一的缺陷就是当地图变大的时候,迷雾的分辨率会降低,不过目前来看已经解决问题了,不是吗?