particleVO.as:
1: package com.helloshp.vo
2: {
3: import flash.display.BitmapData;
4:
5: //粒子对象属性
6: public class ParticleVO
7: {
8: public var bmd:BitmapData;//用来装载切图
9: public var crtPosX:Number;//该粒子对象当前出现在舞台的X位置
10: public var crtPosY:Number;//该粒子对象当前出现在舞台的Y位置
11: public var tragetX:Number;//该粒子最后要运动到的舞台的X位置
12: public var tragetY:Number;//该粒子最后要运动到的舞台的Y位置
13: }
14: }
Main.as:
1: package
2: {
3: import com.helloshp.vo.ParticleVO;
4:
5: import flash.display.Bitmap;
6: import flash.display.BitmapData;
7: import flash.display.Sprite;
8: import flash.events.Event;
9: import flash.events.MouseEvent;
10: import flash.events.TimerEvent;
11: import flash.geom.Point;
12: import flash.geom.Rectangle;
13: import flash.utils.Timer;
14:
15: [SWF(width="800",height="600")]
16: public class Main extends Sprite
17: {
18: [Embed(source="assets/imgTest0.jpg")]
19: private var imgTest0:Class;
20: [Embed(source="assets/imgTest1.jpg")]
21: private var imgTest1:Class;
22: [Embed(source="assets/imgTest2.jpg")]
23: private var imgTest2:Class;
24: [Embed(source="assets/imgTest3.jpg")]
25: private var imgTest3:Class;
26: [Embed(source="assets/imgTest4.jpg")]
27: private var imgTest4:Class;
28:
29: private var bmpimgTest:Bitmap;
30: private var bmp:Bitmap;
31: private var bmd:BitmapData;
32: private var particleVOList:Array;
33: private var currentIndex:int;
34: private var isStop:Boolean;
35: private var timer:Timer;
36:
37: public function Main()
38: {
39: init();
40: }
41:
42: private function init():void{
43: initData();
44: addEventListener(Event.ENTER_FRAME,efHandler);
45: stage.addEventListener(MouseEvent.CLICK,clickHandler);
46: timer = new Timer(3500);
47: timer.addEventListener(TimerEvent.TIMER,timerHandler);
48: timer.start();
49: }
50:
51: private function initData():void{
52: //清除舞台所以的可视对象
53: for(;this.numChildren>0;){
54: this.removeChildAt(0);
55: }
56:
57: //实例化用于创建粒子对象的数组
58: particleVOList = new Array();
59: //把即将要切片的imgTest.jpg图片装载到一个Bitmap视图容器里面
60: bmpimgTest = getImg( currentIndex );
61: //实例化待加载切图的画布
62: bmd = new BitmapData(800,600,true,0);
63: //把画布加载到显示容器里面去,等哈儿显示所有的粒子对象用
64: bmp = new Bitmap( bmd );
65: //把显示容器加载到舞台
66: addChild(bmp);
67: //初始化粒子对象
68: initParticleVO();
69: }
70:
71: private function getImg(crtIndex:int):Bitmap{
72: switch(crtIndex){
73: case 0:
74: return new imgTest0();
75: break;
76: case 1:
77: return new imgTest1();
78: break;
79: case 2:
80: return new imgTest2();
81: break;
82: case 3:
83: return new imgTest3();
84: break;
85: case 4:
86: return new imgTest4();
87: break;
88: default:
89: return new imgTest0();
90: break;
91: }
92:
93: }
94:
95: //当鼠标点击后,暂停或者继续播放
96: private function clickHandler(e:MouseEvent):void{
97: isStop = isStop?false:true;
98: if(isStop){
99: timer.stop();
100: }
101: else{
102: timer.reset();
103: timer.start();
104: }
105:
106: }
107:
108: //初始化所有的粒子对象,每个粒子对象其实就是把加载的testImg图片,通过2重循环切成一个一个的bitmapData,
109: //并设置每个粒子对象的当前坐标(待会儿舞台显示出现的位置),目标坐标(就是粒子对象要移动到的位置),并存放到数组。
110: //通过2重循环切testImg图的时候关键是,新建立一个尺寸10 X 10 大小的bitmapData对象,然后通过它的copyPixels()方法去切加载的图片。
111: //copyPixels(),的参数1: 就是要切的图片对象的bitmapData,参数2: 创建一个要切的那一个方块对象,该方块对象的x,y坐标就是该方块最终要放置到舞台上的坐标
112: //参数3:切图的坐标点,默认设置为原点。
113: private function initParticleVO():void{
114: //行数为50行,因为每次切图的高就是10像素,60*10=600,刚好就是我的图片的高
115: for( var row:int=0;row<60;row++ ){
116: //宽度为80行,因为每次切图的宽就是10像素,80*10=800,刚好就是我的图片的宽
117: for(var col:int=0;col<80;col++){
118: //初始化每一个粒子VO
119: var pvo:ParticleVO = new ParticleVO();
120: pvo.tragetX = col * 10;//粒子目标X坐标(就是粒子对象最终要移动到的X位置)
121: pvo.tragetY = row * 10;//粒子目标Y坐标(就是粒子对象最终要移动到的Y位置)
122: pvo.crtPosX = col * 10 + Math.random() * 1000; //粒子在舞台显示的X位置.通过随机数打乱初始位置
123: pvo.crtPosY = row * 10 + Math.random() * 1000;//粒子在舞台显示的Y位置,通过随机数打乱初始位置
124: pvo.bmd = new BitmapData(10,10,true,0);//创建一个空白的画布
125: //关键代码,就是切图操作
126: pvo.bmd.copyPixels( bmpimgTest.bitmapData,new Rectangle(pvo.tragetX,pvo.tragetY,10,10),new Point() );
127: //把每个切出来的图,装载到一个数组里面(等哈儿再渲染到舞台上出来)
128: particleVOList.push( pvo );
129: }
130: }
131: }
132:
133: private function efHandler(e:Event):void{
134: if(isStop) return;
135: //bmd.lock()
136: //创建一个800 X 600 的空白的画布
137: bmd = new BitmapData(800,600,true,0);
138: //循环取出每一个刚刚切好的图片,然后再转载到画布里面
139: for(var i:int=0;i<particleVOList.length;i++){
140: var pvo:ParticleVO = particleVOList[i];
141: pvo.crtPosX += ( pvo.tragetX - pvo.crtPosX ) / ( 2 + Math.random() * 20 );//X轴缓动效果
142: pvo.crtPosY += ( pvo.tragetY - pvo.crtPosY ) / ( 2 + Math.random() * 20) ;//Y轴缓动效果
143: //关键代码,把数组里面装的每一个小的切图,装载到800 X 600 的大的画布里面去。装载的时候,都是按照粒子对象对应的X,Y坐标装载的。
144: bmd.copyPixels( pvo.bmd, new Rectangle(0,0,10,10 ),new Point(pvo.crtPosX,pvo.crtPosY) );
145: }
146: //把装载好的画布,赋值给显示对象,让可视对象bmp在舞台上渲染出图片出来
147: bmp.bitmapData = bmd;
148: //bmd.unlock();
149: }
150:
151: private function timerHandler(e:TimerEvent):void{
152: currentIndex++;
153: if(currentIndex > 4 ){
154: currentIndex = 0;
155: }
156: initData();
157: }
158: }
159: }
关于冒泡事件的理解,主要有3个阶段:
1.捕获阶段,eventPhase的属性值1
2.目标阶段,eventPhase的属性值2
3.冒泡阶段,eventPhase的属性值3
以上为黑羽所著的《actionscript3殿堂之路》中描述为。让我们来看下面的例子:
比如点击以上倒数第3个容器,事件流过程如下图:
如果在点击容器C的事件里,让这次点击事件停止冒泡的话,拖拽这个容器的时候,这个容器和包含在这个容器
上面的其它容器都会跟着移动。所点击的这个容器以下的容器就不会跟着移动了,因为在所点击的容器的事件里,
已经让冒泡已经停止了,即是说向舞台冒泡的趋于也停止住了。程序中e.stopPropagation(),是停止冒泡的关键
。
如果在点击容器C的事件里,不停止这次点击事件冒泡的话,这次点击的会冒泡到最接近舞台的那个容器去,也
就是最下边那个大容器。当然拖拽的时候,就是对大容器进行拖拽操作,大容器上面的那些被包含的其它容器也会
跟着移动。
分析:
上例中按键向右的话,小球向右边移动,按键向左的话,小球向左移动,当快移动到背景图的两端时候,小球还在移动,直到靠边。
其实当小球移动到舞台的中央过后,再向右移动的时候,背景图就同时开始在向左移动,直到小球移动到快要到背景图的另外一端,背景图才不移动。 从舞台一端开始,你移动小球到了舞台正中央的时候,你应该感觉到小球始终在正中央,此时的背景在向小球移动相反的方向移动。
你观看这个过程就像你观看一个人在扶手自动电梯上向电梯相反方向走步一样。电梯向上一台阶,人就向下一台阶。所以人始终还是在电梯原来那一阶,这个道理就和小球为什么始终在舞台中央一样,但电梯一直在向上运动。如果把人比作小球,电梯比作背景,那么背景就一直在向上运动,就会感觉背景里的小球没运动。 当然你也可以理解为,小球向下运动,而背景没运动。这个就看你选择什么作为参照物了。
程序中,背景图宽800像素,小球和背景分别用了两个视图容器来处理这种相对移动。
小球类:
Ball.as
1: package com.helloshp.view
2: {
3: import flash.display.Sprite;
4:
5: public class Ball extends Sprite
6: {
7: public function Ball()
8: {
9: super();
10: init();
11: }
12:
13: private function init():void{
14: this.graphics.beginFill(0xff0000);
15: this.graphics.drawCircle(0,0,20);
16: this.graphics.endFill();
17: }
18: }
19: }
背景类:
SceneView.as
1: package com.helloshp.view
2: {
3: import flash.display.Sprite;
4:
5: public class SceneView extends Sprite
6: {
7: [Embed(source="assets/bg.jpg")]
8: private var bg:Class;
9:
10: public function SceneView()
11: {
12: super();
13: init();
14: }
15:
16: private function init():void{
17: addChild( new bg() );
18: }
19: }
20: }
主视图类:
MainView.as
1: package com.helloshp
2: {
3: import com.helloshp.view.Ball;
4: import com.helloshp.view.SceneView;
5:
6: import flash.display.Sprite;
7: import flash.events.Event;
8: import flash.events.KeyboardEvent;
9: import flash.ui.Keyboard;
10:
11: public class MainView extends Sprite
12: {
13: private var ball:Ball;
14: private var sv:SceneView;
15:
16: private var isStart:Boolean;
17: private var speed:int;
18: private const LIMIT_LEFT:int=0; //背景图左边界
19: private const LIMIT_RIGHT:int=800;//背景图右边界
20:
21: public function MainView()
22: {
23: super();
24:
25:
26: if(stage!=null){
27: init();
28: }
29: else{
30: this.addEventListener(Event.ADDED_TO_STAGE,addedHandler)
31: }
32:
33: }
34:
35: private function init():void{
36: ball = new Ball();
37: sv = new SceneView();
38: addChild( sv ); //把背景试图放到舞台上
39: sv.addChild(ball);//把小球放到背景试图里面,而不是放到舞台上
40: ball.y = 200;
41:
42: stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownHandler);
43: stage.addEventListener(KeyboardEvent.KEY_UP,kyUpHandler);
44: addEventListener(Event.ENTER_FRAME,enterFrameHandler);
45: }
46:
47: //键盘弹起就停止移动
48: private function kyUpHandler(e:KeyboardEvent):void{
49: isStart = false;
50: }
51:
52: //键盘按下就开始移动
53: private function keyDownHandler(e:KeyboardEvent):void{
54: switch( e.keyCode ){
55: case Keyboard.RIGHT:
56: isStart = true;
57: speed = 10;
58: break;
59: case Keyboard.LEFT:
60: isStart = true;
61: speed = -10;
62: break;
63: default:
64: speed = 0;
65: break;
66: }
67: }
68:
69: private function enterFrameHandler(e:Event):void{
70: if( !isStart) return;
71:
72: ball.x += speed;//小球在X轴加速移动
73:
74:
75: if(ball.x < LIMIT_LEFT)//如果小球的X坐标小于背景视图的左边界,就让小球一直停止在视图的左边界的位置
76: ball.x = LIMIT_LEFT;
77: else if( ball.x > LIMIT_RIGHT )//如果小球的X坐标大于背景视图的右边界,就让小球一直停止在视图的右边界位置
78: ball.x = LIMIT_RIGHT;
79:
80:
81: if( ball.x < stage.stageWidth/2 ){//如果小球X坐标运动小于舞台一半,就让场景视图停止在左边界
82: sv.x = LIMIT_LEFT;
83: }
84: else if( ball.x > LIMIT_RIGHT - stage.stageWidth/2 ){//如果小球X坐标运动到 大于 背景视图右边界减去舞台宽度一半,就让背景视图右边界移动到舞台的右边界
85: sv.x = -LIMIT_RIGHT + stage.stageWidth;
86: }
87: else{//当小球运动到舞台的一半的时候,背景视图 就在舞台上向小球相反的方向运动,
88: sv.x = -(ball.x - stage.stageWidth/2);
89: }
90: }
91:
92: private function addedHandler(e:Event):void{
93: init();
94: }
95: }
96: }
源代码下载:http://files.cnblogs.com/bigbigdotnet/relativeMove.rar
如果遇到数组中有连续的相同的内容的时候,比如类似以下的数组:
var testAry:Array = [6,1,1,5];
你想去掉去除1,过后数组的内容变成:[6,5];但结果呢,试试以下代码:
for(var i:int=0;i<testAry.length;i++){
if(testAry[i] == 1){
testAry.splice(i,1);
}
}
trace(testAry);
输出:6,1,5
为什么还有个1,没有去掉呢?当splice()方法对数组里的元素进行删除的时候,当切割到数组下标i=1的时候,就会把数组的length减1,下一次循环到的下标的位置就为i=3,下标i=2的元素就被跳过了。
以下办法可以解决使用splice的安全问题 :
1.数组元素每次删除后,下标自减一次
public function doSplice1(ary:Array):Array{
for(var i:int=0;i<ary.length;i++){
if(ary[i] == 1){
ary.splice(i,1);
i--;
}
}
return ary;
}
2.倒着进行循环删除处理
public function doSplice2(ary:Array):Array{
for(var i:int=ary.length;i>=0;i--){
if(ary[i] == 1){
ary.splice(i,1);
}
}
return ary;
}