文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>Flash/Flex学习笔记(57):实用技巧

Flash/Flex学习笔记(57):实用技巧

时间:2010-11-22  来源:模西的哥哥

01 varnumDots:uint=50;
02 varfriction:Number=0.9;
03 vardots:Array;
04 varlife:uint=0;
05   
06 functioninit(){
07     graphics.lineStyle(0,0xffffff,.5);
08     dots=newArray();
09     for(vari:uint=0;i<numDots;i++){
10         vardot:Ball=newBall(2,0x00ff00);
11         dot.x=Math.random()*stage.stageWidth;
12         dot.y=Math.random()*stage.stageHeight;
13         dot.vx=0;
14         dot.vy=0;
15         dots.push(dot);
16         addChild(dot);
17         checkBound(dot);
18     }
19     addEventListener(Event.ENTER_FRAME,enterFrameHandler);
20 }
21   
22 //检查边界
23 functioncheckBound(b:Ball){
24     if(b.x<b.width/2){
25         b.x=b.width/2;
26     }
27     elseif(b.x>stage.stageWidth-b.width/2){
28         b.x=stage.stageWidth-b.width/2;
29     }
30     if(b.y<b.height/2){
31         b.y=b.height/2;
32     }
33     elseif(b.y>stage.stageHeight-b.height/2){
34         b.y=stage.stageHeight-b.height/2;
35     }
36 }
37   
38 functionenterFrameHandler(e:Event):void{
39     //trace(life);
40     if(life>=200){
41         graphics.clear();
42         graphics.lineStyle(0,0xffffff,.5);
43         life=0;
44     }
45     for(vari:uint=0;i<numDots;i++){
46         vardot:Ball=dots[i];
47         graphics.moveTo(dot.x,dot.y);
48         dot.vx+=Math.random()-0.5;
49         dot.vy+=Math.random()-0.5;
50         dot.x+=dot.vx;
51         dot.y+=dot.vy;
52         dot.vx*=friction;
53         dot.vy*=friction;
54         checkBound(dot);
55         graphics.lineTo(dot.x,dot.y);
56     }
57     life++;
58 }
59   
60 init();

矩形分布:

show sourceview source print?
01 vardotNumber:uint=500;
02 vardots:Array;
03 varcenterX:uint=stage.stageWidth/2;
04 varcenterY:uint=stage.stageHeight/2;
05 varlimitX:uint=50;
06 varlimitY:uint=100;
07   
08 functioninit():void{
09     dots=newArray();    
10     for(vari:uint=0;i<dotNumber;i++){
11         vardot:Ball=newBall(3*Math.random(),0x00ff00);
12         dot.x=centerX+(Math.random()*2-1)*limitX;
13         dot.y=centerY+(Math.random()*2-1)*limitY;
14         addChild(dot);      
15         dots.push(dot);
16     }
17     addEventListener(Event.ENTER_FRAME,enterframeHandler);
18 }
19   
20 functionenterframeHandler(e:Event):void{
21     for(vari:uint=0;i<dotNumber;i++){
22         vardot:Ball=dots[i];
23         dot.x=centerX+(Math.random()*2-1)*limitX;
24         dot.y=centerY+(Math.random()*2-1)*limitY;       
25         /*varix:Number=dot.x;
26         variy:Number=dot.y;
27         dot.y=ix;
28         dot.x=iy*/
29     }
30 }
31   
32 init();

圆形随机分布:

show sourceview source print?
01 vardotNumber:uint=500;
02 vardots:Array;
03 varcenterX:uint=stage.stageWidth/2;
04 varcenterY:uint=stage.stageHeight/2;
05 varradius:uint=75;
06   
07 functioninit():void{
08     dots=newArray();
09     for(vari:uint=0;i<dotNumber;i++){
10         vardot:Ball=newBall(3*Math.random(),0x00ff00);
11         varangle:Number=2*Math.random()*Math.PI;
12         varr:Number=Math.random()*radius;
13         dot.x=centerX+r*Math.cos(angle);
14         dot.y=centerY+r*Math.sin(angle);
15         addChild(dot);
16         dots.push(dot);
17     }
18     addEventListener(Event.ENTER_FRAME,enterframeHandler);
19 }
20   
21 functionenterframeHandler(e:Event):void{
22     for(vari:uint=0;i<dotNumber;i++){
23         vardot:Ball=dots[i];
24         varangle:Number=2*Math.random()*Math.PI;
25         varr:Number=Math.random()*radius;
26         dot.x=centerX+r*Math.cos(angle);
27         dot.y=centerY+r*Math.sin(angle);
28     }
29 }
30   
31 init();

更均匀的圆形随机分布:

show sourceview source print?
01 vardotNumber:uint=200;
02   
03 varcenterX:uint=stage.stageWidth/2;
04 varcenterY:uint=100;
05 varradius:uint=50;
06   
07 functioninit():void{
08       
09     for(vari:uint=0;i<dotNumber;i++){
10         vardot:Ball=newBall(2,0x00ff00);
11         varangle:Number=2*Math.random()*Math.PI;        
12         varr:Number=Math.random()*radius;
13         dot.x=centerX+r*Math.cos(angle);
14         dot.y=centerY+r*Math.sin(angle);
15         addChild(dot);
16           
17     }
18       
19     //更均匀的随机分布
20     for(i=0;i<dotNumber;i++){
21         vardot1:Ball=newBall(2,0x00ff00);
22         varangle1:Number=2*Math.random()*Math.PI;
23         varr1:Number=Math.sqrt(Math.random())*radius;//关键在这里,对Math.random()取平方根后,分布变得更均匀了
24         dot1.x=centerX+r1*Math.cos(angle1);
25         dot1.y=centerY+200+r1*Math.sin(angle1);
26         addChild(dot1);
27           
28     }
29       
30 }
31   
32   
33 init();

偏向分布:(即在指定的区域内,中心位置分布最密集,离中心越远,分布越稀疏)

show sourceview source print?
01 vardotNumber:uint=600;
02 varcenterX:uint=stage.stageWidth/2;
03 varmaxWidth:uint=75;
04 varballs:Array=newArray();
05   
06 functioninit():void{
07   
08     for(vari:uint=0;i<dotNumber;i++){
09         vardot:Ball=newBall(2,0x00ff00);
10   
11         //在y轴方向上随便取二个值,然后计算平均值做为y坐标
12         vary1=stage.stageHeight*Math.random();
13         vary2=stage.stageHeight*Math.random();
14   
15         varty=(y1+y2)/2;
16   
17         //x轴做类似的处理
18         varx1=centerX+(Math.random()*2-1)*maxWidth;
19         varx2=centerX+(Math.random()*2-1)*maxWidth;
20   
21         vartx=(x1+x2)/2;
22   
23   
24         dot.x=tx;
25         dot.y=ty;
26   
27         addChild(dot);
28   
29         balls.push(dot);
30     }
31     stage.frameRate=1;
32     addEventListener(Event.ENTER_FRAME,enterFrameHandler);
33 }
34   
35 init();
36   
37   
38 functionenterFrameHandler(e:Event){
39     for(vari:uint=0;i<dotNumber;i++){
40         vardot:Ball=balls[i];
41   
42   
43         vary1=stage.stageHeight*Math.random();
44         vary2=stage.stageHeight*Math.random();
45   
46         varty=(y1+y2)/2;
47   
48   
49         varx1=centerX+(Math.random()*2-1)*maxWidth;
50         varx2=centerX+(Math.random()*2-1)*maxWidth;
51   
52         vartx=(x1+x2)/2;
53   
54   
55         dot.x=tx;
56         dot.y=ty;
57   
58   
59     }
60 }

多次迭代的偏向分布(类似星云分布)

show sourceview source print?
01 vardotNumber:uint=100;
02 variterations:uint=6;
03 varballs:Array=newArray();
04   
05 functioninit():void{
06   
07     for(vari:uint=0;i<dotNumber;i++){
08         vardot:Ball=newBall(2,0x00ff00);
09   
10         varxpos:Number=0;
11         varypos:Number=0;
12         for(varj:uint=0;j<iterations;j++){
13             xpos+=stage.stageWidth*Math.random();
14             ypos+=stage.stageHeight*Math.random();
15         }
16   
17         dot.x=xpos/iterations;
18         dot.y=ypos/iterations;
19           
20         addChild(dot);
21           
22         balls.push(dot);
23     }
24       
25     stage.frameRate=1;
26     addEventListener(Event.ENTER_FRAME,enterFrameHandler);
27 }
28   
29 init();
30   
31   
32 functionenterFrameHandler(e:Event){
33     for(vari:uint=0;i<dotNumber;i++){
34         vardot:Ball=balls[i];
35       
36           
37         varxpos:Number=0;
38         varypos:Number=0;
39         for(varj:uint=0;j<iterations;j++){
40             xpos+=stage.stageWidth*Math.random();
41             ypos+=stage.stageHeight*Math.random();
42         }
43   
44         dot.x=xpos/iterations;
45         dot.y=ypos/iterations;
46   
47           
48     }
49 }

Timer类的重绘设置:

show sourceview source print?
01 varball:Ball=newBall();
02 varvx:Number=5;
03 vartimer=newTimer(20);
04   
05 stage.frameRate=1;//设置flash动画的帧数为1帧/秒
06   
07 ball.y=stage.stageHeight/2;
08 ball.vx=5;
09 addChild(ball);
10   
11 timer.addEventListener(TimerEvent.TIMER,TimerHandler);
12   
13 functionTimerHandler(e:TimerEvent):void{
14     ball.x+=ball.vx;
15     if(ball.x>stage.stageWidth+ball.width/2){
16         ball.x=-ball.width/2;
17     }
18     e.updateAfterEvent();//事件触发后,重绘整个stage(建议大家去掉这一行,再看看效果)
19 }
20   
21 timer.start();

注意:timer类的计时并不象c#中那样精确,因为跟帧速有关联。

 

基于时间的动画:

Flash动画是基于帧的(即每进入一帧时,舞台上的对象才会重绘,并触发Enter_Frame事件),这跟Silverlight是基于时间的设计完全不同。一般情况下,这也不是什么问题,但是这样会在不同配置的机器上可能产生不一致的播放效果,比如“一个简单的小球从左运动到右”的简单动画,如果在ENTER_FRAME事件中,用ball.x+=ball.vx来处理,在老爷机上,可能swf动画只能达到每秒10帧的播放速度,而在4核的高配置机器上,能达到每秒100帧的播放速度。 问题就来了:假如ball.vx为5,则在老爷机上,小球最终每秒移动了5*10=50像素,而在高配置机器上,小球每秒移动了5*100=500像素,这与开发者期望的并不一样,下面的代码演示了如何制作基于时间的动画,最终让小球在不同配置的机器上运动速度达到一致。(注:在这一点上,不得不承认Silverlight的设计要优于Flash)

show sourceview source print?
01 varball:Ball=newBall();
02 varvx:Number=5;
03   
04 stage.frameRate=100;//通常在基于时间的动画中,帧数可以设置得高一点(尽管机器最终可能达不到这个帧数.)
05   
06 ball.y=stage.stageHeight/2;
07 ball.vx=10;
08 addChild(ball);
09   
10 vartimer=getTimer();
11   
12 addEventListener(Event.ENTER_FRAME,enterFrameHandler);
13   
14 functionenterFrameHandler(e:Event):void{
15     varelapsed:Number=getTimer()-timer;//计算每帧之间间隔的时间差(以毫秒为单位)
16       
17     ball.x+=(ball.vx*elapsed/1000);//将毫秒换算成秒,再乘“速度”,最终的效果即:如果帧数低,动画播放得太慢,则一次多移动一些距离;反之则少移动一些距离,起到了动态调整的目的.
18     if(ball.x>stage.stageWidth+ball.width/2){
19         ball.x=-ball.width/2;
20     }   
21       
22     timer=getTimer();
23 }

大家可以尝试把上面的帧数设置,改成200或50,然后再测试下播放效果,会发现小球的移动速度是一致的,不受帧数的影响。(但帧数建议不要低于10,因为人眼的视觉暂留极限大概是0.1秒,低于这个值动画看起来会很卡)

另外,这里对比给出Silverlight的对比代码:

 

show sourceview source print?
01 usingSystem;
02 usingSystem.Windows;
03 usingSystem.Windows.Controls;
04 usingSystem.Windows.Interop;
05 usingSystem.Windows.Threading;
06   
07 namespaceSilverlightApplication1
08 {
09 publicpartialclassMainPage:UserControl
10 {
11 DispatcherTimertmr;
12 Ballb;
13   
14 publicMainPage()
15 {
16 InitializeComponent();
17 this.Loaded+=newRoutedEventHandler(MainPage_Loaded);
18 }
19   
20 voidMainPage_Loaded(objectsender,RoutedEventArgse)
21 {
22 Settingssettings=Application.Current.Host.Settings;
23 settings.EnableFrameRateCounter=true;
24 settings.MaxFrameRate=1;
25   
26 b=newBall();//ball是一个自定义控件,里面就一个圆
27 c.Children.Add(b);
28 b.SetValue(Canvas.LeftProperty,c.Width/2);
29 b.SetValue(Canvas.TopProperty,c.Height/2);
30   
31 tmr=newDispatcherTimer();
32 tmr.Interval=newTimeSpan(0,0,0,0,20);
33 tmr.Tick+=newEventHandler(tmr_Tick);
34 tmr.Start();
35 }
36   
37 voidtmr_Tick(objectsender,EventArgse)
38 {
39 double_left=(double)b.GetValue(Canvas.LeftProperty);
40 b.SetValue(Canvas.LeftProperty,_left+5);
41 }
42 }
43 }

 

相同质量的小球碰撞:

Flash/Flex学习笔记(43):动量守恒与能量守恒 里,我们学习了如何用AS3.0来模拟小球的运量守恒,但计算也是很复杂的,对于相同质量的碰撞,其实可以实现得更简单一些。基本原理是,两个物体沿着碰撞的线路交换它们的速度(想深究的同学们,可以自己去解方程验证)。这样我们在处理这种特殊情况时,就可以简化一部分计算,完整代码如下:(注意加★的部分)

show sourceview source print?
001 package{
002   
003     importflash.display.Sprite;
004     importflash.events.Event;
005     importflash.geom.Point;
006   
007     publicclassSameMassextendsSprite{
008   
009         privatevarballs:Array;
010         privatevarnumBalls:uint=8;
011         privatevarbounce:Number=-1.0;
012   
013         publicfunctionSameMass(){
014             init();
015         }
016   
017         privatefunctioninit():void{
018             balls=newArray();
019             for(vari:uint=0;i<numBalls;i++){
020                 //varradius:Number=Math.random()*40+10;
021                 varradius:Number=20;//★★★★★把所有质量强制为相同
022                 varball:Ball=newBall(radius,Math.random()*0xffffff);
023                 ball.mass=radius;
024                 ball.x=i*100;
025                 ball.y=i*50;
026                 ball.vx=Math.random()*10-5;
027                 ball.vy=Math.random()*10-5;
028                 addChild(ball);
029                 balls.push(ball);
030             }
031             addEventListener(Event.ENTER_FRAME,onEnterFrame);
032         }
033   
034         privatefunctiononEnterFrame(event:Event):void{
035             for(vari:uint=0;i<numBalls;i++){
036                 varball:Ball=balls[i];
037                 ball.x+=ball.vx;
038                 ball.y+=ball.vy;
039                 checkWalls(ball);
040             }
041   
042             for(i=0;i<numBalls-1;i++){
043                 varballA:Ball=balls[i];
044                 for(varj:Number=i+1;j<numBalls;j++){
045                     varballB:Ball=balls[j];
046                     checkCollision(ballA,ballB);
047                 }
048             }
049         }
050   
051   
052         //舞台边界检测
053         functioncheckWalls(b:Ball){
054             if(b.x<b.radius){
055                 b.x=b.radius;
056                 b.vx*=bounce;
057             }
058             elseif(b.x>stage.stageWidth-b.radius){
059                 b.x=stage.stageWidth-b.radius;
060                 b.vx*=bounce;
061             }
062             if(b.y<b.radius){
063                 b.y=b.radius;
064                 b.vy*=bounce;
065             }
066             elseif(b.y>stage.stageHeight-b.radius){
067                 b.y=stage.stageHeight-b.radius;
068                 b.vy*=bounce;
069             }
070         }
071   
072         privatefunctionrotate(x:Number,y:Number,sin:Number,cos:Number,reverse:Boolean):Point{
073             varresult:Point=newPoint();
074             if(reverse){
075                 result.x=x*cos+y*sin;
076                 result.y=y*cos-x*sin;
077             }
078             else{
079                 result.x=x*cos-y*sin;
080                 result.y=y*cos+x*sin;
081             }
082             returnresult;
083         }
084   
085         privatefunctioncheckCollision(ball0:Ball,ball1:Ball):void{
086             vardx:Number=ball1.x-ball0.x;
087             vardy:Number=ball1.y-ball0.y;
088             vardist:Number=Math.sqrt(dx*dx+dy*dy);
089             if(dist<ball0.radius+ball1.radius){
090                 //计算角度和正余弦值
091                 varangle:Number=Math.atan2(dy,dx);
092                 varsin:Number=Math.sin(angle);
093                 varcos:Number=Math.cos(angle);
094                 //旋转ball0的位置
095                 varpos0:Point=newPoint(0,0);
096                 //旋转ball1的速度
097                 varpos1:Point=rotate(dx,dy,sin,cos,true);
098                 //旋转ball0的速度
099                 varvel0:Point=rotate(ball0.vx,ball0.vy,sin,cos,true);
100                 //旋转ball1的速度
101                 varvel1:Point=rotate(ball1.vx,ball1.vy,sin,cos,true);
102                 /*//碰撞的作用力
103                 varvxTotal:Number=vel0.x-vel1.x;
104                 vel0.x=((ball0.mass-ball1.mass)*vel0.x+2*ball1.mass*vel1.x)/(ball0.mass+ball1.mass);
105                 vel1.x=vxTotal+vel0.x;*/
106                 //★★★★★改成速度交换★★★★★
107                 vartemp:Point=vel0;
108                 vel0=vel1;
109                 vel1=temp;
110                   
111                 //更新位置
112                 varabsV:Number=Math.abs(vel0.x)+Math.abs(vel1.x);
113                 varoverlap:Number=(ball0.radius+ball1.radius)-Math.abs(pos0.x-pos1.x);
114                 pos0.x+=vel0.x/absV*overlap;
115                 pos1.x+=vel1.x/absV*overlap;
116                 //将位置旋转回来
117                 varpos0F:Object=rotate(pos0.x,pos0.y,sin,cos,false);
118                 varpos1F:Object=rotate(pos1.x,pos1.y,sin,cos,false);
119                 //将位置调整为屏幕的实际位置
120                 ball1.x=ball0.x+pos1F.x;
121                 ball1.y=ball0.y+pos1F.y;
122                 ball0.x=ball0.x+pos0F.x;
123                 ball0.y=ball0.y+pos0F.y;
124                 //将速度旋转回来
125                 varvel0F:Object=rotate(vel0.x,vel0.y,sin,cos,false);
126                 varvel1F:Object=rotate(vel1.x,vel1.y,sin,cos,false);
127                 ball0.vx=vel0F.x;
128                 ball0.vy=vel0F.y;
129                 ball1.vx=vel1F.x;
130                 ball1.vy=vel1F.y;
131             }
132         }
133     }
134 }

声音的使用:

声音的使用其实没什么特别的,跟图片,视频等其它资源都差不多.

如上图,在导入一个声音时,可以指定一个类名,然后在代码中,就可以new一个该类的实例了。除此之外,还可以直接加载远程声音,完整代码如下:

show sourceview source print?
01 varbgMusic=newSound(newURLRequest("http://210.51.38.234/music/sophie_zelmani_Going_Home.mp3"));
02 varstf:SoundTransform=newSoundTransform();
03 stf.volume=0.3;
04 bgMusic.play(0,0,stf);
05   
06 varbing:Bing=newBing();
07 varball:Ball=newBall(30);
08 ball.vx=5;
09 ball.vy=5;
10 ball.x=stage.stageWidth/2;
11 ball.y=stage.stageHeight/2;
12 addChild(ball);
13   
14 addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
15   
16 functionEnterFrameHandler(e:Event):void{
17     ball.x+=ball.vx;
18     ball.y+=ball.vy;
19   
20     if(ball.x>=stage.stageWidth-ball.radius){
21         ball.x=stage.stageWidth-ball.radius;
22         ball.vx*=-1;
23         bing.play();
24     }
25     elseif(ball.x<=ball.radius){
26         ball.x=ball.radius;
27         ball.vx*=-1;
28         bing.play();
29     }
30   
31     if(ball.y>=stage.stageHeight-ball.radius){
32         ball.y=stage.stageHeight-ball.radius;
33         ball.vy*=-1;
34         bing.play();
35     }
36     elseif(ball.y<=ball.radius){
37         ball.y=ball.radius;
38         ball.vy*=-1;
39         bing.play();
40     }
41 }

AnimationinActionScript3.0/MakingThingsMove!一书终于全部啃完了,感谢作者“KeithPeters”大师写出这么好的书,感谢[FL基理文]历时4个月的用心翻译!强烈推荐给想研究Silverlight/Flash动画的朋友们,里面的很多思想和处理方法都是动画编程通用的,并不局限于某一种特定的语言!“师傅领进门,修行在各人”,以后在动画编程的道路上能走多远,就只能看自己的造化了。

相关阅读 更多 +
排行榜 更多 +
枪炮战场真实模拟手游 v2024.11.167 安卓版

枪炮战场真实模拟手游 v2024.11.167 安卓版

飞行射击 下载
枪炮战场真实模拟手游 v2024.11.167 安卓版

枪炮战场真实模拟手游 v2024.11.167 安卓版

飞行射击 下载
枪炮战场真实模拟手游 v2024.11.167 安卓版

枪炮战场真实模拟手游 v2024.11.167 安卓版

飞行射击 下载