提到烟花,大家首先想到的都是天空上那绽放的炫美,或者手中炫目的白光,作为计算机体制内的人,以面向对象的思维来看待烟花的话,会得到什么呢?我们可以将美丽的烟花效果抽象为由一个个粒子组成的一个系统,将粒子作为对象,它拥有坐标、颜色、速度、生命周期等属性,通过对大量粒子的颜色、路径处理,就可以得到近似的烟花效果啦,那么我们一起来看一下怎么实现吧!
- Java面向对象
- 线程、双缓冲画图
基本思路
1.粒子对象
我们所说的粒子,可以理解为空间中的一个点,或者半径较小的圆,主要有以下属性:
- 独立性:每个粒子是独立的对象,互不影响
- 状态性:粒子的状态包括运动状态、外观状态等,每个状态中包含着对应的属性
- 生命周期:粒子会经历从产生到消亡的周期
2.路径实现
在实例化粒子对象之后,我们要考虑的就是如何让粒子按照烟花的轨迹来动起来,这才是整个程序的关键,就是路径实现问题。想必基本的小球运动线程大家都很熟悉,只要给出初始坐标,配合v-t、a-t函数即可得到路径。
欧拉方法:设物体在任意时间 t 的状态:位置矢量为 r(t)、速度矢量为v(t) 、加速度矢量为a(t), 则:
v(t+△t)=v(t)+a(t)△t
r(t+△t)=r(t)+v(t)△t
即从时间t的状态,计算下一个模拟时间t+△t的状态。
这里我们模拟的是仙女棒的效果,使用的v-t、a-t函数为:
pt.vspeed=new Vector(10,-20);
pt.vacceleration=randomDirection();
public static Vector randomDirection() {
//Math.random(),随机选取大于等于 0.0 且小于 1.0 的伪随机 double 值
double theta=Math.random()*3*Math.PI;
return new Vector((Math.cos(theta)),(Math.sin(theta)));
}
函数所产生的角从0-3π,加速度的函数为(cosθ,sinθ),画出坐标图来大家就可以发现,是圈型轨迹,随着粒子向外运动和规模的增大,效果就近似于仙女棒了,怎么样,是不是想不到~(@ο@) ~
3.具体实现
思路清晰了,实现起来就简单了嘛,建立以下类:
- 粒子类Particle:包括坐标、颜色、大小、周期等属性
- 界面类:用来实现Swing界面,添加监听器(建议用内部类,节省资源),启动线程
- 线程类:实例化粒子对象,放入粒子队列,然后获取画笔,将粒子画出来,这里因为粒子规模大、移动快,导致刷新比较频繁,为解决闪烁问题,使用了双缓冲技术,即先把粒子画在Image上,再放到窗体上:
Image image=jf.createImage(jf.getWidth(),jf.getHeight());
Graphics bg=image.getGraphics();
bg.draw.....
jf.getGraphics().drawImage(image, 0, 0, null);
- 矢量类Vector:粒子的坐标、速度、加速度均可以抽象为二维变量,根据前面讲的欧拉公式,在此类中建立两个函数即可:
public Vector add(Vector v) {
return new Vector(this.x+v.x,this.y+v.y);
}
public Vector multiple(double rate) {
return new Vector(this.x*rate,this.y*rate);
}
//线程类中,对应的粒子的坐标和速度的刷新
p.vposition=p.vposition.add(p.vspeed.multiple(rate));
p.vspeed=p.vspeed.add(p.vacceleration.multiple(rate));
4.成果
(懒得做gif别打我啊)
额,看着有那么点凌乱,哎呀,不管了,有兴趣的同学可以改一改路径函数,做一个天空版的烟花(我今天回去试一下)。