一些算法
2010-04-23 09:48 宝宝合凤凰 阅读(478) 评论(0) 收藏 举报小球随机运动
帧循环(EnterFrame)

1 //Save as BallMove.as
2 package
3 {
4 import flash.display.Sprite;
5 import flash.events.Event;
6
7 public class BallMove extends Sprite
8 {
9 private var ball:Sprite;
10
11 public function BallMove ()
12 {
13 Init ();
14 }
15 public function Init ():void
16 {
17 ball=new Sprite();
18 addChild (ball);
19
20 ball.graphics.beginFill (0xffff00);
21 ball.graphics.drawCircle (0,0,5);
22 ball.graphics.endFill ();
23
24 ball.x=stage.stageWidth/2;
25 ball.y=stage.stageHeight/2;
26
27 ball.addEventListener (Event.ENTER_FRAME,Ball_EnterFrame);
28 }
29 private function Ball_EnterFrame (e:Event):void
30 {
31 ball.x+=(15-30*Math.random());
32 ball.y+=(15-30*Math.random());
33 }
34 }
35 }
角度转向-鼠标跟随
1,构建精灵

 package
package  {
{ import flash.display.Sprite;
    import flash.display.Sprite; public class Arrow extends Sprite
    public class Arrow extends Sprite {
    { public function Arrow()
        public function Arrow() {
        { init();
            init(); }
        } public function init():void
        public function init():void {
        { graphics.lineStyle(1,0,1);
            graphics.lineStyle(1,0,1); graphics.beginFill(0xffff00);
            graphics.beginFill(0xffff00); graphics.moveTo(-50,-25);
            graphics.moveTo(-50,-25); graphics.lineTo(0,-25);
            graphics.lineTo(0,-25); graphics.lineTo(0,-50);
            graphics.lineTo(0,-50); graphics.lineTo(50,0);
            graphics.lineTo(50,0); graphics.lineTo(0,50);
            graphics.lineTo(0,50); graphics.lineTo(0,25);
            graphics.lineTo(0,25); graphics.lineTo(-50,25);
            graphics.lineTo(-50,25); graphics.lineTo(-50,-25);
            graphics.lineTo(-50,-25); graphics.endFill();
            graphics.endFill(); }
        } }
    } }
}
2,跟随动画

package
{
import flash.events.Event;
import flash.display.Sprite;
public class FollowMouse extends Sprite
{
private var myArrow:Arrow;
public function FollowMouse ()
{
Init ();
}
private function Init ():void
{
myArrow=new Arrow() ;
addChild (myArrow);
myArrow.scaleX=0.5;
myArrow.scaleY=0.3;
myArrow.x=stage.stageWidth / 2;
myArrow.y=stage.stageHeight / 2;
myArrow.addEventListener (Event.ENTER_FRAME,Active);
}
private function Active (e:Event):void
{
var vx:Number=0;
var vy:Number=0;
var ax:Number=(mouseX - myArrow.x)/5;
var ay:Number=(mouseY - myArrow.y)/5;
vx+= ax;
vy+= ay;
myArrow.x+= vx;
myArrow.y+= vy;
var angle:Number=Math.atan2(ay,ax);
myArrow.rotation=angle*180/Math.PI;
}
}
}
模拟喷泉粒子
1.用ball构建单个粒子

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public var vx:Number=0;
public var vy:Number=0;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}
2.构建喷泉粒子发射

package
{
import flash.events.Event;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
public class Fountain extends Sprite
{
private var count:int=300;
private var gravity:Number=0.5;
private var balls:Array;
public function Fountain ()
{
Init ();
}
public function Init ():void
{
stage.scaleMode=StageScaleMode.NO_SCALE;
stage.align=StageAlign.TOP_LEFT;
balls=new Array();
for (var i:int=0; i<count; i++)
{
var ball:Ball=new Ball(2,Math.random() * 0xffffff);
InitPosition(ball);
InitSpeed (ball);
addChild (ball);
balls.push (ball);
}
addEventListener (Event.ENTER_FRAME,Active);
}
private function Active (e:Event):void
{
for (var i:int =0; i<balls.length; i++)
{
var ball:Ball=Ball(balls[i]);//var ball:Ball=balls[i];也可以
ball.vy+=gravity;
ball.x+=ball.vx;
ball.y+=ball.vy;
//边界再生
if (ball.x-ball.radius>stage.stageWidth ||
ball.x+ball.radius<0 ||
ball.y-ball.radius>stage.stageHeight ||
ball.y+ball.radius<0)
{
InitPosition(ball);
InitSpeed (ball);
}
}
}
private function InitPosition(ball:Ball):void
{
ball.x=stage.stageWidth/2;
ball.y=stage.stageHeight;
}
private function InitSpeed (ball:Ball):void
{
ball.vx=Math.random() *6-3;
ball.vy=(-10)*Math.random() -10;
}
}
}
小球回弹模拟
1.构建小球

package 
{
    import flash.display.Sprite;
    public class Ball extends Sprite
    {
        public var radius:Number;
        public var color:uint;
        public function Ball (radius:Number,color:uint)
        {
            this.radius=radius;
            this.color=color;
            Init ();
        }
        public function Init ():void
        {
            graphics.beginFill (color);
            graphics.drawCircle (0,0,radius);
            graphics.endFill ();
        }
    }
}
2.构建回弹动画

package
{
import flash.events.Event;
import flash.display.Sprite;
import flash.display.StageScaleMode;
import flash.display.StageAlign;
public class Bouncing extends Sprite
{
private var ball:Ball;
private var vx:Number;
private var vy:Number;
private var radius:Number=20;
public function Bouncing ()
{
Init ();
}
public function Init ():void
{
stage.scaleMode=StageScaleMode.NO_SCALE;
stage.align=StageAlign.TOP_LEFT;
ball=new Ball(radius,0xff0000);
ball.x=stage.stageWidth/2;
ball.y=stage.stageHeight/2;
vx=20*Math.random()-10;
vy=20*Math.random()-10;
addChild (ball);
addEventListener (Event.ENTER_FRAME,Active);
}
private function Active (e:Event):void
{
ball.x+=vx;
ball.y+=vy;
if (ball.x<radius)
{
ball.x=radius;
vx*=-1;
}
if (ball.x>stage.stageWidth-radius)
{
ball.x=stage.stageWidth-radius;
vx*=-1;
}
if (ball.y<radius)
{
ball.y=radius;
vy*=-1;
}
if (ball.y>stage.stageHeight-radius)
{
ball.y=stage.stageHeight-radius;
vy*=-1;
}
}
}
}
摩擦力模拟
1.构建小球

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
private var _radius:Number;
private var _color:uint;
public function Ball (radius:Number,color:uint)
{
_radius=radius;
_color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (_color);
graphics.drawCircle (0,0,_radius);
graphics.endFill ();
}
}
}
2.构建动画

package
{
import flash.events.Event;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
public class Friction extends Sprite
{
private var vx:Number;
private var vy:Number;
private var friction:Number;
private var ball:Ball;
private var speed:Number;
private var angle:Number;
public function Friction ()
{
Init ();
}
private function Init ():void
{
stage.scaleMode=StageScaleMode.NO_SCALE;
stage.align=StageAlign.TOP_LEFT;
ball=new Ball(20,0xffff00);
ball.x=stage.stageWidth/2;
ball.y=stage.stageHeight/2;
vx=Math.random()*20-10;
vy=Math.random()*20-10;
friction=0.95;
addChild (ball);
addEventListener (Event.ENTER_FRAME,Active);
}
private function Active (e:Event):void
{
speed=Math.sqrt(vx*vx+vy*vy);
angle=Math.atan2(vy,vx);
speed*=friction;
vx=Math.cos(angle)*speed;
vy=Math.sin(angle)*speed;
ball.x+=vx;
ball.y+=vy;
}
}
}
拖动精灵的三种方法比较
构建Ball精灵:

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}
第一种方法:会出现拖动时突然跳跃,使自身的中心与鼠标的中心对齐。

package
{
import flash.events.MouseEvent;
import flash.display.Sprite;
public class MouseMoveDrag extends Sprite
{
private var ball:Ball;
public function MouseMoveDrag()
{
Init();
}
public function Init():void
{
ball=new Ball(40,0xFFFF00);
ball.x=stage.stageWidth/2;
ball.y=stage.stageHeight/2;
addChild(ball);
ball.addEventListener(MouseEvent.MOUSE_DOWN,MouseDown);
}
public function MouseDown(e:MouseEvent):void
{
stage.addEventListener(MouseEvent.MOUSE_UP,MouseUp);
stage.addEventListener(MouseEvent.MOUSE_MOVE,MouseMove);
}
public function MouseUp(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_UP,MouseUp);
stage.removeEventListener(MouseEvent.MOUSE_MOVE,MouseMove);
}
public function MouseMove(e:MouseEvent):void
{
ball.x=mouseX;
ball.y=mouseY;
}
}
}
第二种方法:完全正确,稍微有点繁琐。

package
{
import flash.events.MouseEvent;
import flash.display.Sprite;
public class MouseMoveDrag extends Sprite
{
private var ball:Ball;
private var dx:Number;
private var dy:Number;
public function MouseMoveDrag()
{
Init();
}
public function Init():void
{
ball=new Ball(40,0xFFFF00);
ball.x=stage.stageWidth/2;
ball.y=stage.stageHeight/2;
addChild(ball);
ball.addEventListener(MouseEvent.MOUSE_DOWN,MouseDown);
}
public function MouseDown(e:MouseEvent):void
{
stage.addEventListener(MouseEvent.MOUSE_UP,MouseUp);
stage.addEventListener(MouseEvent.MOUSE_MOVE,MouseMove);
dx=ball.x-mouseX;
dy=ball.y-mouseY;
}
public function MouseUp(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_UP,MouseUp);
stage.removeEventListener(MouseEvent.MOUSE_MOVE,MouseMove);
}
public function MouseMove(e:MouseEvent):void
{
ball.x=mouseX+dx;
ball.y=mouseY+dy;
}
}
}
第三种方法:简单,但是startDrag()和stopDrag()每次只能拖动一个物体。

package
{
import flash.events.MouseEvent;
import flash.display.Sprite;
public class MouseMoveDrag extends Sprite
{
private var ball:Ball;
public function MouseMoveDrag()
{
Init();
}
public function Init():void
{
ball=new Ball(40,0xFFFF00);
ball.x=stage.stageWidth/2;
ball.y=stage.stageHeight/2;
addChild(ball);
ball.addEventListener(MouseEvent.MOUSE_DOWN,MouseDown);
}
public function MouseDown(e:MouseEvent):void
{
stage.addEventListener(MouseEvent.MOUSE_UP,MouseUp);
ball.startDrag();
}
public function MouseUp(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_UP,MouseUp);
ball.stopDrag();
}
}
}
拖动和运动模拟
1.构建小球精灵

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}
2.构建拖动和运动动画

package
{
import flash.display.Sprite;
import flash.display.StageScaleMode;
import flash.display.StageAlign;
import flash.events.MouseEvent;
import flash.events.Event;
public class DragAndMove extends Sprite
{
private var ball:Ball;
private var vx:Number;
private var vy:Number;
private var bounce:Number=-0.8;
private var gravity:Number=0.9;
public function DragAndMove ()
{
Init ();
}
public function Init ():void
{
stage.scaleMode=StageScaleMode.NO_SCALE;
stage.align=StageAlign.TOP_LEFT;
ball=new Ball(20,0xFFF000);
ball.x=stage.stageWidth/2;
ball.y=stage.stageHeight/2;
vx=Math.random()*20-10;
vy=-20;
addChild (ball);
ball.addEventListener (MouseEvent.MOUSE_DOWN,MouseDown);
addEventListener (Event.ENTER_FRAME,EnterFrame);
}
private function EnterFrame (e:Event):void
{
vy+=gravity;
ball.x+=vx;
ball.y+=vy;
if (ball.x<ball.radius)
{
ball.x=ball.radius;
vx*=bounce;
}
else if (ball.x+ball.radius>stage.stageWidth)
{
ball.x=stage.stageWidth-ball.radius;
vx*=bounce;
}
if (ball.y<ball.radius)
{
ball.y=ball.radius;
vy*=bounce;
}
else if (ball.y+ball.radius>stage.stageHeight)
{
ball.y=stage.stageHeight-ball.radius;
vy*=bounce;
}
}
private function MouseDown (e:MouseEvent):void
{
stage.addEventListener (MouseEvent.MOUSE_UP,MouseUp);
ball.startDrag ();
removeEventListener (Event.ENTER_FRAME,EnterFrame);
}
private function MouseUp (e:MouseEvent):void
{
stage.removeEventListener (MouseEvent.MOUSE_UP,MouseUp);
ball.stopDrag ();
addEventListener (Event.ENTER_FRAME,EnterFrame);
}
}
}
精灵的抛运动

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}
2.构建小球的抛物运动

package
{
import flash.events.MouseEvent;
import flash.events.Event;
import flash.display.Sprite;
import flash.display.StageScaleMode;
import flash.display.StageAlign;
public class Throwing extends Sprite
{
private var ball:Ball;
private var vx:Number;
private var vy:Number;
private var bounce:Number=-0.7;
private var gravity:Number=0.5;
private var oldX:Number;
private var oldY:Number;
public function Throwing ()
{
Init ();
}
public function Init ():void
{
stage.scaleMode=StageScaleMode.NO_SCALE;
stage.align=StageAlign.TOP_LEFT;
ball=new Ball(20,0x00FFF0);
ball.x=stage.stageWidth/2;
ball.y=stage.stageHeight/2;
vx=Math.random()*20-10;
vy=-10;
addChild (ball);
ball.addEventListener (MouseEvent.MOUSE_DOWN,MouseDown);
addEventListener (Event.ENTER_FRAME,EnterFrame);
}
public function EnterFrame (e:Event):void
{
vy+=gravity;
ball.x+=vx;
ball.y+=vy;
if (ball.x<ball.radius)
{
ball.x=ball.radius;
vx*=bounce;
}
else if (ball.x+ball.radius>stage.stageWidth)
{
ball.x=stage.stageWidth-ball.radius;
vx*=bounce;
}
if (ball.y<ball.radius)
{
ball.y=ball.radius;
vy*=bounce;
}
else if (ball.y+ball.radius>stage.stageHeight)
{
ball.y=stage.stageHeight-ball.radius;
vy*=bounce;
}
}
public function MouseDown (e:MouseEvent):void
{
stage.addEventListener (MouseEvent.MOUSE_UP,MouseUp);
removeEventListener (Event.ENTER_FRAME,EnterFrame);
addEventListener (Event.ENTER_FRAME,TrackVelocity);
ball.startDrag ();
oldX=ball.x;
oldY=ball.y;
}
public function MouseUp (e:MouseEvent):void
{
stage.removeEventListener (MouseEvent.MOUSE_UP,MouseUp);
addEventListener (Event.ENTER_FRAME,EnterFrame);
removeEventListener (Event.ENTER_FRAME,TrackVelocity);
ball.stopDrag ();
}
public function TrackVelocity (e:Event):void
{
vx=ball.x-oldX;
vy=ball.y-oldY;
oldX=ball.x;
oldY=ball.y;
}
}
}

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}

package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.Event;
public class Earsing extends Sprite
{
private var ball:Ball;
private var earsing:Number=0.2;
private var targetX:Number=stage.stageWidth/2;
private var targetY:Number=stage.stageHeight/2;
public function Earsing ()
{
Init ();
}
public function Init ():void
{
ball=new Ball(20,0xFF0000);
ball.x=0;
ball.y=0;
addChild (ball);
ball.addEventListener (MouseEvent.MOUSE_DOWN,MouseDown);
addEventListener (Event.ENTER_FRAME,EnterFrame);
}
public function MouseDown (e:MouseEvent):void
{
stage.addEventListener (MouseEvent.MOUSE_UP,MouseUp);
removeEventListener (Event.ENTER_FRAME,EnterFrame);
ball.startDrag ();
}
public function MouseUp (e:MouseEvent):void
{
stage.removeEventListener (MouseEvent.MOUSE_UP,MouseUp);
addEventListener (Event.ENTER_FRAME,EnterFrame);
ball.stopDrag ();
}
public function EnterFrame (e:Event):void
{
var dx:Number=targetX-ball.x;
var dy:Number=targetY-ball.y;
var distance:Number=Math.sqrt(dx*dx+dy*dy);
//停止缓动
if (distance<1)
{
targetX=ball.x;
targetY=ball.y;
removeEventListener (Event.ENTER_FRAME,EnterFrame);
}
else
{
ball.x+=dx*earsing;
ball.y+=dy*earsing;
}
}
}
}
鼠标跟随缓动

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}

package
{
import flash.events.Event;
import flash.display.Sprite;
public class EarseToMouse extends Sprite
{
private var ball:Ball;
private var earsing:Number=0.2;
public function EarseToMouse ()
{
Init ();
}
public function Init ():void
{
ball=new Ball(20,0xFF00FF);
addChild (ball);
addEventListener (Event.ENTER_FRAME,EnterFrame);
}
public function EnterFrame (e:Event):void
{
ball.x+=(mouseX-ball.x)*earsing;
ball.y+=(mouseY-ball.y)*earsing;
}
}
}

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}

package
{
import flash.display.Sprite;
import flash.events.Event;
public class Spring extends Sprite
{
private var ball:Ball;
private var spring:Number=0.1;
private var vx:Number=0;
private var vy:Number=0;
private var friction:Number=0.9;
private var gravity:Number=0.5;
public function Spring ()
{
Init ();
}
public function Init ():void
{
ball=new Ball(20,0xFF00FF);
addChild (ball);
addEventListener (Event.ENTER_FRAME,EnterFrame);
}
private function EnterFrame (e:Event):void
{
var dx:Number=mouseX-ball.x;
var dy:Number=mouseY-ball.y;
var ax:Number=dx*spring;
var ay:Number=dy*spring;
vx+=ax;
vy+=ay;
vy+=gravity;
vx*=friction;
vy*=friction; ball.x+=vx;
ball.y+=vy;
graphics.clear ();
graphics.lineStyle (1);
graphics.moveTo (ball.x,ball.y);
graphics.lineTo (mouseX,mouseY);
}
}
}

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}

package
{
import flash.events.Event;
import flash.display.Sprite;
public class Chain extends Sprite
{
private var balls:Array;
private var numBalls:Number=10;
private var friction:Number=0.8;
private var spring:Number=0.1;
private var gravity:Number=5;
private var vx:Number=stage.stageWidth/2;
private var vy:Number=stage.stageHeight/2;
public function Chain ()
{
Init ();
}
private function Init ():void
{
balls=new Array();
for (var i:int=0; i<numBalls; i++)
{
var ball:Ball=new Ball(20,0xFF0000);
addChild (ball);
balls.push (ball);
}
addEventListener (Event.ENTER_FRAME,EnterFrame);
}
private function EnterFrame (e:Event):void
{
graphics.clear ();
graphics.lineStyle (1);
graphics.moveTo (mouseX,mouseY);
moveBall (balls[0],mouseX,mouseY);
graphics.lineTo (balls[0].x,balls[0].y);
for (var i:int=1; i<numBalls; i++)
{
var ballA:Ball=balls[i-1];
var ballB:Ball=balls[i];
moveBall (ballB,ballA.x,ballA.y);
graphics.lineTo (ballB.x,ballB.y);
}
}
private function moveBall (ball:Ball,targetX:Number,targetY:Number):void
{
vx+=(targetX-ball.x)*spring;
vy+=(targetY-ball.y)*spring;
vy+=gravity;
vx*=friction;
vy*=friction;
ball.x+=vx;
ball.y+=vy;
}
}
}
多目标点弹性模拟

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public var vx:Number=0;
public var vy:Number=0;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}

package
{
import flash.display.Sprite;
public class Rect extends Sprite
{
public function Rect (r_width:Number,r_color:uint)
{
graphics.beginFill (r_color);
graphics.drawRect (0,0,r_width,r_width);
graphics.endFill ();
}
}
}

package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class MultiSpring extends Sprite
{
private var ball:Ball;
private var handles:Array;
private var numHandles:Number=3;
private var friction:Number=0.8;
private var spring:Number=0.2;
private var handleWidth:Number=10;
public function MultiSpring ()
{
Init ();
}
private function Init ():void
{
ball=new Ball(20,0xFF0000);
addChild (ball);
handles=new Array();
for (var i:int=0; i<numHandles; i++)
{
var handle:Rect=new Rect(handleWidth,0xFFFF00);
handle.x=Math.random()*stage.stageWidth;
handle.y=Math.random()*stage.stageHeight;
handle.addEventListener (MouseEvent.MOUSE_DOWN,MouseDown);
addChild (handle);
handles.push (handle);
}
addEventListener (Event.ENTER_FRAME,EnterFrame);
}
private function MouseDown (e:MouseEvent):void
{
e.target.addEventListener (MouseEvent.MOUSE_UP,MouseUp);
e.target.startDrag ();
}
private function MouseUp (e:MouseEvent):void
{
e.target.removeEventListener (MouseEvent.MOUSE_UP,MouseUp);
e.target.stopDrag ();
}
private function EnterFrame (e:Event):void
{
for (var i:int=0; i<numHandles; i++)
{
var dx:Number=handles[i].x-ball.x;
var dy:Number=handles[i].y-ball.y;
ball.vx+=dx*spring;
ball.vy+=dy*spring;
}
ball.vx*=friction;
ball.vy*=friction;
ball.x+=ball.vx;
ball.y+=ball.vy;
graphics.clear ();
graphics.lineStyle (1);
for (var j:int=0; j<numHandles; j++)
{
graphics.moveTo (ball.x,ball.y);
graphics.lineTo (handles[j].x+handleWidth/2,handles[j].y+handleWidth/2);
}
}
}
}
目标偏移模拟
所谓目标偏移就是真正的弹簧在正常状态下的长度是不为0的,即弹簧在正常状态下总是有一定长度的。
1.构建小球精灵

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public var vx:Number=0;
public var vy:Number=0;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}

package
{
import flash.display.Sprite;
import flash.events.Event;
public class OffsetSpring extends Sprite
{
private var ball:Ball;
private var friction:Number=0.8;
private var spring:Number=0.1;
private var springLength:Number=100;
public function OffsetSpring()
{
Init();
}
private function Init():void
{
ball=new Ball(20,0xFF0000);
addChild(ball);
addEventListener(Event.ENTER_FRAME,EnterFrame);
}
private function EnterFrame(e:Event):void
{
var dx:Number=ball.x-mouseX;
var dy:Number=ball.y-mouseY;
var angle:Number=Math.atan2(dy,dx);
var targetX:Number=mouseX+Math.cos(angle)*springLength;
var targetY:Number=mouseY+Math.sin(angle)*springLength;
ball.vx+=(targetX-ball.x)*spring;
ball.vy+=(targetY-ball.y)*spring;
ball.vx*=friction;
ball.vy*=friction;
ball.x+=ball.vx;
ball.y+=ball.vy;
graphics.clear();
graphics.lineStyle(1);
graphics.moveTo(ball.x,ball.y);
graphics.lineTo(mouseX,mouseY);
}
}
}
弹性多个物体

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public var vx:Number=0;
public var vy:Number=0;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}

package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class DoubleSpring extends Sprite
{
private var ball0:Ball;
private var ball1:Ball;
private var ball0Dragging:Boolean=false;
private var ball1Dragging:Boolean=false;
private var spring:Number=0.1;
private var friction:Number=0.8;
private var springLength:Number=150;
public function DoubleSpring()
{
Init();
}
private function Init():void
{
ball0=new Ball(20,0xFF0000);
ball0.x=Math.random()*stage.stageWidth;
ball0.y=Math.random()*stage.stageHeight;
ball0.addEventListener(MouseEvent.MOUSE_DOWN,MouseDown);
addChild(ball0);
ball1=new Ball(20,0xFF0000);
ball1.x=Math.random()*stage.stageWidth;
ball1.y=Math.random()*stage.stageHeight;
ball1.addEventListener(MouseEvent.MOUSE_DOWN,MouseDown);
addChild(ball1);
addEventListener(Event.ENTER_FRAME,EnterFrame);
stage.addEventListener(MouseEvent.MOUSE_UP,MouseUp);
}
private function EnterFrame(e:Event):void
{
if(!ball0Dragging)
{
SpringTo(ball0,ball1);
}
if(!ball1Dragging)
{
SpringTo(ball1,ball0);
}
graphics.clear();
graphics.lineStyle(1);
graphics.moveTo(ball0.x,ball0.y);
graphics.lineTo(ball1.x,ball1.y);
}
private function SpringTo(ballA:Ball,ballB:Ball):void
{
var dx:Number=ballB.x-ballA.x;
var dy:Number=ballB.y-ballB.y;
var angle:Number=Math.atan2(dy,dx);
var targetX:Number=ballB.x-Math.cos(angle)*springLength;
var targetY:Number=ballB.y-Math.sin(angle)*springLength;
ballA.vx+=(targetX-ballA.x)*spring;
ballA.vy+=(targetY-ballA.y)*spring;
ballA.vx*=friction;
ballA.vy*=friction;
ballA.x+=ballA.vx;
ballA.y+=ballA.vy;
}
private function MouseDown(e:MouseEvent):void
{
e.target.startDrag();
if(e.target==ball0)
{
ball0Dragging=true;
}
if(e.target==ball1)
{
ball1Dragging=true;
}
}
private function MouseUp(e:MouseEvent):void
{
ball0.stopDrag();
ball1.stopDrag();
ball0Dragging=false;
ball1Dragging=false;
}
}
}
简单检测物体碰撞

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}

package
{
import flash.display.Sprite;
import flash.events.Event;
public class ObjectHitTest extends Sprite
{
private var ballA:Ball;
private var ballB:Ball;
public function ObjectHitTest ()
{
Init ();
}
private function Init ():void
{
ballA=new Ball(40,0xFF0000);
addChild (ballA);
ballA.x=stage.stageWidth/2;
ballA.y=stage.stageHeight/2;
ballB=new Ball(40,0xFFCC00);
addChild (ballB);
ballB.x=mouseX;
ballB.y=mouseY;
ballB.startDrag ();
addEventListener (Event.ENTER_FRAME,EnterFrame);
}
private function EnterFrame (e:Event):void
{
if (ballA.hitTestObject(ballB))
{
trace ("Hi,Hit.");
}
}
}
}
简单点碰撞

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}

package
{
import flash.display.Sprite;
import flash.events.Event;
public class PointHitTest extends Sprite
{
private var ball:Ball;
public function PointHitTest ()
{
Init ();
}
private function Init ():void
{
ball=new Ball(20,0xFF0000);
addChild (ball);
ball.x=stage.stageWidth/2;
ball.y=stage.stageHeight/2;
addEventListener (Event.ENTER_FRAME,EnterFrame);
}
private function EnterFrame (e:Event):void
{
if (ball.hitTestPoint(mouseX,mouseY))
{
trace ("Hit.");
}
}
}
}
不准确,和边界盒进行测试。
如果进行精确碰撞,也就是对可视区域进行碰撞测试(而不是边界盒)用:
ball.hitTestPoint(mouseX,mouseY,true)
弹性距离碰撞

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public var vx:Number=0;
public var vy:Number=0;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}

package
{
import flash.events.Event;
import flash.display.Sprite;
public class Bubbles extends Sprite
{
private var balls:Array;
private var bigBall:Ball;
private var bounce:Number=-0.7;
private var numBalls:Number=10;
private var spring:Number=0.2;
public function Bubbles ()
{
Init ();
}
private function Init ():void
{
balls=new Array();
bigBall=new Ball(100,0xFF0000);
addChild (bigBall);
bigBall.x=stage.stageWidth/2;
bigBall.y=stage.stageHeight/2;
for (var i:int=0; i<numBalls; i++)
{
var ball=new Ball(Math.random()*40+5,0xffcc00);
addChild (ball);
ball.x=Math.random()*stage.stageWidth;
ball.y=Math.random()*stage.stageHeight;
ball.vx=Math.random()*6-3;
ball.vy=Math.random()*6-3;
balls.push (ball);
}
addEventListener (Event.ENTER_FRAME,EnterFrame);
}
private function EnterFrame (e:Event):void
{
for (var i:int=0; i<numBalls; i++)
{
var ball:Ball=balls[i];
Move (ball);
var dx:Number=ball.x-bigBall.x;
var dy:Number=ball.y-bigBall.y;
var dist:Number=Math.sqrt(dx*dx+dy*dy);
var minDist:Number=ball.radius+bigBall.radius;
if (dist<minDist)
{
var angle:Number=Math.atan2(dy,dx);
var tx:Number=bigBall.x+Math.cos(angle)*minDist;
var ty:Number=bigBall.y+Math.sin(angle)*minDist;
ball.vx+=(tx-ball.x)*spring;
ball.vy+=(ty-ball.y)*spring;
}
}
}
private function Move(ball:Ball):void
{
ball.x+=ball.vx;
ball.y+=ball.vy;
if(ball.x+ball.radius>stage.stageWidth)
{
ball.x=stage.stageWidth-ball.radius;
ball.vx*=bounce;
}
else if(ball.x-ball.radius<0)
{
ball.x=ball.radius;
ball.vx*=bounce;
}
if(ball.y+ball.radius>stage.stageHeight)
{
ball.y=stage.stageHeight-ball.radius;
ball.vy*=bounce;
}
else if(ball.y-ball.radius<0)
{
ball.y=ball.radius;
ball.vy*=bounce;
}
}
}
}
多物体碰撞模拟

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public var vx:Number=0;
public var vy:Number=0;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}

package
{
import flash.events.Event;
import flash.display.Sprite;
public class Bubbles2 extends Sprite
{
private var balls:Array;
private var bounce:Number=-0.1;
private var spring:Number=0.1;
private var gravity:Number=0.2;
private var numBalls:Number=30;
public function Bubbles2 ()
{
Init ();
}
private function Init ():void
{
balls=new Array();
for (var i:int=0; i<numBalls; i++)
{
var ball:Ball=new Ball(Math.random()*50+5,Math.random()*0xFFFFFF);
addChild (ball);
ball.x=Math.random()*stage.stageWidth;
ball.y=Math.random()*stage.stageHeight;
ball.vx=Math.random()*6-3;
ball.vy=Math.random()*6-3;
balls.push (ball);
}
addEventListener (Event.ENTER_FRAME,EnterFrame);
}
private function EnterFrame (e:Event):void
{
for (var i:int=0; i<numBalls-1; i++)
{
var ball0:Ball=balls[i];
for (var j:int=i+1; j<numBalls; j++)
{
var ball1:Ball=balls[j];
var dx:Number=ball1.x-ball0.x;
var dy:Number=ball1.y-ball0.y;
var dist:Number=Math.sqrt(dx*dx+dy*dy);
var minDist:Number=ball0.radius+ball1.radius;
if (dist<minDist)
{
var tx:Number=ball0.x+dx/dist*minDist;
var ty:Number=ball0.y+dy/dist*minDist;
var ax:Number=(tx-ball1.x)*spring;
var ay:Number=(ty-ball1.y)*spring;
ball0.vx-=ax;
ball0.vy-=ay;
ball1.vx+=ax;
ball1.vy+=ay;
}
}
}
for (var i:int=0; i<numBalls; i++)
{
var ball:Ball=balls[i];
Move (ball);
}
}
private function Move (ball:Ball):void
{
ball.vy+=gravity;
ball.x+=ball.vx;
ball.y+=ball.vy;
if (ball.x+ball.radius>stage.stageWidth)
{
ball.x=stage.stageWidth-ball.radius;
ball.vx*=bounce;
}
else if (ball.x-ball.radius<0)
{
ball.x=ball.radius;
ball.vx*=bounce;
}
if (ball.y+ball.radius>stage.stageHeight)
{
ball.y=stage.stageHeight-ball.radius;
ball.vy*=bounce;
}
else if (ball.y-ball.radius<0)
{
ball.y=ball.radius;
ball.vy*=bounce;
}
}
}
}
----------------------------------------------------------------------------------------------------
碰撞算法优化
多个精灵进行碰撞的一般算法:
| sprite1 | with | sprite2 | sprite3 | sprite4 | sprite5 | sprite6 | sprite7 | sprite8 | 
| sprite2 | with | sprite1 | sprite3 | sprite4 | sprite5 | sprite6 | sprite7 | sprite8 | 
| sprite3 | with | sprite2 | sprite1 | sprite4 | sprite5 | sprite6 | sprite7 | sprite8 | 
| sprite4 | with | sprite2 | sprite3 | sprite1 | sprite5 | sprite6 | sprite7 | sprite8 | 
| sprite5 | with | sprite2 | sprite3 | sprite4 | sprite1 | sprite6 | sprite7 | sprite8 | 
| sprite6 | with | sprite2 | sprite3 | sprite4 | sprite5 | sprite1 | sprite7 | sprite8 | 
| sprite7 | with | sprite2 | sprite3 | sprite4 | sprite5 | sprite6 | sprite1 | sprite8 | 
| sprite8 | with | sprite2 | sprite3 | sprite4 | sprite5 | sprite6 | sprite7 | sprite1 | 
精简算法:
| sprite1 | with | sprite2 | sprite3 | sprite4 | sprite5 | sprite6 | sprite7 | sprite8 | 
| sprite2 | with | sprite3 | sprite4 | sprite5 | sprite6 | sprite7 | sprite8 | |
| sprite3 | with | sprite4 | sprite5 | sprite6 | sprite7 | sprite8 | ||
| sprite4 | with | sprite5 | sprite6 | sprite7 | sprite8 | |||
| sprite5 | with | sprite6 | sprite7 | sprite8 | ||||
| sprite6 | with | sprite7 | sprite8 | |||||
| sprite7 | with | sprite8 | ||||||
| sprite8 | with | nothing | 
简单的赛平斯基垫片

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}

package
{
import flash.display.Sprite;
public class Sierpinski extends Sprite
{
private var ball:Ball;
private var balls:Array;
private var numDots:int=1000;
public function Sierpinski()
{
Init();
}
private function Init():void
{
balls=new Array();
for(var i:int=0;i<numDots;i++)
{
var ball=new Ball(1,0xFF0000);
addChild(ball);
balls.push(ball);
}
balls[0].x=10;
balls[0].y=10;
balls[1].x=400;
balls[1].y=30;
balls[2].x=200;
balls[2].y=300;
for(var i:int=0;i<numDots-1;i++)
{
var index:int=Math.random()*3;
balls[i+1].x=(balls[i].x+balls[index].x)/2;
balls[i+1].y=(balls[i].y+balls[index].y)/2;
}
}
}
}
注意:如果显示不对,多ctrl+Enter几次。
高级坐标旋转
坐标算法:如图
算法实现:

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}

package
{
import flash.display.Sprite;
import flash.events.Event;
public class Rotation extends Sprite
{
private var ball:Ball;
private var vAngle:Number=0.05;
public function Rotation ()
{
ball=new Ball(20,0xFF0000);
addChild (ball);
ball.x=Math.random()*stage.stageWidth;
ball.y=Math.random()*stage.stageHeight;
addEventListener (Event.ENTER_FRAME,EnterFrame);
}
private function EnterFrame (e:Event):void
{
var x1:Number=ball.x-stage.stageWidth/2;
var y1:Number=ball.y-stage.stageHeight/2;
var x2:Number=x1*Math.cos(vAngle)-y1*Math.sin(vAngle);//逆时针旋转
var y2:Number=y1*Math.cos(vAngle)+x1*Math.sin(vAngle);//逆时针旋转
//var x2:Number=x1*Math.cos(vAngle)+y1*Math.sin(vAngle);顺时针旋转
//var y2:Number=y1*Math.cos(vAngle)-x1*Math.sin(vAngle); 顺时针旋转
ball.x=stage.stageWidth/2+x2;
ball.y=stage.stageHeight/2+y2;
}
}
}
旋转多个物体
 
1.构建小球精灵

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}

package
{
import flash.display.Sprite;
import flash.events.Event;
public class MultiRotation extends Sprite
{
private var balls:Array;
private var numBalls:int=10;
public function MultiRotation ()
{
balls=new Array();
for (var i:Number=0; i<numBalls; i++)
{
var ball:Ball=new Ball(20,Math.random()*0xFFFFFF);
addChild (ball);
balls.push (ball);
ball.x=Math.random()*stage.stageWidth;
ball.y=Math.random()*stage.stageHeight;
}
addEventListener (Event.ENTER_FRAME,EnterFrame);
}
private function EnterFrame (e:Event):void
{
var angle:Number=(mouseX-stage.stageWidth/2)*0.001;
for (var i:Number=0; i<numBalls; i++)
{
var ball:Ball=balls[i];
var x1:Number=ball.x-stage.stageWidth/2;
var y1:Number=ball.y-stage.stageHeight/2;
var x2:Number=x1*Math.cos(angle)-y1*Math.sin(angle);
var y2:Number=y1*Math.cos(angle)+x1*Math.sin(angle);
ball.x=x2+stage.stageWidth/2;
ball.y=y2+stage.stageHeight/2;
}
}
}
}
多角度回弹
算法实现:

ActionScirpt3.0实现:
1.构建小球精灵

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public var vx:Number=0;
public var vy:Number=0;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}

package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Rectangle;
public class MultiAngleBounce extends Sprite
{
private var ball:Ball;
private var lines:Array;
private var numLines:int=5;
private var gravity:Number=0.3;
private var bounce:Number=-0.6;
public function MultiAngleBounce ()
{
Init ();
}
private function Init ():void
{
ball=new Ball(20,Math.random()*0xFFFFFF);
addChild (ball);
ball.x=100;
ball.y=0;
lines=new Array();
for (var i:int=0; i<numLines; i++)
{
var line:Sprite=new Sprite();
line.graphics.lineStyle (1);
line.graphics.moveTo (-50,0);
line.graphics.lineTo (50,0);
addChild (line);
lines.push (line);
}
lines[0].x=100;
lines[0].y=100;
lines[0].rotation=30;
lines[1].x=100;
lines[1].y=230;
lines[1].rotation=45;
lines[2].x=250;
lines[2].y=180;
lines[2].rotation=-30;
lines[3].x=150;
lines[3].y=330;
lines[3].rotation=10;
lines[4].x=230;
lines[4].y=250;
lines[4].rotation=-30;
addEventListener (Event.ENTER_FRAME,EnterFrame);
}
private function EnterFrame (e:Event):void
{
ball.vy+=gravity;
ball.x+=ball.vx;
ball.y+=ball.vy;
if (ball.x+ball.radius>stage.stageWidth)
{
ball.x=stage.stageWidth-ball.radius;
ball.vx*=bounce;
}
else if (ball.x-ball.radius<0)
{
ball.x=ball.radius;
ball.vx*=bounce;
}
if (ball.y+ball.radius>stage.stageHeight)
{
ball.y=stage.stageHeight-ball.radius;
ball.vy*=bounce;
}
else if (ball.y-ball.radius<0)
{
ball.y=ball.radius;
ball.vy*=bounce;
}
for (var i:int=0; i<numLines; i++)
{
CheckLine (lines[i]);
}
}
private function CheckLine (line:Sprite):void
{
var bounds:Rectangle=line.getBounds(this);
if (ball.x>bounds.left && ball.x<bounds.right)
{
var angle:Number=line.rotation*Math.PI/180;
var x1:Number=ball.x-line.x;
var y1:Number=ball.y-line.y;
var y2:Number=Math.cos(angle)*y1-Math.sin(angle)*x1;
var vy1:Number=Math.cos(angle)* ball.vy-Math.sin(angle)*ball.vx;
if (y2+ball.radius>0 && y2<vy1)//y2为负值
{
var x2:Number=Math.cos(angle)*x1+Math.sin(angle)*y1;
var vx1:Number=Math.cos(angle)* ball.vx+Math.sin(angle)*ball.vy;
y2=-ball.radius;
vy1*=bounce;
x1=Math.cos(angle)*x2-Math.sin(angle)*y2;
y1=Math.cos(angle)*y2+Math.sin(angle)*x2;
ball.vx=Math.cos(angle)*vx1-Math.sin(angle)*vy1;
ball.vy=Math.cos(angle)*vy1+Math.sin(angle)*vx1;
ball.x=line.x+x1;
ball.y=line.y+y1;
}
}
}
}
}
一维动量守恒

package
{
import flash.display.Sprite;
public class Ball extends Sprite
{
public var radius:Number;
public var color:uint;
public var vx:Number=0;
public var vy:Number=0;
public function Ball (radius:Number,color:uint)
{
this.radius=radius;
this.color=color;
Init ();
}
public function Init ():void
{
graphics.beginFill (color);
graphics.drawCircle (0,0,radius);
graphics.endFill ();
}
}
}

package
{
import flash.events.Event;
import flash.display.Sprite;
public class Billiard1 extends Sprite
{
private var ball0:Ball;
private var ball1:Ball;
private var mass0:Number;
private var mass1:Number;
public function Billiard1()
{
Init();
}
private function Init():void
{
ball0=new Ball(20,0xFFcc00);
mass0=ball0.radius;
ball0.vx=10;
ball0.x=40;
ball0.y=200;
addChild(ball0);
ball1=new Ball(30,0xFF0000);
mass1=ball1.radius;
ball1.vx=-10;
ball1.x=500;
ball1.y=200;
addChild(ball1);
addEventListener(Event.ENTER_FRAME,EnterFrame);
}
private function EnterFrame(e:Event):void
{
ball0.x+=ball0.vx;
ball1.x+=ball1.vx;
var distance:Number=ball1.x-ball0.x;
if(Math.abs(distance)<ball0.radius+ball1.radius)
{
var dv:Number=ball0.vx-ball1.vx;
ball0.vx=((mass0-mass1)*ball0.vx+2*mass1*ball1.vx)/(mass0+mass1);
ball1.vx=dv+ball0.vx;
ball0.x+=ball0.vx;
ball1.x+=ball1.vx;
}
}
}
}
 
                    
                     
                    
                 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号