引言
前不久热剧《权利的游戏》在万众期待中大结局了,很多人对它的大结局不满意,甚至网上有人联名请愿重拍大结局。但不论如何,这陪伴我们8年的美剧终究还是完结了。
纪念人和事的方式有很多种:文字、音乐、光和影,而代码也是其中一种。所以,我们可以通过写代码去和这部我们追了多年的剧说再见。
大家应该都知道该剧改编自美国作家乔治·R·R·马丁的奇幻小说《冰与火之歌》系列。正巧大佬Jason Labbe写了一个和“冰与火”相关的作品,效果如下。
看完大家可能会觉得,你这不是骗我吗?这明明只有火,哪来的冰呀。确实,这个作品的名字就Fire Brush,和冰毫无关系。但是,大家请稍安勿躁,我在这个作品的基础上做了一点点修改,完成了Ice and Fire。效果如下,这样就是名副其实的冰与火之歌了!
Fire Brush这个作品是用P5.js写的,用粒子系统去模拟了火焰和烟雾的效果。同时作品里面有很多小技巧值得我们去学习。接下来我就给大家介绍一下它的Processing版本,之后介绍如何修改,让它变成名副其实的"冰与火之歌":凛冬之后,火影摇曳。
FireBrush
分析作品
分析Fire Brush作品我们可以获得如下发现。
该作品由两种元素构成,火焰和烟雾。拖动鼠标,会增加火焰。火焰会沿着鼠标拖动的方向移动,同时也会向下运动,过一段时间后会消失。在火焰移动的过程中会有烟雾出现,它们会向两边跳动,给人一种喷发的感觉,最后也会慢慢消失。
火焰是由一个个圆构成,每个大圆里还有一个小圆,并且它们的透明度不同。每一个烟雾是一个黑色的圆,它们的透明度也不一样。
还有一个细节就是作品背景的颜色会随着火焰数量的变化而变化。那么接下来我们就来一起看看如何实现以上的效果。
大概流程
我们首先来看大概的流程。我们在setup函数中初始化了我们的粒子系统,然后在draw函数中不断更新背景的颜色、粒子的状态,以及监听按下鼠标左键事件,判断是否需要加入新的火焰。
注意这里颜色的模式不是RGB,而是HSB。并且按下一次鼠标左键会调用多次addFire函数,因为按下鼠标不是一瞬间的事情,这段时间会执行多次draw函数。
ParticleSystem ps;
void setup() {
size(600, 600);
colorMode(HSB, 255);
ps = new ParticleSystem();
}
void draw() {
//根据火焰粒子的数量来确定背景颜色的饱和度
background(255, ps.getSize(), 255);
ps.run();
if (mousePressed && mouseButton == LEFT) {
//按一次鼠标会执行多次这里的函数
ps.addFire(mouseX, mouseY);
}
}
class ParticleSystem {
}
class Particle {
}
class Fire extends Particle{
}
class Smoke extends Particle{
}
接下来来看ParticleSystem这个类,看它是如何存储粒子、管理粒子的行为。我们用一个ArrayList来存储所有的粒子,并且每次更新的时候需要删除生命走到尽头的粒子。
class ParticleSystem {
ArrayList<Particle> plist;
ParticleSystem() {
plist = new ArrayList<Particle>();
}
void run() {
for (int i = plist.size() - 1; i >= 0; i--) {
Particle p = plist.get(i);
p.run();
//删除生命走到尽头的粒子
if (p.isDead()) {
plist.remove(i);
}
}
}
void addFire(float x, float y) {
plist.add(new Fire(x, y));
}
void addSmoke(float x, float y, float size) {
plist.add(new Smoke(</