Forked from: AceDecade's flash on 2009-11-15 diff:299 ぱんぱんぼーる neguse forked:0favorite:0lines:255license : All rights reserved modified : 2009-11-20 23:21:15 Embed Tweet // forked from AceDecade's flash on 2009-11-15 package { import flash.display.*; import flash.events.*; import flash.utils.*; import flash.text.* public class Test extends Sprite { private var sp:Sprite; private var ba:Array; private var high:uint; private var nowText:TextField; private var highText:TextField; private function addBall(b:Ball):void { addChild(b); ba.push(b); } private function remBall(b:Ball):void { removeChild(b); ba.splice(ba.indexOf(b), 1); } public function Test() { graphics.beginFill(0x000000); graphics.drawRoundRect(FIELD_S, FIELD_S, FIELD_L, FIELD_L, 5); graphics.endFill(); graphics.beginFill(0xffffff); graphics.drawRoundRect(FIELD_S + 2, FIELD_S + 2, FIELD_L - 4, FIELD_L - 4, 5); graphics.endFill(); ba = new Array(); var t = new Timer(DELAY); t.addEventListener(TimerEvent.TIMER, onTimer); t.start(); // stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown) high = 0; nowText = new TextField(); highText = new TextField(); nowText.textColor = 0xf0f0f0; nowText.y += 20; addChild(highText); addChild(nowText); } public function onTimer(e:TimerEvent):void { for (var i:int = 0; i < ba.length; i++) { ba[i].onTimer(e); } for (var i:int = 0; i < ba.length - 1; i++) { for (var j:int = i; j < ba.length; j++) { if (isCollide(ba[i], ba[j])) { onCollide(ba[i], ba[j]); } } } for (var i:int = 0; i < ba.length; i++) { if (ba[i].y > DISP_L - FIELD_S + ba[i].l) { remBall(ba[i]); continue; } } for (var i:int = 0; i < ba.length; i++) { ba[i].onUpdate(); } if (high < ba.length) high = ba.length; nowText.text = "ball: " + String(ba.length); highText.text = "high: " + String(high); if (high == ba.length) { highText.textColor = 0xf00000; } else { highText.textColor = 0xf0f000; } if (ba.length == 0) { addBall(new Ball(this, BALL_INIT_L, DISP_H, -BALL_INIT_L)); } } public function onCollide(b1:Ball, b2:Ball):void { var l:Number = b1.l + b2.l; var d:Vec2 = b2.p.sub(b1.p); // difference var dl:Number = d.len(); // length of d var di:Vec2 = d.angle().vec(); // identity vector of d // intersection canceling b1.p.subs(di.mul((l - dl) * b1.l / l)); b2.p.adds(di.mul((l - dl) * b2.l / l)); // add impact force var rv:Vec2 = b2.v.sub(b1.v); // relative velocity var E:Number = 0.90; var dr:Number = dot(rv, di) * (1.0 + E) / l; b1.v.adds(di.mul(dr * b2.l)); b2.v.subs(di.mul(dr * b1.l)); } public function onClick(b:Ball):void { var b1 = new Ball(this, b.l * 3 / 4, b.x - 0.1, b.y); var b2 = new Ball(this, b.l * 3 / 4, b.x + 0.1, b.y); b1.v.x = -100.0; b2.v.x = 100.0; b1.v.y = b2.v.y = -Math.abs(b.v.y) - 10.0; addBall(b1); addBall(b2); remBall(b); } } } import flash.display.*; import flash.events.*; import flash.text.* const DISP_L:int = 465; const DISP_H:int = int(DISP_L / 2); const FIELD_L:int = 400; const FIELD_H:int = 200; const FIELD_S:int = DISP_H - FIELD_H; const BALL_INIT_L:Number = 150.0; const DELAY:int = 30; const DT:Number = DELAY / 1000.0; const GRAVITY:Number = 149.8; class Angle { public var a:Number = 0; function Angle(n:Number) { a = n; round(); } function add(n:Angle) : Angle { return new Angle(a + n.a); } function adds(n:Angle) : Angle{ a += n.a; round(); return this; } function sub(n:Angle) : Angle { return new Angle(a - n.a); } function subs(n:Angle) : Angle { a - n.a; round(); return this; } function mul(n:Number) : Angle { return new Angle(a * n); } function muls(n:Number) : Angle{ a *= n; round(); return this; } function div(n:Number) : Angle { return new Angle(a / n); } function divs(n:Number) : Angle{ a /= n; round(); return this; } function round() { while (a >= Math.PI) a -= Math.PI * 2 while (a < -Math.PI) a += Math.PI * 2 } function cos() : Number { return Math.cos(a); } function sin() : Number { return Math.sin(a); } function vec() : Vec2 { return new Vec2(cos(), sin()); } function reverse() : Angle { return new Angle(a + Math.PI); } } class Vec2 { public var x:Number = 0, y:Number = 0; function Vec2(ax:Number = 0, ay:Number = 0) { x = ax; y = ay; } function set(ax:Number = 0, ay:Number = 0) { x = ax; y = ay; } function add(v:Vec2) : Vec2 { return new Vec2(x + v.x, y + v.y); } function adds(v:Vec2) : Vec2 { x += v.x; y += v.y; return this; } function sub(v:Vec2) : Vec2 { return new Vec2(x - v.x, y - v.y); } function subs(v:Vec2) : Vec2 { x -= v.x; y -= v.y; return this; } function mul(n:Number) : Vec2 { return new Vec2(x * n, y * n); } function muls(n:Number) : Vec2 { x *= n; y *= n; return this; } function div(n:Number) : Vec2 { return new Vec2(x / n, y / n); } function divs(n:Number) : Vec2 { x /= n; y /= n; return this; } function len() : Number { return Math.sqrt(x * x + y * y); } function angle() : Angle { return new Angle(Math.atan2(y, x)); } } function dot(v1:Vec2, v2:Vec2):Number { return v1.x * v2.x + v1.y * v2.y; } class Misc { static function clamp(x:Number, min:Number, max:Number) : Number { return Math.min(Math.max(x, min), max); } static function randRange(min:Number, max:Number) : Number { return min + (max - min) * Math.random(); } } class Ball extends Sprite { // constants // member variables public var v:Vec2 = new Vec2(); public var p:Vec2 = new Vec2(); public var l:Number; public var s:Test; // member function public function Ball(s:Test, l:Number, x, y) { p.x = x; p.y = y; this.x = x; this.y = y; this.l = l; this.s = s; //graphics.beginFill(0x000000); //graphics.drawCircle(0, 0, l); //graphics.endFill(); graphics.beginFill(Math.random() * 0xffffff); graphics.drawCircle(0, 0, l - 1.0); graphics.endFill(); addEventListener(MouseEvent.MOUSE_OVER, onMouseDown) } public function onTimer(e:Event) { v.y += GRAVITY * DT; p.adds(v.mul(DT)); if (p.x < l + FIELD_S) { p.x = l + FIELD_S; if (v.x < 0.0) v.x = -v.x; } if (DISP_L - FIELD_S - l < p.x) { p.x = DISP_L - FIELD_S - l; if (v.x > 0.0) v.x = -v.x; } } public function onMouseDown(e:MouseEvent):void { s.onClick(this); } public function onUpdate():void { x = p.x; y = p.y; } } function isCollide(b1:Ball, b2:Ball) : Boolean { var d:Vec2 = b1.p.sub(b2.p); return d.len() < (b1.l + b2.l); } Code Fullscreen Preview Fullscreen 物理 Math.round Math.min length Math.max drawRoundRect endFill beginFill Math.PI reverse MouseEvent.MOUSE_OVER indexOf TextField removeChild addChild textColor TimerEvent splice Math.atan2 Math.cos drawCircle