ビリヤードボールの原理
ビリヤードボールの原理
/**
* Copyright akira_odohira ( http://wonderfl.net/user/akira_odohira )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/5HQu
*/
/*
ビリヤードボールの原理
*/
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.geom.Point;
import flash.utils.Timer;
//import utils.ExDebug;
public class Circle extends Sprite{
private var _cnt:int = 20;
private var _timer:Timer;
private var _spArr:Array = new Array();
private var _ptArr:Array = new Array();
//circleの初期設定
private var _minRadius:uint = 30;
private var _lengeRadius:uint = 20;
private var _initV:Number = 4;
//画面外
private var _addV:Number = 0.4;
private var _hosei:int = 00;
public function Circle() {
// ExDebug.motitor(stage);
init();
}
private function init():void {
_spArr = new Array();
_ptArr = new Array();
setTimer();
setListener();
// triger
//addCircle();
}
private function setTimer():void{
_timer = new Timer(500, _cnt);
_timer.addEventListener(TimerEvent.TIMER, addCircle, false, 0, true);
//_timer.addEventListener(TimerEvent.TIMER_COMPLETE, addCircle, false, 0, true);
_timer.start();
}
private function setListener():void{
addEventListener(Event.ENTER_FRAME, motion, false, 0, true);
addEventListener(Event.ENTER_FRAME, rendering, false, 0, true);
}
private function addCircle(e:TimerEvent = null):void {
var radius:uint = Math.random() * _lengeRadius + _minRadius;
drawCircle(radius);
setPoint(radius);
}
private function drawCircle(radius:uint):void{
var sp :Sprite = new Sprite();
sp.graphics.beginFill(0, 1);
sp.graphics.drawCircle(0, 0, radius );
sp.graphics.endFill();
sp.x = -500;
addChild(sp);
_spArr.push(sp);
}
private function setPoint(radius:uint):void{
var pt:CirclePoint = new CirclePoint(radius, _initV);
pt.x = -500;
pt.y = stage.stageHeight >> 1;
_ptArr.push(pt);
}
// circle1の座標計算
private function motion(e:Event):void {
var ptArr:Array = _ptArr;
var length:uint = ptArr.length;
var i:int, j:int;
var pt:CirclePoint, pt0:CirclePoint, pt1:CirclePoint;
var boo:Boolean;
for (i = 0; i < length; i++ ) {
pt = ptArr[i];
pt.x += pt.vx;
pt.y += pt.vy;
if (pt.vx * pt.vx + pt.vy * pt.vy > 10) {
pt.vx *= 0.98;
pt.vy *= 0.98;
}
pt.rotation += ( -pt.vx + pt.vy) / 10;
pt.rotation *= 0.99;
checkWalls(pt);
}
for (i = 0; i < length; i++ ) {
pt0 = ptArr[i];
for (j = 0; j < length; j++ ) {
pt1 = ptArr[j];
if(pt0 != pt1) checkCollision( pt0, pt1);
}
}
}
// 描画
private function rendering(e:Event):void {
var spArr:Array = _spArr;
var ptArr:Array = _ptArr;
var length:uint = spArr.length;
var i:uint;
var sp:Sprite;
var pt:CirclePoint;
for (i = 0; i < length; i++ ) {
sp = spArr[i];
pt = ptArr[i];
sp.x = pt.x;
sp.y = pt.y;
sp.rotation = pt.rotation;
}
}
// 円と円の衝突
private function checkCollision(pt0:CirclePoint, pt1:CirclePoint):void {
var dx:Number = pt1.x - pt0.x;
var dy:Number = pt1.y - pt0.y;
var dist:Number = Math.sqrt(dx * dx + dy * dy);
if(dist < pt0.radius + pt1.radius) {
var angle:Number = Math.atan2(dy, dx);
var sin:Number = Math.sin(angle);
var cos:Number = Math.cos(angle);
var v:Number = dist - (pt0.radius + pt1.radius);
pt0.vx += (v / (pt0.radius * 10)) * cos;
pt0.vy += (v / (pt0.radius * 10)) * sin;
}
}
// エリア外に出たときの処理
private function checkWalls(pt:CirclePoint):void{
if (pt.x < -_hosei ) pt.vx += _addV;
else if (pt.x > stage.stageWidth + _hosei) pt.vx += -_addV;
if (pt.y < -_hosei) pt.vy = _addV;
else if (pt.y > stage.stageHeight + _hosei) pt.vy = -_addV;
}
}
}
class CirclePoint {
public var x:Number = 0; // x
public var y:Number = 0; // y
public var rotation:Number = 0; // rotation
public var vx:Number = 0; // 速度 x
public var vy:Number = 0; // 速度 y
public var vr:Number = 0; // 速度 rotation
public var radius:Number = 0; // 半径
public function CirclePoint(radius:Number, v:Number) {
this.radius = radius;
this.vx = v + Math.random();
this.vy = (Math.random() > 0.5)? v + Math.random() : -(v + Math.random());
}
}