zoukankan      html  css  js  c++  java
  • Flash/Flex学习笔记(57):实用技巧

    布朗运动:

    varnumDots:uint=50;
    varfriction:Number=0.9;
    vardots:Array;
    varlife:uint=0;
    
    functioninit(){
    	graphics.lineStyle(0,0xffffff,.5);
    	dots=newArray();
    	for(vari:uint=0;i<numDots;i++){
    		vardot:Ball=newBall(2,0x00ff00);
    		dot.x=Math.random()*stage.stageWidth;
    		dot.y=Math.random()*stage.stageHeight;
    		dot.vx=0;
    		dot.vy=0;
    		dots.push(dot);
    		addChild(dot);
    		checkBound(dot);
    	}
    	addEventListener(Event.ENTER_FRAME,enterFrameHandler);
    }
    
    //检查边界
    functioncheckBound(b:Ball){
    	if(b.x<b.width/2){
    		b.x=b.width/2;
    	}
    	elseif(b.x>stage.stageWidth-b.width/2){
    		b.x=stage.stageWidth-b.width/2;
    	}
    	if(b.y<b.height/2){
    		b.y=b.height/2;
    	}
    	elseif(b.y>stage.stageHeight-b.height/2){
    		b.y=stage.stageHeight-b.height/2;
    	}
    }
    
    functionenterFrameHandler(e:Event):void{
    	//trace(life);
    	if(life>=200){
    		graphics.clear();
    		graphics.lineStyle(0,0xffffff,.5);
    		life=0;
    	}
    	for(vari:uint=0;i<numDots;i++){
    		vardot:Ball=dots[i];
    		graphics.moveTo(dot.x,dot.y);
    		dot.vx+=Math.random()-0.5;
    		dot.vy+=Math.random()-0.5;
    		dot.x+=dot.vx;
    		dot.y+=dot.vy;
    		dot.vx*=friction;
    		dot.vy*=friction;
    		checkBound(dot);
    		graphics.lineTo(dot.x,dot.y);
    	}
    	life++;
    }
    
    init();
    

    矩形分布:

    vardotNumber:uint=500;
    vardots:Array;
    varcenterX:uint=stage.stageWidth/2;
    varcenterY:uint=stage.stageHeight/2;
    varlimitX:uint=50;
    varlimitY:uint=100;
    
    functioninit():void{
    	dots=newArray();	
    	for(vari:uint=0;i<dotNumber;i++){
    		vardot:Ball=newBall(3*Math.random(),0x00ff00);
    		dot.x=centerX+(Math.random()*2-1)*limitX;
    		dot.y=centerY+(Math.random()*2-1)*limitY;
    		addChild(dot);		
    		dots.push(dot);
    	}
    	addEventListener(Event.ENTER_FRAME,enterframeHandler);
    }
    
    functionenterframeHandler(e:Event):void{
    	for(vari:uint=0;i<dotNumber;i++){
    		vardot:Ball=dots[i];
    		dot.x=centerX+(Math.random()*2-1)*limitX;
    		dot.y=centerY+(Math.random()*2-1)*limitY;		
    		/*varix:Number=dot.x;
    		variy:Number=dot.y;
    		dot.y=ix;
    		dot.x=iy*/
    	}
    }
    
    init();
    

    圆形随机分布:

    vardotNumber:uint=500;
    vardots:Array;
    varcenterX:uint=stage.stageWidth/2;
    varcenterY:uint=stage.stageHeight/2;
    varradius:uint=75;
    
    functioninit():void{
    	dots=newArray();
    	for(vari:uint=0;i<dotNumber;i++){
    		vardot:Ball=newBall(3*Math.random(),0x00ff00);
    		varangle:Number=2*Math.random()*Math.PI;
    		varr:Number=Math.random()*radius;
    		dot.x=centerX+r*Math.cos(angle);
    		dot.y=centerY+r*Math.sin(angle);
    		addChild(dot);
    		dots.push(dot);
    	}
    	addEventListener(Event.ENTER_FRAME,enterframeHandler);
    }
    
    functionenterframeHandler(e:Event):void{
    	for(vari:uint=0;i<dotNumber;i++){
    		vardot:Ball=dots[i];
    		varangle:Number=2*Math.random()*Math.PI;
    		varr:Number=Math.random()*radius;
    		dot.x=centerX+r*Math.cos(angle);
    		dot.y=centerY+r*Math.sin(angle);
    	}
    }
    
    init();
    

    更均匀的圆形随机分布:

    vardotNumber:uint=200;
    
    varcenterX:uint=stage.stageWidth/2;
    varcenterY:uint=100;
    varradius:uint=50;
    
    functioninit():void{
    	
    	for(vari:uint=0;i<dotNumber;i++){
    		vardot:Ball=newBall(2,0x00ff00);
    		varangle:Number=2*Math.random()*Math.PI;		
    		varr:Number=Math.random()*radius;
    		dot.x=centerX+r*Math.cos(angle);
    		dot.y=centerY+r*Math.sin(angle);
    		addChild(dot);
    		
    	}
    	
    	//更均匀的随机分布
    	for(i=0;i<dotNumber;i++){
    		vardot1:Ball=newBall(2,0x00ff00);
    		varangle1:Number=2*Math.random()*Math.PI;
    		varr1:Number=Math.sqrt(Math.random())*radius;//关键在这里,对Math.random()取平方根后,分布变得更均匀了
    		dot1.x=centerX+r1*Math.cos(angle1);
    		dot1.y=centerY+200+r1*Math.sin(angle1);
    		addChild(dot1);
    		
    	}
    	
    }
    
    
    init();
    

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

    vardotNumber:uint=600;
    varcenterX:uint=stage.stageWidth/2;
    varmaxWidth:uint=75;
    varballs:Array=newArray();
    
    functioninit():void{
    
    	for(vari:uint=0;i<dotNumber;i++){
    		vardot:Ball=newBall(2,0x00ff00);
    
    		//在y轴方向上随便取二个值,然后计算平均值做为y坐标
    		vary1=stage.stageHeight*Math.random();
    		vary2=stage.stageHeight*Math.random();
    
    		varty=(y1+y2)/2;
    
    		//x轴做类似的处理
    		varx1=centerX+(Math.random()*2-1)*maxWidth;
    		varx2=centerX+(Math.random()*2-1)*maxWidth;
    
    		vartx=(x1+x2)/2;
    
    
    		dot.x=tx;
    		dot.y=ty;
    
    		addChild(dot);
    
    		balls.push(dot);
    	}
    	stage.frameRate=1;
    	addEventListener(Event.ENTER_FRAME,enterFrameHandler);
    }
    
    init();
    
    
    functionenterFrameHandler(e:Event){
    	for(vari:uint=0;i<dotNumber;i++){
    		vardot:Ball=balls[i];
    
    
    		vary1=stage.stageHeight*Math.random();
    		vary2=stage.stageHeight*Math.random();
    
    		varty=(y1+y2)/2;
    
    
    		varx1=centerX+(Math.random()*2-1)*maxWidth;
    		varx2=centerX+(Math.random()*2-1)*maxWidth;
    
    		vartx=(x1+x2)/2;
    
    
    		dot.x=tx;
    		dot.y=ty;
    
    
    	}
    }
    

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

    vardotNumber:uint=100;
    variterations:uint=6;
    varballs:Array=newArray();
    
    functioninit():void{
    
    	for(vari:uint=0;i<dotNumber;i++){
    		vardot:Ball=newBall(2,0x00ff00);
    
    		varxpos:Number=0;
    		varypos:Number=0;
    		for(varj:uint=0;j<iterations;j++){
    			xpos+=stage.stageWidth*Math.random();
    			ypos+=stage.stageHeight*Math.random();
    		}
    
    		dot.x=xpos/iterations;
    		dot.y=ypos/iterations;
    		
    		addChild(dot);
    		
    		balls.push(dot);
    	}
    	
    	stage.frameRate=1;
    	addEventListener(Event.ENTER_FRAME,enterFrameHandler);
    }
    
    init();
    
    
    functionenterFrameHandler(e:Event){
    	for(vari:uint=0;i<dotNumber;i++){
    		vardot:Ball=balls[i];
    	
    		
    		varxpos:Number=0;
    		varypos:Number=0;
    		for(varj:uint=0;j<iterations;j++){
    			xpos+=stage.stageWidth*Math.random();
    			ypos+=stage.stageHeight*Math.random();
    		}
    
    		dot.x=xpos/iterations;
    		dot.y=ypos/iterations;
    
    		
    	}
    }
    

    Timer类的重绘设置:

    varball:Ball=newBall();
    varvx:Number=5;
    vartimer=newTimer(20);
    
    stage.frameRate=1;//设置flash动画的帧数为1帧/秒
    
    ball.y=stage.stageHeight/2;
    ball.vx=5;
    addChild(ball);
    
    timer.addEventListener(TimerEvent.TIMER,TimerHandler);
    
    functionTimerHandler(e:TimerEvent):void{
    	ball.x+=ball.vx;
    	if(ball.x>stage.stageWidth+ball.width/2){
    		ball.x=-ball.width/2;
    	}
    	e.updateAfterEvent();//事件触发后,重绘整个stage(建议大家去掉这一行,再看看效果)
    }
    
    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)

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

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

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

    usingSystem;
    usingSystem.Windows;
    usingSystem.Windows.Controls;
    usingSystem.Windows.Interop;
    usingSystem.Windows.Threading;
    
    namespaceSilverlightApplication1
    {
    publicpartialclassMainPage:UserControl
    {
    DispatcherTimertmr;
    Ballb;
    
    publicMainPage()
    {
    InitializeComponent();
    this.Loaded+=newRoutedEventHandler(MainPage_Loaded);
    }
    
    voidMainPage_Loaded(objectsender,RoutedEventArgse)
    {
    Settingssettings=Application.Current.Host.Settings;
    settings.EnableFrameRateCounter=true;
    settings.MaxFrameRate=1;
    
    b=newBall();//ball是一个自定义控件,里面就一个圆
    c.Children.Add(b);
    b.SetValue(Canvas.LeftProperty,c.Width/2);
    b.SetValue(Canvas.TopProperty,c.Height/2);
    
    tmr=newDispatcherTimer();
    tmr.Interval=newTimeSpan(0,0,0,0,20);
    tmr.Tick+=newEventHandler(tmr_Tick);
    tmr.Start();
    }
    
    voidtmr_Tick(objectsender,EventArgse)
    {
    double_left=(double)b.GetValue(Canvas.LeftProperty);
    b.SetValue(Canvas.LeftProperty,_left+5);
    }
    }
    }
    
    

    相同质量的小球碰撞:

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

    package{
    
    	importflash.display.Sprite;
    	importflash.events.Event;
    	importflash.geom.Point;
    
    	publicclassSameMassextendsSprite{
    
    		privatevarballs:Array;
    		privatevarnumBalls:uint=8;
    		privatevarbounce:Number=-1.0;
    
    		publicfunctionSameMass(){
    			init();
    		}
    
    		privatefunctioninit():void{
    			balls=newArray();
    			for(vari:uint=0;i<numBalls;i++){
    				//varradius:Number=Math.random()*40+10;
    				varradius:Number=20;//★★★★★把所有质量强制为相同
    				varball:Ball=newBall(radius,Math.random()*0xffffff);
    				ball.mass=radius;
    				ball.x=i*100;
    				ball.y=i*50;
    				ball.vx=Math.random()*10-5;
    				ball.vy=Math.random()*10-5;
    				addChild(ball);
    				balls.push(ball);
    			}
    			addEventListener(Event.ENTER_FRAME,onEnterFrame);
    		}
    
    		privatefunctiononEnterFrame(event:Event):void{
    			for(vari:uint=0;i<numBalls;i++){
    				varball:Ball=balls[i];
    				ball.x+=ball.vx;
    				ball.y+=ball.vy;
    				checkWalls(ball);
    			}
    
    			for(i=0;i<numBalls-1;i++){
    				varballA:Ball=balls[i];
    				for(varj:Number=i+1;j<numBalls;j++){
    					varballB:Ball=balls[j];
    					checkCollision(ballA,ballB);
    				}
    			}
    		}
    
    
    		//舞台边界检测
    		functioncheckWalls(b:Ball){
    			if(b.x<b.radius){
    				b.x=b.radius;
    				b.vx*=bounce;
    			}
    			elseif(b.x>stage.stageWidth-b.radius){
    				b.x=stage.stageWidth-b.radius;
    				b.vx*=bounce;
    			}
    			if(b.y<b.radius){
    				b.y=b.radius;
    				b.vy*=bounce;
    			}
    			elseif(b.y>stage.stageHeight-b.radius){
    				b.y=stage.stageHeight-b.radius;
    				b.vy*=bounce;
    			}
    		}
    
    		privatefunctionrotate(x:Number,y:Number,sin:Number,cos:Number,reverse:Boolean):Point{
    			varresult:Point=newPoint();
    			if(reverse){
    				result.x=x*cos+y*sin;
    				result.y=y*cos-x*sin;
    			}
    			else{
    				result.x=x*cos-y*sin;
    				result.y=y*cos+x*sin;
    			}
    			returnresult;
    		}
    
    		privatefunctioncheckCollision(ball0:Ball,ball1:Ball):void{
    			vardx:Number=ball1.x-ball0.x;
    			vardy:Number=ball1.y-ball0.y;
    			vardist:Number=Math.sqrt(dx*dx+dy*dy);
    			if(dist<ball0.radius+ball1.radius){
    				//计算角度和正余弦值
    				varangle:Number=Math.atan2(dy,dx);
    				varsin:Number=Math.sin(angle);
    				varcos:Number=Math.cos(angle);
    				//旋转ball0的位置
    				varpos0:Point=newPoint(0,0);
    				//旋转ball1的速度
    				varpos1:Point=rotate(dx,dy,sin,cos,true);
    				//旋转ball0的速度
    				varvel0:Point=rotate(ball0.vx,ball0.vy,sin,cos,true);
    				//旋转ball1的速度
    				varvel1:Point=rotate(ball1.vx,ball1.vy,sin,cos,true);
    				/*//碰撞的作用力
    				varvxTotal:Number=vel0.x-vel1.x;
    				vel0.x=((ball0.mass-ball1.mass)*vel0.x+2*ball1.mass*vel1.x)/(ball0.mass+ball1.mass);
    				vel1.x=vxTotal+vel0.x;*/
    				//★★★★★改成速度交换★★★★★
    				vartemp:Point=vel0;
    				vel0=vel1;
    				vel1=temp;
    				
    				//更新位置
    				varabsV:Number=Math.abs(vel0.x)+Math.abs(vel1.x);
    				varoverlap:Number=(ball0.radius+ball1.radius)-Math.abs(pos0.x-pos1.x);
    				pos0.x+=vel0.x/absV*overlap;
    				pos1.x+=vel1.x/absV*overlap;
    				//将位置旋转回来
    				varpos0F:Object=rotate(pos0.x,pos0.y,sin,cos,false);
    				varpos1F:Object=rotate(pos1.x,pos1.y,sin,cos,false);
    				//将位置调整为屏幕的实际位置
    				ball1.x=ball0.x+pos1F.x;
    				ball1.y=ball0.y+pos1F.y;
    				ball0.x=ball0.x+pos0F.x;
    				ball0.y=ball0.y+pos0F.y;
    				//将速度旋转回来
    				varvel0F:Object=rotate(vel0.x,vel0.y,sin,cos,false);
    				varvel1F:Object=rotate(vel1.x,vel1.y,sin,cos,false);
    				ball0.vx=vel0F.x;
    				ball0.vy=vel0F.y;
    				ball1.vx=vel1F.x;
    				ball1.vy=vel1F.y;
    			}
    		}
    	}
    }
    

    声音的使用:

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

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

    varbgMusic=newSound(newURLRequest("http://210.51.38.234/music/sophie_zelmani_Going_Home.mp3"));
    varstf:SoundTransform=newSoundTransform();
    stf.volume=0.3;
    bgMusic.play(0,0,stf);
    
    varbing:Bing=newBing();
    varball:Ball=newBall(30);
    ball.vx=5;
    ball.vy=5;
    ball.x=stage.stageWidth/2;
    ball.y=stage.stageHeight/2;
    addChild(ball);
    
    addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
    
    functionEnterFrameHandler(e:Event):void{
    	ball.x+=ball.vx;
    	ball.y+=ball.vy;
    
    	if(ball.x>=stage.stageWidth-ball.radius){
    		ball.x=stage.stageWidth-ball.radius;
    		ball.vx*=-1;
    		bing.play();
    	}
    	elseif(ball.x<=ball.radius){
    		ball.x=ball.radius;
    		ball.vx*=-1;
    		bing.play();
    	}
    
    	if(ball.y>=stage.stageHeight-ball.radius){
    		ball.y=stage.stageHeight-ball.radius;
    		ball.vy*=-1;
    		bing.play();
    	}
    	elseif(ball.y<=ball.radius){
    		ball.y=ball.radius;
    		ball.vy*=-1;
    		bing.play();
    	}
    }
    

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

    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    codeforces 455B A Lot of Games(博弈,字典树)
    HDU 4825 Xor Sum(二进制的字典树,数组模拟)
    hdu 1800 Flying to the Mars(简单模拟,string,字符串)
    codeforces 425A Sereja and Swaps(模拟,vector,枚举区间)
    codeforces 425B Sereja and Table(状态压缩,也可以数组模拟)
    HDU 4148 Length of S(n)(字符串)
    codeforces 439D Devu and Partitioning of the Array(有深度的模拟)
    浅谈sass
    京东楼层案例思维逻辑分析
    浅谈localStorage和sessionStorage
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/1756400.html
Copyright © 2011-2022 走看看