[GEiv]第六章:粒子特效 绚丽的火焰与爆炸
第六章:粒子特效
绚丽的火焰与爆炸
本章节主要介绍粒子特效设计的方法论,其中有相当的知识量是平台无关的;在本文中会以“爆炸”这个实际的例子为线索,进行详细的设计讲解,并最终使用GEiv实现它。
[为什么要使用”粒子”]
实现粒子特效的首要目的,是对一些环境效果进行模拟仿真,常见的环境效果,例如火焰、爆炸、雨、雪、雾等,都是无数微小的粒子以某些规律共同作用的结果。而对于计算机来讲,虽然没有足够的运算能力对每一个自然粒子进行抽象,但我们可以借鉴其原理,使用相对更少的粒子对这些自然现象进行模拟和仿真,以达到近似的效果。
[需要设计哪些内容]
[粒子属性]
首先需要设计的是单个粒子的属性,这里我们以粒子个体作为考虑的焦点,考虑的内容往往是粒子的共有属性,属性的内容可以是图形样式、大小、颜色等等。
[投射规律]
投射规律考虑粒子以何种方式投射到屏幕上,这里以粒子群为考虑的焦点,考虑的内容会涉及到实际的物理规律,例如粒子在空间中的角度分布、速度分布以及颗粒大小分布等情况。
[演变规律]
演变规律是抛射后的粒子随着时间变化的规律,它同样会涉及到物理规律的模拟,只不过这次是针对单个粒子的设计,例如速度、自旋角度、颜色等属性的变化规律。
[实例-模拟爆炸]
爆炸特效在游戏中的使用相当广泛,属于经典的粒子系统。现在我们从零开始,设计一个爆炸的粒子特效。
在想要模拟爆炸前先来观察一个实际的爆炸例子:
从图片中我们能够概况一些基本的物理规律:
首先,在一个爆炸中,粒子的大小显然是不同的,而且,简单的想,粒子的大小与其质量成正比,所以粒子速度应该与其大小负相关,你可以看到颗粒状的小型碎片已经飞到了火焰之外的区域,这是动量守恒定律所确定的。
其次,在爆炸的中心,能量较高,呈现出亮白色;而在爆炸的外围,与空气接触后热量明显下降,火焰呈现出暗红色,在这个过程中,颜色也呈现出了明显的变化规律:亮白-》黄色-》红色-》暗红。
还有,速度的变化规律:在爆炸发生后,粒子的速度并不会一直不变,它还要受到空气阻力的作用,根据流体力学的相关内容,空气阻力与速度的平方成正比,与物体在运动方向的正投影面积成正比,所以其速度变化应该表现为某种受到阻尼的运动状态。
最后,在能量耗尽的暗红色区域,粒子逐渐消失,也就是说其颜色通道系数应该以某种非线性(先慢后快)的方式衰减。
[属性设计]
粒子图元:首先需要确定的问题,我们如何选择粒子的图形呢,使用点?圆形?方块?还是使用某种贴图呢……其实设计粒子的基本形态很值得一说,我们暂且使用圆形来设计,在最后您可以看到更改粒子形态对整体特效的影响。
粒子的颜色:由白到红,初始值使用白色。
粒子的大小:为了较为明确的产生大小两种粒子,我将使用一定的概率分布策略随机产生大小(详见投射设计部分)。
自旋角度:在圆周上均匀分布,由于一开始我们使用圆形作为图元,所以这个自旋这个属性不会显露出来。
通道:Alph初始值设置为1.0。
[投射设计]
产生:在我们给定爆炸点之后,假定粒子围绕着给定点进行+/-5位置浮动的随机的产生。
大小分布:以50%的概率产生6~35大小的粒子,否则产生6~24大小的粒子,这里只是一个简单方案,你也可以考虑使用高斯分布等。
速度方向分布:以产生点进行360度均匀分布。
速度大小分布:为了简化选择了恒定值,但是,空气阻力模型在演变中起到作用,故仍可观察到非常近似地模拟结果。
[演变设计]
速度衰减:
对于每一帧:v -= a*w^2*v;其中,w是粒子大小,a是衰减系数,v是当前速度,也就是说,速度进行阻尼衰减,并且大碎片的速度衰减的更快。
颜色衰减:
↑衰减时间图
↑衰减过程均匀抽样
首先,RGB中的红色分量是不变的。
假如把时间t变量规格化到0~1之间。
那么,蓝色分量应该最快衰减,因为爆炸主色调至少应该是一个暖色调。所以蓝色线使用的是t^16。
绿色分量暂时设置为伴随t的线性衰减,其实,G分量衰减速度可以依据大小而定以获得更逼真的效果。
通道衰减:
↑衰减时间图
↑衰减过程均匀抽样
通道衰减过程先慢后快,这样,在特效开始的一段时间内,我们不会感到通道的变化,直到粒子快要消亡时才会有直观的视觉感受。
[编码实现]
接下来就是编码阶段了,我们也明确的看到,其实整个粒子特效的实现过程中,设计占了相当大的比例,在最后的阶段,只不过是要我们使用擅长的平台去实现罢了,其实很多软件开发都是这样的,编码只是个实现过程,不是什么高科技。
您可以到GitHub上找到本章中的例子。这里进入
在Geiv下,我们的粒子仅需要实现Individual接口,并使用个体的集群管理器进行管理即可(参阅第五章)。
//ExpIndividual.java:
package com.geiv.test;import engineextend.crowdcontroller.Individual;
import geivcore.UESI;
import geivcore.enginedata.obj.Obj;
import java.awt.Color;
import com.thrblock.util.REPR;
import com.thrblock.util.RandomSet;public class ExpIndividual implements Individual {UESI UES;Obj disp;float sTallms = 500;//这里设置了粒子从产生到消亡的总经历时间float allms = sTallms;float Dms = 17;//这里设置了每一帧的时间,你也可以用1000/UES.getFPS这中方法在构造器里填充float V = 4.5f;//运动的初始速度被固定为4.5像素每帧float ax, ay;float vx, vy;float Theta;//自选角度,本例中暂时使用圆形,所以是看不出的public ExpIndividual(UESI UES) {this.UES = UES;disp = UES.creatObj(UESI.XRIndex);//这里把图元产生在了XR层,前面的章节中介绍了该层次混合模式的特点。disp.addGLOval("FFFFFF",0,0,12,12,12);//画一个圆形disp.setGLFill(true);disp.setColor("FFFFFF");disp.setAlph(disp.getTopDivIndex(), 1.0f);allms = sTallms;}@Overridepublic boolean isAvalible() {return !disp.isPrintable();//关于Individual请参考第五章的介绍}@Overridepublic void getUse(Object[] ARGS, float... FARGS) {int Rad;//我们使用一定的分布方法产生Rad大小,RandomSet是内置的随机数发生器,其静态方法名称都比较好理解,就不在这里细细讲解了。if (RandomSet.getRate(50)) {//以50%的概率返回布尔值trueRad = RandomSet.getRandomNum(6, 35);//返回6~35随机数,均匀分布。} else {Rad = RandomSet.getRandomNum(6, 24);}disp.setWidth(Rad);disp.setHeight(Rad);//初始位置具有+/-5的浮动区域disp.setCentralX(FARGS[0] + RandomSet.getRandomNum(-5, 5));disp.setCentralY(FARGS[1] + RandomSet.getRandomNum(-5, 5));//初始自选角度,0~360均匀分布。disp.setAngle(RandomSet.getRandomFloatIn_1() * 360);//速度角,0~2PI均匀分布,使用弧度是为了方便调用Math下的三角函数。Theta = (float) Math.PI * 2 * RandomSet.getRandomFloatIn_1();vx = V * (float) Math.sin(Theta);//计算横纵向速度vy = -V * (float) Math.cos(Theta);ax = -0.0003f * (disp.getWidth() * disp.getWidth()) * vx;//计算加速度ay = -0.0003f * (disp.getHeight() * disp.getHeight()) * vy;disp.show();//显示到屏幕上(投射完成)}@Overridepublic void doStp(int clock) {if (this.allms > Dms) {allms -= Dms;//allms记录当前剩余存活期,使用这个变量是为了将存活期规格化到0~1之间。//REPR是内置的变换工具,可以将一个规格化后的线性量转化为自定义的常用非线性量//颜色变化disp.setColor(new Color(1.0f, REPR.Rep_POW_1_F(allms / sTallms, disp.getWidth() / 24), REPR.Rep_POW_F(allms / sTallms, 16)));//通道变化disp.setAlph(REPR.Rep_POW_1_F(allms / sTallms, disp.getWidth() / 12));//运算加速度ax = -0.0003f * (disp.getWidth() * disp.getWidth()) * vx;ay = -0.0003f * (disp.getHeight() * disp.getHeight()) * vy;//运算速度vx += ax;vy += ay;//运算位置disp.setDx(disp.getDx() + vx);disp.setDy(disp.getDy() + vy);} else {//生命周期结束后,将粒子资源回收finish(Individual.SRC_INNER);}}@Overridepublic void finish(int src) {disp.hide();//重置颜色与通道disp.setColor("FFFFFF");disp.setAlph(disp.getTopDivIndex(), 1.0f);//重置大小disp.setWidth(12);disp.setHeight(12);//重置存活时间。allms = sTallms;}@Overridepublic void destroy() {disp.destroy();}
}
//Explosion.java:
package com.geiv.test;import engineextend.crowdcontroller.CrowdController;
import geivcore.UESI;public class Explosion{UESI UES;CrowdController cc;public Explosion(UESI UES){this.UES = UES;cc = new CrowdController(UES, true);for(int i = 0;i < 512;i++)//装入了512个粒子资源{cc.addIndividual(new ExpIndividual(UES));}}public void doEffect(float dx,float dy) {for(int i = 0;i < 128;i++)//当每次调用时,分配128个粒子资源,同时也意味着,您可以同时在屏幕上产生4个异步的爆炸特效。{cc.getAvailible().getUse(null,dx,dy);}}public void forceClose() {cc.finishAllInd();}
}
//Main.java:
package com.geiv.test;import geivcore.R;
import geivcore.UESI;public class Main{public static void main(String[] args) {UESI UES = new R();Explosion exp = new Explosion(UES);for(;;){exp.doEffect(400,300); //产生一个爆炸UES.wait(3,1000); //延时1秒}}
}
执行效果:
[粒子特效的改进]
“一堆圆形一点儿也不像嘛”这是我同学看到程序后的第一句评价,的确,从粒子的行为模式上来讲,是有类似爆炸的性质了,不过一个爆炸也不能只让圆形组成不是吗?
↑给一个大点的图,可以更突出的发现这个问题
在属性设计时,我提到了关于粒子图元选择的问题,对于爆炸这个特效,显然均匀的圆形(或者其他图形)不是一种好的图元构成,我们需要一个形状并不均匀,甚至伴有随机性的图形来替换这个圆,于是笔者想到了“云”这个东西。
↑由于云是白色的,所以为了展示,把PS的衬底一起截下来了。
云本来是与爆炸毫不相干的东西,选择它是由它的图形性质决定的:边缘渐变、具有随机性、在颜色通道上也不均匀。而且,加上我们之前定义的自旋随机分布,加入自旋角的云看起来和彼此具有更大的差异。
为了使用云这个素材,先把它放在项目目录里:
之后找到ExpIndividual类,找到它的图元绘制部分:
我们把
disp.addGLOval("FFFFFF",0,0,12,12,12);
disp.setGLFill(true);
这两行改为:
disp.addGLImage(0, 0, 12, 12,".\\Effect\\PT_CLOUD1_POINT.png");
经过改进的特效:
↑可以跟圆形做一下对比,是不是好多了呢
[总结]
本章介绍了粒子特效设计的基本步骤,即属性、投射、演化三部分。
粒子特效是对自然的模拟,因此在设计时要充分地考虑到物理因素,这样会得到更好的仿真结果。
最后,恰当地选择粒子图元可以得到更好的结果,而粒子图元的选择与图形的性质有关。
[GEiv]第六章:粒子特效 绚丽的火焰与爆炸相关推荐
- 游戏感:虚拟感觉的游戏设计师指南——第十六章 Raptor Safari
这是一本游戏设计方面的好书 转自天:天之虹的博客:http://blog.sina.com.cn/jackiechueng 感谢天之虹的无私奉献 Word版可到本人的资源中下载 第十六章 Raptor ...
- Silverlight 解谜游戏 之四 粒子特效
前几篇一直在Blend中工作没体现出开发者的作用,本篇将为订书器(Stapler)添加自定义粒子效果,当订书器被点击时产生更好的视觉效果.其中将使用到nerdplusart 的Silverlight ...
- vue 3 + mo.js 实现点赞粒子特效【实战】
ue 3.2 + js 实现点赞粒子特效 创建一个项目 一.显示页面 1.新建页面 2.写部分显示代码 3.导入文件 4.将其他的注释掉 二.下载点赞图片 1.打开阿里云矢量库 2.复制SVG代码 3 ...
- 第六章 电磁新理论(修补章)
第六章 电磁新理论(修补章) 关于麦克斯韦方程中的散度式的证明,网上资料很多,也较为简单.所以,本章只是对麦克斯韦方程中的旋度式做逻辑推导, ...
- 大学物理第六章 静电场详解(全)
电场 电场强度 一.电荷 电荷的概念是从物体带电的现象中产生的,电荷是物体状态的一种属性,宏观物体或微观粒子处于带电状态就说它们带有电荷 物体或微观粒子所带的电荷有两种,称为正电荷和负电荷,带同种电荷 ...
- 第六章:演示文稿软件PowerPoint 2010 ——知识点整理
第六章:演示文稿软件PowerPoint 2010 --知识点整理 第六章:演示文稿软件PowerPoint 2010 知识梳理 高频考点 6.1 PowerPoint 2010 基本知识 6.1.1 ...
- unity2d粒子特效
文章目录 前言 先看效果 一.2d平台雨 1. 配置 2. 图片素材 3. 最终效果 二.脚步灰尘效果 1. 配置 2. 代码调用 3. 效果 三.受伤血液四溅效果 1. 配置 2. 效果 待续 四. ...
- 计算化学系列教程-第六章-氢原子(1)
计算化学-第六章-氢原子 6.1 中心力 https://v.qq.com/x/page/g31501593ii.html 6.2 不相互作用的粒子与分离变量法 https://v.qq.com/x/ ...
- Unity_粒子特效_序列帧
由上一篇中不难看出,简单的粒子特效就是对产生的粒子进行材质的更换以及颜色的间断变化,由此我们可以发挥想象如果对材质进行规律替换是否可以实现更绚丽的粒子特效呢? 先展示特效效果: 配置信息以及序列动画材 ...
最新文章
- linux 内网共享文件夹_在Linux下访问Windows共享文件夹
- webgl(three.js)实现室内定位,楼宇bim、实时定位三维可视化解决方案——第五课
- LeetCode 456 132 Pattern
- [云炬创业基础笔记] 第四章测试15
- Spring什么是复杂对象
- SpringBoot 配置环境属性
- python 下的数据结构与算法---6:6大排序算法
- 移动后端支持平台Parse将API由Ruby迁移到Go
- linux下的各个语言中stdin,stdout和stderr理解
- 在Win7旗舰版安装并运行LoadRunner11
- wpf之MVVM绑定背景色
- 1085 Perfect Sequence(25 分)
- 收藏 | 数据资源下载网址大全
- java 什么是过滤器_java中的过滤器是什么
- 【BZOJ1778】[Usaco2010 Hol]Dotp 驱逐猪猡
- 逆向学习路线(推荐书籍)
- 探索、松散结构,和大家谈谈关于社区的思考|shadow与mixlab的故事
- 西北师大与新华三开展物联网战略合作,共建“物联网联合实验室”
- 贪心算法-加勒比海盗船——最优装载问题
- 揭开自然拼读法(Phonics)的神秘面纱
热门文章
- pyqt 使用问题总结
- javascript脚本_JavaScript Shell脚本
- Yii2 Using pretty URLs (Yii2 中使用漂亮的urls) from ----- Yii2 By Example
- ps入门第9天_ps色阶ps曲线 案例:ps照片校正
- Matplotlib可视化练习
- 【BZOJ4755】 [Jsoi2016]扭动的回文串
- 贴几张Google Earth的图
- 如何近似计算回归方程的预测区间?
- 劳伦杰克逊写给姚明的情书:你的名字
- 国外大神数据,全球主板厂商信息汇总,A B X系在主板汇总