一、前言
此博客由一个新手游戏程序编写,没有高深的技术,基本是天气效果表现和代码设计的浅谈,如果有更好的实现方法,欢迎指正。
二、背景
该系统设计背景:2D游戏、正交45度表现地图、以及同一张地图上存在不同气候的区域/地形,需要体现不同天气效果以及不同天气的切换
类似游戏:三国群英传(地图相似)、塞尔达传说-众神的三角力量(天气表现相似)、口袋妖怪绿宝石(天气表现相似)
三、全局计算和局部表现
额外系统:区域划分系统
根据地图的设计,各个理论上会出现不同气候的地形均放在一张地图里面,因此在游戏中就需要有一个类似“气象台”的系统来控制不同区域的天气,然后根据玩家所在区域去“表现”当前区域的天气,该设计的目的就是为了节省cpu和内存。
众所周知,天气的表现是会有不小的消耗的(2d游戏中,大量的雨滴粒子以及地面滴水表现;3d游戏中则是画面的渲染),直接全场景添加天气的效果明显不现实,所以采用全局计算天气的状态,再根据位置表现天气的方式去实现该系统
1、全局计算
“气象台”的实现需要引入另外一个系统:区域划分系统。该系统系统主要的作用有两点:1)根据玩家的位置得出当前所在区域。2)根据时间变化实施计算各个天气的状态
第一点的实现,在此不展开讲,区域划分的方式因人而异,博主采用的方式就是把区域看成一个多边形去做,如果使用这种方法的话,区域判定提供两种方式:
1)一定时间判断点与多边形的包含关系。
这个可以去搜索“判断点是否在多边形内部”,然后定时去计算。
参考:https://www.jianshu.com/p/ba03c600a557
优点:空间上的精准;实现方式清晰,复杂度可以自己控制。缺点:频繁调用,时间上不够精准。
2)物理框碰撞。
这个方法是博主朋友提议的,并未实现。也是把区域看成一个多边形,不过这个多边形是一个物理框,玩家(也需要有物理框)进入和离开区域的时候去调用其碰撞函数,再去判定位置
优点:时间上的精准;方法不用自己实现。缺点:空间上的准确度有待商榷;需要进一步优化需要学习底层代码。
天气状态也是因人而异,不过最重要的就是“天气”和“天数”了。
2、局部表现
不管用什么方式得到当前区域的天气之后,就需要去表现天气。表现的方式就是在摄像机上,把粒子和效果添加到相机节点上(或者根据相机位置添加到地图上),具体的表现和实现在下一节讲述。
四、天气表现效果
天气系统的运作方式决定了之后,就是去设计天气的表现效果了。
博主设计的天气目前有四种:小雨、烈日、沙暴和暴雨
1、小雨和暴雨
效果参考:
该天气推荐使用cocos2d的粒子编辑器(Particle Builder)做。粒子编辑器可以用一张图片表现各种效果,如下面两张图,只需要调节参数就可以做出下雨特效
下雨的时候可以在相机上再添加一个图片精灵(或者着色精灵)去实现变暗效果,通过修改颜色和透明度起到天变暗的效果,在暴雨天下,设置可以在几帧内瞬间改变亮度和颜色,起到打雷的表现效果
根据我的理解,粒子编辑器只能针对一张图片做特效,而地面滴水需要一个动画表示,所以需要创建精灵节点去播放动画,实现方式下文再讲。下图是植物大战僵尸滴水特效:
滴水精灵节点需要添加在地图节点上,如果添加在相机节点上的话,那么如果相机跟随人物移动的话,滴水还没消失就会移动会看上去很别扭。
滴水效果添加是很有必要的,博主表达能力不强,所以只能用“感觉上没滴水的雨很别扭”这句话去形容。
最终效果:
2、沙暴
看到图应该就能理解了,目前实现方式为一张图片循环移动。
3、烈日
烈日实现的效果目前参考口袋妖怪绿宝石的烈日的效果,在之前下雨的着色精灵把透明度调高,改变颜色实现(和雨天的闪电闪屏效果类似),不过效果并不是很好……
五、技术点(代码和数值设计的原因)
1、所有天气精灵独立
各个表现天气的精灵都需要独立,目的是防止在“切换”表现天气时出现冲突。人物从一个区域走到另外一个区域的时候,天气系统需要做的事是:原区域天气逐渐消失,现区域天气逐渐出现,如果所有精灵(或者个别精灵)共用一个节点的话,那么“新”的天气精灵会覆盖之前的天气精灵,导致原区域天气瞬间消失。
def __init__(self):# 雨天精灵self.RainSprite = None# 沙暴精灵self.SandStormSprite = None# 暴雨精灵self.RainStormSprite = None
2、区域划分的时候需要有过渡区
说简单一点就是划分区域的时候,把边缘部分再划分一个区域。其目的是防止不同区域刷出完全对立的天气导致的不合理,比如说沙漠目前处于烈日状态,而沙漠外的草原在下暴雨,如果没有做过渡区,会出现“烈日渐渐消失,暴雨渐渐出现”的天气切换效果,虽然是渐变效果,但还是出现了烈日和暴雨同时出现的画面,非常不合理。
3、滴水效果实现方法
前文讲了,滴水效果是动画效果,不能用粒子编辑器来做。所以博主的实现方式是:在初始化天气的时候,直接创建一堆精灵(比如暴雨天,地面上需要有300个滴水效果),每帧(时间间隔可以改)去播放动画,在播放动画之前把精灵移动到摄像机视野范围内。当前区域天气的表现结束的时候,也不要销毁精灵, 而是继续保留,其目的是防止频繁的创建精灵导致的消耗,水滴精灵的内存占用和地图相比,通常只占了很小一部分,权衡之下,可以用空间去换时间。
六、后记
因为博主个人原因,代码不愿意公开,所以本篇博文不过是个技术总结罢了。
总而言之,天气系统在游戏中不是一个很难实现的系统,不过在实际编写代码的过程中还是会遇到很多问题。
天气系统的主要难点只有两个,一是各种渐变效果,二是天气的表现效果,没有很硬核的技术。
最后感谢您看到这里,如果有好的想法和建议,欢迎留言~