流れる粒子
/**
* Copyright termat ( http://wonderfl.net/user/termat )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/htHu
*/
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import com.bit101.components.*;
import flash.geom.Point;
import flash.geom.Rectangle;
[SWF(width = "480", height = "480", backgroundColor = "0xffffff", fps = "30")]
public class Practice46 extends Sprite{
private var list:Vector.<Particle>;
private var num:int = 400;
private var dt:Number = 0.15;
private var mode:int = 0;
private var pos:Point, pos2:Point;
private var faucet:MovieClip;
private var isDouble:Boolean = false;
public function Practice46() {
list = new Vector.<Particle>();
for (var i:int = 0; i < num; i++) {
var p:Particle = new Particle(0, 0, 0, 0, 1000);
list.push(p);
}
stage.doubleClickEnabled = true;
addEventListener(Event.ENTER_FRAME, update);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
stage.addEventListener(MouseEvent.CLICK, singleClick);
stage.addEventListener(MouseEvent.DOUBLE_CLICK, doubleClick);
var prob1 : RadioButton = new RadioButton(this, 420, 5, "Inflow", true, function(e:Event):void { mode = 0; } );
var prob2 : RadioButton = new RadioButton(this, 420, 20, "Draw Wall", false, function(e:Event):void { mode = 1; } );
var prob3 : RadioButton = new RadioButton(this, 420, 35, "Cut Wall", false, function(e:Event):void { mode = 2; } );
faucet = new MovieClip();
faucet.graphics.lineStyle(4, 0x000066);
faucet.graphics.drawCircle(0, 0, 12);
faucet.x = 32; faucet.y = 20;
addChild(faucet);
initWall();
Wonderfl.capture_delay(30);
}
private function singleClick(e:MouseEvent):void {
isDouble = false;
}
private function doubleClick(e:MouseEvent):void {
isDouble = true;
}
private function initWall():void {
setWall(new Point(18, 55), new Point(370, 165));
setWall(new Point(452, 122), new Point(452, 226));
setWall(new Point(453, 214), new Point(283, 254));
setWall(new Point(230, 262), new Point(84, 294));
setWall(new Point(19, 267), new Point(19, 371));
setWall(new Point(19, 374), new Point(100, 446));
setWall(new Point(100, 446), new Point(203, 446));
setWall(new Point(203, 446), new Point(249, 382));
setWall(new Point(253, 418), new Point(411, 448));
}
private function update(e:Event):void {
if (mode==0) {
for each(var p:Particle in list) {
if (p.isAlive) continue;
p.x = faucet.x;
p.y = faucet.y;
p.isAlive = true;
p.color = 0x0000ff;
break;
}
}
this.graphics.clear();
for each(p in list) {
if (p.isAlive) {
p.draw(this.graphics);
p.calcBuoyancy(dt);
p.calcConvection(dt);
p.updateAlive();
}
}
Particle.calcCollision(dt, list);
if (pos2 != null) {
if (mode == 1) {
graphics.lineStyle(1,0xff0000);
graphics.moveTo(pos.x, pos.y);
graphics.lineTo(pos2.x, pos2.y);
}else {
graphics.lineStyle(1, 0xff0000);
graphics.drawRect(Math.min(pos.x, pos2.x), Math.min(pos.y, pos2.y), Math.abs(pos.x - pos2.x), Math.abs(pos.y - pos2.y));
}
}
if (isDouble) {
faucet.x = mouseX;
faucet.y = mouseY;
isDouble = false;
}
}
private function mouseDown(e:MouseEvent):void {
if (mode >= 1) pos = new Point(e.stageX, e.stageY);
}
private function setWall(p1:Point, p2:Point):void {
var vx:Number = p2.x - p1.x;
var vy:Number = p2.y - p1.y;
var lg:Number = Math.sqrt(vx * vx + vy * vy);
vx *= 1.0 / lg;
vy *= 1.0 / lg;
var xx:Number = p1.x;
var yy:Number = p1.y;
while (true) {
var p:Particle = new Particle(xx, yy, 0, 0, 1000);
p.isAlive = true;
p.isFix = true;
p.color = 0x888888;
list.push(p);
xx += vx * Particle.radius/2.0;
yy += vy * Particle.radius/2.0;
if (lg < Math.sqrt(Math.pow(xx - p1.x, 2) + Math.pow(yy - p1.y, 2))) break;
}
}
private function mouseUp(e:MouseEvent):void {
if (pos != null && pos2 != null) {
if (mode == 1) {
setWall(pos,pos2);
}else {
var r:Rectangle = new Rectangle(Math.min(pos.x, pos2.x), Math.min(pos.y, pos2.y), Math.abs(pos.x - pos2.x), Math.abs(pos.y - pos2.y));
for each(var p:Particle in list) {
if (r.contains(p.x, p.y)) {
p.x = 0; p.y = 0;
p.vx = 0; p.vy = 0;
p.isFix = false; p.isAlive = false;
}
}
}
}
pos = null;
pos2 = null;
}
private function mouseMove(e:MouseEvent):void {
if (pos != null) pos2 = new Point(e.stageX, e.stageY);
}
}
}
import flash.display.Graphics;
import flash.geom.Rectangle;
class Particle {
public static var rect:Rectangle = new Rectangle(0, 0, 480, 480);
public static var radius:Number = 8.0;
public const GRAV:Number = 9.8;
public const COL_RATE:Number=1.6;
public var x:Number=0.0 , y:Number=0.0;
public var vx:Number=0.0 , vy:Number=0.0;
public var isAlive:Boolean = false;
public var isFix:Boolean = false;
public var dencity:Number = 1000;
public var color:uint = 0x0000ff;
public function Particle(x:Number , y:Number , vx:Number , vy:Number, d:Number) {
this.x = x ; this.y = y ;
this.vx = vx ; this.vy = vy ;
dencity = d;
}
public function updateAlive():void {
isAlive = rect.contains(x, y);
if (!isAlive) { vx = 0; vy = 0; x = 0; y = 0; }
}
public function draw(g:Graphics):void {
if (isAlive) {
g.beginFill(color);
g.drawCircle(x,y,radius);
g.endFill();
}
}
public function distanceSq( p:Particle ):Number {
var xx:Number = x - p.x;
var yy:Number = y - p.y;
return ( xx * xx + yy * yy) ;
}
public function getVerocity():Number {
return Math.sqrt(vx * vx + vy * vy) ;
}
public function calcBuoyancy(dt:Number ):void {
if(!isAlive||isFix) return;
vy += GRAV * dt ;
}
public function calcConvection( dt:Number ):void {
if(!isAlive||isFix) return;
x += vx * dt ;
y += vy * dt ;
}
public static function calcCollision(dt:Number , ps:Vector.<Particle>):void {
var rr2:Number = 4 * radius * radius;
var dist:Number;
for (var i:int = 0; i < ps.length; i++) {
if (!ps[i].isAlive) continue;
for (var j:int = i + 1; j < ps.length; j++) {
if (!ps[j].isAlive) continue;
dist = ps[i].distanceSq(ps[j]);
if (dist < rr2) ps[i].collision(dt, ps[j], rr2);
}
}
}
public function collision(dt:Number , p:Particle, rr2:Number):void {
var xx:Number = p.x - x ;
var yy:Number = p.y - y ;
var m1:Number = dencity;
var m2:Number = p.dencity;
var rr:Number = Math.sqrt(rr2);
var mm:Number = m1 + m2 ;
var gx:Number = ( m1 * vx + m2 * p.vx ) / mm ;
var gy:Number = ( m1 * vy + m2 * p.vy ) / mm ;
gx = m1 * ( vx - gx ) ;
gy = m1 * ( vy - gy ) ;
var vabs:Number = ( gx * xx + gy * yy) / rr ;
if( vabs < 0.0 ) return;
var vrat:Number = 1.0 + COL_RATE;
gx = vrat * vabs * xx / rr ;
gy = vrat * vabs * yy / rr ;
if(!isFix){
vx -= gx / m1;
vy -= gy / m1;
x -= dt * gx / m1;
y -= dt * gy / m1;
}
if(!p.isFix) {
p.vx += gx / m2;
p.vy += gy / m2;
p.x += dt * gx / m2;
p.y += dt * gy / m2;
}
}
}