代码改变世界

一些算法

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 
{
    
import flash.display.Sprite;
    
public class Arrow extends Sprite
    
{
        
public function Arrow()
        
{
            init();
        }

        
public function init():void
        
{
            graphics.lineStyle(
1,0,1);
            graphics.beginFill(
0xffff00);
            graphics.moveTo(
-50,-25);
            graphics.lineTo(
0,-25);
            graphics.lineTo(
0,-50);
            graphics.lineTo(
50,0);
            graphics.lineTo(
0,50);
            graphics.lineTo(
0,25);
            graphics.lineTo(
-50,25);
            graphics.lineTo(
-50,-25);
            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);
        }
    }
}

精灵的抛运动

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.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;
        }
    }
}
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.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;
            }
        }
    }
}

鼠标跟随缓动

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;


    
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;
        }
    }
}
注意:与 加速度的鼠标跟随 进行比较
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.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);

        }
    }
}
注意:帧率提高,效果会准确。
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;


    
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;
        }
    }
}

多目标点弹性模拟

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 ();
        }
    }
}
2. 构建正方形精灵(可以拖动的手柄)

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 ();
        }
    }
}
3.构建多目标弹性动画

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 ();
        }
    }
}
2.构建目标偏移动画

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);
        }
    }
}

弹性多个物体

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 ();
        }
    }
}
2.构建两个精灵的弹性动画

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;
        }
    }
}

简单检测物体碰撞

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.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.");
            }
        }
    }
}

简单点碰撞

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.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)

弹性距离碰撞

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 ();
        }
    }
}
2.构建碰撞动画

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;
            }
        }
    }
}

多物体碰撞模拟

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 ();
        }
    }
}
2.模拟碰撞动画

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

简单的赛平斯基垫片

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;
    
    
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 ();
        }
    }
}
2. 构建多物体旋转

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 ();
        }
    }
}
2.构建多角度回弹

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;
                }
            }
        }
    }
}

一维动量守恒

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 ();
        }
    }
}
2.构建一维动量守恒动画

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;
            }
        }
    }
}