粒子爆炸:
仍然要用到以前的小球类,不过稍加改造
01
package
{
02
import
flash.display.Sprite;
03
04
//小球 类
05
public
class
Ball
extends
Sprite {
06
07
public
var
radius:
uint
;
//半径
08
public
var
color:
uint
;
//颜色
09
public
var
vx:
Number
=
0
;
//x轴速度
10
public
var
vy:
Number
=
0
;
//y轴速度
11
12
public
function
Ball(r:
Number
=
50
,c:
uint
=
0xff0000
) {
13
this
.radius=r;
14
this
.color=c;
15
init();
16
}
17
18
private
function
init():
void
{
19
graphics.beginFill(color);
20
graphics.drawCircle(
0
,
0
,radius);
21
graphics.endFill();
22
}
23
}
24
}
增加了x,y轴的速度,其它没变
原理:在舞台的某一区域放置大量小球实例,然后在某个时刻让其向四面八方运动即可(即改变每个小球在x,y轴上的坐标)
问题:效率!让CPU在每帧对于大量对象进行重绘是很耗资源的,所以当小球跑出舞台边界时,得想办法通知CPU:这些小球不需要再处理了(反正也看不见)!否则纯属折腾CPU,下面的代码用一个数组存放所有对象实例的引用,然后在EnterFrame事件中不断检测,一旦有对象跑出边界了,就将其清除,不再理会了.
01
import
fl.controls.Label;
02
import
flash.text.TextFieldAutoSize;
03
04
stage.scaleMode=StageScaleMode.NO_SCALE;
05
stage.align=StageAlign.TOP_LEFT;
06
07
var
Count:
Number
=
1500
;
08
var
Radius:
uint
=
30
;
09
var
CenterX:
uint
=stage.stageWidth/
2
;
10
var
CenterY:
uint
=stage.stageHeight/
2
;
11
12
var
ArrBall:
Array
=
new
Array
(Count);
13
14
//让小球呈圆形随机分布
15
for
(
var
i=
0
; i<ArrBall.length; i++) {
16
ArrBall[i]=
new
Ball(Math.random() *
5
,Math.random() *
0xff0000
);
17
var
angle:
Number
=Math.random()*Math.PI*
2
;
18
var
RadiusRnd:
Number
=Math.random()*Radius;
19
ArrBall[i].x=CenterX+Math.cos(angle)*RadiusRnd;
20
ArrBall[i].y=CenterY+Math.sin(angle)*RadiusRnd;
21
addChild(ArrBall[i]);
22
}
23
24
var
lbl1:Label =
new
Label();
25
lbl1.text=
"点击鼠标引爆这个球"
;
26
lbl1.autoSize=TextFieldAutoSize.CENTER;
27
28
lbl1.x=stage.stageWidth/
2
-lbl1.width/
2
;
29
lbl1.y=
50
;
30
Mouse.cursor=MouseCursor.BUTTON;
31
addChild(lbl1);
32
33
stage.addEventListener(MouseEvent.MOUSE_MOVE,MouseMoveHandler);
34
stage.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);
35
36
//文件鼠标跟随
37
function
MouseMoveHandler(e:MouseEvent):
void
{
38
lbl1.x=mouseX+
15
;
39
lbl1.y=mouseY+
15
;
40
}
41
42
function
MouseDownHandler(e:MouseEvent):
void
{
43
//点击一次后,取消鼠标跟随,并移除lbl1,同时也取消鼠标点击事件(即本事件仅触发一次)
44
Mouse.cursor=MouseCursor.ARROW;
45
stage.removeEventListener(MouseEvent.MOUSE_MOVE,MouseMoveHandler);
46
lbl1.visible=
false
;
47
removeChild(lbl1);
48
stage.removeEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);
49
50
InitVelocity();
//初始化粒子速度
51
52
addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
53
}
54
55
function
InitVelocity() {
56
for
(
var
i=
0
; i<ArrBall.length; i++) {
57
ArrBall[i].vx = (Math.random()*
2
-
1
) *
30
;
//注意这里的小技巧: Math.random()*2-1即得到一个在-1到1之间分布的随机小数,即小球随机向左或向右的初始速度,然后再放大N倍,得到x轴最终速度
58
ArrBall[i].vy = (Math.random()*
2
-
1
) *
30
;
59
}
60
61
}
62
63
64
function
EnterFrameHandler(e:Event):
void
{
65
for
(i=ArrBall.length-
1
; i>=
0
; i--) {
66
var
ball:Ball = ArrBall[i];
67
ball.x += (ball.vx );
68
ball.y += (ball.vy );
69
//检测边界,如果超出屏幕则移除该对象(注:从舞台上移除不再使用的对象,能使CPU占用率有效降低)
70
if
(ball.x < -ball.width/
2
|| ball.x > stage.stageWidth + ball.width/
2
|| ball.y< -ball.height/
2
|| ball.y > stage.stageHeight + ball.height/
2
){
71
removeChild(ball);
72
ArrBall.splice(i,
1
);
73
}
74
75
//如果数组已经为空,则清除EnterFrame事件
76
if
(ArrBall.length==
0
){
77
removeEventListener(Event.ENTER_FRAME,EnterFrameHandler);
78
}
79
80
//trace(ArrBall.length);
81
82
83
}
84
}
粒子喷射:
如果看过上篇Flash/Flex学习笔记(23):运动学原理 并动手实践过"自由落体运动"的朋友,对于这种粒子效果可能比较容易理解。
原理:将所有粒子聚集于屏幕上某点(本例中为屏幕底部中心点),然后赋给一个随机向上的速度(这样就能向上喷射出),同时为了更效果更自然,还要加入随机的x轴方向速度(以实现喷射过程中的扩散),最后再加入重力加速度,以实现粒子的自由回落。
效率:为了能最大限度的利用现有对象,当粒子跑出舞台边界时,重新用代码将其定位到发射点,以便下次继续喷射。
交互:本例中为增强交互性,用鼠标的x轴位置模拟了风力影响。(在水平方向移动鼠标可看到喷射方向略有变化)
01
package
{
02
import
flash.display.Sprite;
03
import
flash.display.StageAlign;
04
import
flash.display.StageScaleMode;
05
import
flash.events.Event;
06
public
class
Fountain
extends
Sprite {
07
private
var
count:
int
=
3000
;
08
private
var
wind:
Number
=
0.0
;
09
10
private
var
gravity:
Number
=
0.3
;
11
private
var
balls:
Array
;
12
public
function
Fountain() {
13
init();
14
}
15
private
function
init():
void
{
16
stage.scaleMode=StageScaleMode.NO_SCALE;
17
stage.align=StageAlign.TOP_LEFT;
18
balls =
new
Array
();
19
for
(
var
i:
int
=
0
; i < count; i++) {
20
var
ball:Ball=
new
Ball(
1
,
0xffffff
);
21
ball.x=stage.stageWidth/
2
;
22
ball.y=stage.stageHeight;
23
ball.vx = (Math.random()*
2
-
1
) *
1.5
+ wind;
24
ball.vy=-
5
+Math.random()*-
10
;
25
addChild(ball);
26
balls.push(ball);
27
}
28
addEventListener(Event.ENTER_FRAME, onEnterFrame);
29
}
30
private
function
onEnterFrame(event:Event):
void
{
31
wind = -
1
*(mouseX - stage.stageWidth/
2
)/
200
;
32
for
(
var
i:
Number
=
0
; i < balls.length; i++) {
33
var
ball:Ball=Ball(balls[i]);
34
ball.vy+=gravity;
35
ball.x+=ball.vx;
36
ball.y+=ball.vy;
37
if
(ball.x > stage.stageWidth + ball.radius || ball.x < -ball.radius || ball.y >stage.stageHeight + ball.radius || ball.y<-ball.radius) {
38
ball.x=stage.stageWidth/
2
;
39
ball.y=stage.stageHeight;
40
ball.vx = (Math.random()*
2
-
1
) *
1.5
+ wind;
41
ball.vy=-
5
+Math.random()*-
10
;
42
}
43
}
44
}
45
}
46
}
粒子跟随:
除了利用边界检测移除粒子外,在实际开发中也经常利用时间来判断,比如一个对象在舞台上存活几秒后,便将其干掉。
01
stage.addEventListener(MouseEvent.MOUSE_MOVE,MouseMoveHandler);
02
03
function
MouseMoveHandler(e:MouseEvent):
void
{
04
var
ball:Ball =
new
Ball(Math.random()*
3
,
0x00ff00
);
05
ball.x = mouseX;
06
ball.y = mouseY;
07
ball.vx = (Math.random()*
2
-
1
)*
3
;
08
ball.vy = (Math.random()*
2
-
1
)*
3
;
09
addChild(ball);
10
ball.addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
11
}
12
13
function
EnterFrameHandler(e:Event):
void
{
14
var
ball:Ball = e.target
as
Ball;
15
ball.x += ball.vx;
16
ball.y += ball.vy;
17
ball.count ++;
18
if
(ball.count>=
50
){
19
ball.removeEventListener(Event.ENTER_FRAME,EnterFrameHandler);
20
removeChild(ball);
21
}
22
}
注:需要先在Ball类中增加一个public var count:uint=0;变量(用来辅助计时),上面的代码中用 if ball.count>=50做判断,相当于每个小球只让其播放50帧对应的时间就寿终正寝
模拟布朗运动:
01
var
Count:
Number
=
200
;
02
03
//初始化
04
for
(
var
i:
Number
=
0
; i<=Count; i++) {
05
var
ball:Ball=
new
Ball(Math.random()*
3
,
0x00ff00
);
06
ball.x=Math.random()*stage.stageWidth;
07
ball.y=Math.random()*stage.stageHeight;
08
ball.vx=ball.vy=
0
;
09
addChild(ball);
10
ball.addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
11
}
12
13
function
EnterFrameHandler(e:Event):
void
{
14
var
ball:Ball=e.target
as
Ball;
15
//每一帧让其速度随机变化一点点
16
ball.vx += (Math.random()*
2
-
1
)*
2
;
17
ball.vy += (Math.random()*
2
-
1
)*
2
;
18
19
ball.x+=ball.vx;
20
ball.y+=ball.vy;
21
22
//超出边界后,先让其反向运动一次(即:退回原处),然后速度反向
23
if
(ball.x>stage.stageWidth-ball.width/
2
||ball.x<ball.width/
2
) {
24
ball.x-=ball.vx;
25
ball.vx*=-
1
;
26
}
27
28
if
(ball.y>stage.stageHeight-ball.height/
2
||ball.y<ball.height/
2
) {
29
ball.y-=ball.vy;
30
ball.vy*=-
1
;
31
}
32
33
//加入摩擦力因子,看起来更自然
34
ball.vx=ball.vx*
0.9
;
35
ball.vy=ball.vy*
0.9
;
36
}