多物体碰撞(动量守恒)

View Code
package cn.d
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Point;

public class MultiBilliard extends Sprite
{
private var balls:Array;
private var numBalls:uint=200;
private var bounce:Number=-1.0;

public function MultiBilliard()
{
stage.scaleMode=StageScaleMode.NO_SCALE;
stage.align=StageAlign.TOP_LEFT;

init();
}

private function init():void
{
balls=new Array();
for (var i:uint=0; i < numBalls; i++)
{
var radius:Number=Math.random() * 20 + 20;
var ball:Ball=new Ball(radius);
ball.mass=radius;
ball.x=i * 100;
ball.y=i * 50;
ball.vx=Math.random() * 10 - 5;
ball.vy=Math.random() * 10 - 5;
addChild(ball);
balls.push(ball);
}

addEventListener(Event.ENTER_FRAME, onEnterFrame);
}

private function onEnterFrame(e:Event):void
{
for (var i:uint=0; i < numBalls; i++)
{
var ball:Ball=balls[i];
ball.x+=ball.vx;
ball.y+=ball.vy;
checkWalls(ball);
}

for (i=0; i < numBalls - 1; i++)
{
var ballA:Ball=balls[i];
for (var j:Number=i + 1; j < numBalls; j++)
{
var ballB:Ball=balls[j];
checkCollision(ballA, ballB)
}
}

}

private function checkCollision(ball0:Ball, ball1:Ball):void
{
var dx:Number=ball1.x - ball0.x;
var dy:Number=ball1.y - ball0.y;
var dist:Number=Math.sqrt(dx * dx + dy * dy);
if (dist < ball0.radius + ball1.radius)
{
// 计算角度和正余弦值
var angle:Number=Math.atan2(dy, dx);
var sin:Number=Math.sin(angle);
var cos:Number=Math.cos(angle);
// 旋转 ball0 的位置
var pos0:Point=new Point(0, 0);
// 旋转 ball1 的速度
var pos1:Point=rotate(dx, dy, sin, cos, true);
// 旋转 ball0 的速度
var vel0:Point=rotate(ball0.vx, ball0.vy, sin, cos, true);
// 旋转 ball1 的速度
var vel1:Point=rotate(ball1.vx, ball1.vy, sin, cos, true);
// 碰撞的作用力
var vxTotal:Number=vel0.x - vel1.x;
vel0.x=((ball0.mass - ball1.mass) * vel0.x + 2 * ball1.mass * vel1.x) / (ball0.mass + ball1.mass);
vel1.x=vxTotal + vel0.x;
// 更新位置
pos0.x+=vel0.x;
pos1.x+=vel1.x;

// 将位置旋转回来
var pos0F:Object=rotate(pos0.x, pos0.y, sin, cos, false);
var pos1F:Object=rotate(pos1.x, pos1.y, sin, cos, false);

// 将位置调整为屏幕的实际位置
ball1.x=ball0.x + pos1F.x;
ball1.y=ball0.y + pos1F.y;
ball0.x=ball0.x + pos0F.x;
ball0.y=ball0.y + pos0F.y;

// 将速度旋转回来
var vel0F:Object=rotate(vel0.x, vel0.y, sin, cos, false);
var vel1F:Object=rotate(vel1.x, vel1.y, sin, cos, false);

ball0.vx=vel0F.x;
ball0.vy=vel0F.y;
ball1.vx=vel1F.x;
ball1.vy=vel1F.y;

}
}

private function rotate(x:Number, y:Number, sin:Number, cos:Number, reverse:Boolean):Point
{
var result:Point=new Point();
if (reverse)
{
result.x=x * cos + y * sin;
result.y=y * cos - x * sin;
}
else
{
result.x=x * cos - y * sin;
result.y=y * cos + x * sin;
}
return result;
}

private function checkWalls(ball:Ball):void
{
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 cn.d
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Point;

public class Billiard3 extends Sprite
{
private var ball0:Ball;
private var ball1:Ball;
private var bounce:Number=-1.0;

public function Billiard3()
{
stage.scaleMode=StageScaleMode.NO_SCALE;
stage.align=StageAlign.TOP_LEFT;

init();
}

private function init():void
{
ball0=new Ball(150);
ball0.mass=2;
ball0.x=stage.stageWidth - 200;
ball0.y=stage.stageHeight - 200;
ball0.vx=Math.random() * 10 - 5;
ball0.vy=Math.random() * 10 - 5;
addChild(ball0);
ball1=new Ball(90);
ball1.mass=1;
ball1.x=600;
ball1.y=100;
ball1.vx=Math.random() * 10 - 5;
ball1.vy=Math.random() * 10 - 5;
addChild(ball1);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}

private function onEnterFrame(event:Event):void
{
ball0.x+=ball0.vx;
ball0.y+=ball0.vy;
ball1.x+=ball1.vx;
ball1.y+=ball1.vy;
checkCollision(ball0, ball1);
checkWalls(ball0);
checkWalls(ball1);
}

private function checkWalls(ball:Ball):void
{
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;
}

}

private function checkCollision(ball0:Ball, ball1:Ball):void
{
var dx:Number=ball1.x - ball0.x;
var dy:Number=ball1.y - ball0.y;
var dist:Number=Math.sqrt(dx * dx + dy * dy);
if (dist < ball0.radius + ball1.radius)
{
// 计算角度和正余弦值
var angle:Number=Math.atan2(dy, dx);
var sin:Number=Math.sin(angle);
var cos:Number=Math.cos(angle);
// 旋转 ball0 的位置
var pos0:Point=new Point(0, 0);
// 旋转 ball1 的速度
var pos1:Point=rotate(dx, dy, sin, cos, true);
// 旋转 ball0 的速度
var vel0:Point=rotate(ball0.vx, ball0.vy, sin, cos, true);
// 旋转 ball1 的速度
var vel1:Point=rotate(ball1.vx, ball1.vy, sin, cos, true);
// 碰撞的作用力
var vxTotal:Number=vel0.x - vel1.x;
vel0.x=((ball0.mass - ball1.mass) * vel0.x + 2 * ball1.mass * vel1.x) / (ball0.mass + ball1.mass);
vel1.x=vxTotal + vel0.x;
// 更新位置
pos0.x+=vel0.x;
pos1.x+=vel1.x;

// 将位置旋转回来
var pos0F:Object=rotate(pos0.x, pos0.y, sin, cos, false);
var pos1F:Object=rotate(pos1.x, pos1.y, sin, cos, false);

// 将位置调整为屏幕的实际位置
ball1.x=ball0.x + pos1F.x;
ball1.y=ball0.y + pos1F.y;
ball0.x=ball0.x + pos0F.x;
ball0.y=ball0.y + pos0F.y;

// 将速度旋转回来
var vel0F:Object=rotate(vel0.x, vel0.y, sin, cos, false);
var vel1F:Object=rotate(vel1.x, vel1.y, sin, cos, false);

ball0.vx=vel0F.x;
ball0.vy=vel0F.y;
ball1.vx=vel1F.x;
ball1.vy=vel1F.y;

}
}

private function rotate(x:Number, y:Number, sin:Number, cos:Number, reverse:Boolean):Point
{
var result:Point=new Point();
if (reverse)
{
result.x=x * cos + y * sin;
result.y=y * cos - x * sin;
}
else
{
result.x=x * cos - y * sin;
result.y=y * cos + x * sin;
}
return result;
}

}
}

 

 

 

 




转载于:https://www.cnblogs.com/ndljava/archive/2012/03/06/2382446.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值