Forked from: glasses_factory's LiquidFailling diff:3 bloodFailling ペンキが壁から垂れていくっぽい感じの奴 sw_lucchini forked:0favorite:2lines:292license : MIT License modified : 2009-08-21 15:47:51 Embed Tweet // forked from glasses_factory's LiquidFailling //ペンキが壁から垂れていくっぽい感じの奴 package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; [SWF(width = "465",height = "465",backgroundColor="0x000000")] public class LiquidFalling extends Sprite { private var main:Liquid; private var bmd:BitmapData; private var bmp:Bitmap; //一度に生成出来る最大数 private const MAX_LIQUID:int = 10; private var cnt:int; public function LiquidFalling() { init(); } //初期化 private function init():void { bmd = new BitmapData(465,465,true,0x00ffffff); //一行のポイント数,描画するBitmapData liquidGen(Math.random() * 20 + 10,bmd); bmp = new Bitmap(bmd); addChild(bmp); stage.addEventListener(MouseEvent.CLICK,onClick); } //クリックで生成 private function onClick(e:MouseEvent):void { liquidGen(Math.random() * 20 + 10,bmd); bmp.bitmapData = bmd; } private function liquidGen(ptNum:int,_bmd:BitmapData):void { //最大数より生成されていたらリターン。 if(cnt > MAX_LIQUID) { return; } else { main = new Liquid(ptNum,_bmd); main.generate(-100,Math.random() * 0xFF0000); main.addEventListener(Liquid.FAIL_OUT,failed); cnt++; } } private function failed(e:Event):void { cnt--; e.target.removeEventListener(Liquid.FAIL_OUT,failed); } } } import __AS3__.vec.Vector; import flash.display.BitmapData; import flash.display.Sprite; import flash.events.Event; import flash.events.TimerEvent; import flash.utils.Timer; class Liquid extends Sprite { public static const FAIL_OUT:String = "fail_out"; private var ptNum:int; private var bmd:BitmapData; private var sp:Sprite; private var ptVect:Vector.<LiquidPt>; private var _color:uint; private var rightEnd:LiquidPt; private var loc1:*; private var loc2:*; private var loc3:*; private var loc4:*; private var endCnt:uint; private var _timer:Timer; public function Liquid(_ptNum:int,_bmd:BitmapData) { ptNum = _ptNum; bmd = _bmd; sp = new Sprite(); ptVect = new Vector.<LiquidPt>(_ptNum,true); } public function generate(pos:Number,col:uint):void { _color = col; for(var i:int = 0; i < ptNum-1; i++) { loc1 = i * (465 / ptNum+1); ptVect[i] = new LiquidPt(loc1,pos); ptVect[i].gravity = 8; ptVect[i].friction = 0.5; } ptVect[ptNum-1] = new LiquidPt(465,pos); ptVect[ptNum-1].gravity = 8; ptVect[ptNum-1].friction = 0.5; //描画 draw(); //毎フレーム描画 addEventListener(Event.ENTER_FRAME,onEnter); // 落ち始めるポイントをランダムに指定 _timer = new Timer(1000); _timer.addEventListener(TimerEvent.TIMER,onTimer); _timer.start(); } public function draw():void { sp.graphics.clear(); sp.graphics.lineStyle(1,_color); sp.graphics.beginFill(_color); sp.graphics.moveTo(ptVect[0].x,ptVect[0].y); for(var i:int = 1; i < ptNum-1; i++) { sp.graphics.curveTo(ptVect[i].x,ptVect[i].y,(ptVect[i].x + ptVect[i+1].x) / 2,(ptVect[i].y + ptVect[i+1].y)/2) } sp.graphics.curveTo(ptVect[ptNum-1].x,ptVect[ptNum-1].y,(ptVect[ptNum-1].x + 465) / 2,(ptVect[ptNum-1].y + ptVect[ptNum-1].y)/2); sp.graphics.lineTo(465,0); sp.graphics.lineTo(0,0); sp.graphics.endFill(); bmd.draw(sp); } private function onEnter(e:Event):void { for(var i:int =0; i < ptNum; i++) { if(ptVect[i].isFalling) { ptVect[i].fallDown(); if(ptVect[i].y >= 465 + 465/2) { !ptVect[i].isFallDown ? endCnt++ : endCnt; ptVect[i].isFallDown = true; } } //ステージ中心より下に落ちたら両隣のポイントを引きずる if(ptVect[i].y > 465/2) { if(i-1 >-1) { if(!ptVect[i-1].isFalling) { ptVect[i-1].isFalling = true; //重力と抵抗をランダムにする事で何かそれっぽくなる ptVect[i-1].gravity = Math.random() * 12 + 6; ptVect[i-1].friction = Math.random() * 0.8 + 0.4; } } if(i < ptNum-1) { if(!ptVect[i+1].isFalling) { ptVect[i+1].isFalling = true; ptVect[i+1].gravity = Math.random() * 12 + 6; ptVect[i+1].friction = Math.random() * 0.8 + 0.4; } } } //全てのポイントがステージより下に落ちたら落ちきった事を通知 if(endCnt >= ptNum) { dispatchEvent(new Event(FAIL_OUT)); removeEventListener(Event.ENTER_FRAME,onEnter); } } draw(); } private function onTimer(e:TimerEvent):void { //まだ落ちていないポイントを抽出 loc1 = function(item:LiquidPt,ind:int,vect:Vector.<LiquidPt>):Boolean { if(!item.isFalling) return true; else return false }; loc2 = ptVect.filter(loc1); //落ち始めるポイントをランダムに決定 //同時に複数落とす事で液体の幅を変える loc3 = int(Math.random() * loc2.length); loc4 = int(Math.random() * 3); //Vectorの中が空でなければ if(loc2.length-1 > 0) { for(var i:int =0; i < loc4; i++) { loc2[loc3+i].isFalling = true; } } //全てのポイントが落ちきったらタイマーストップ if(loc2.length <= 0) { _timer.stop(); _timer.removeEventListener(TimerEvent.TIMER,onTimer); } } } import flash.geom.Point; class LiquidPt extends Point { private var _vx:Number, _vy:Number; private var _gravity:Number; private var _friction:Number; private var _isFalling:Boolean; private var _moved:Boolean; private var oldX:Number; private var oldY:Number; private var _isFallDown:Boolean; public function get vx():Number { return _vx; } public function set vx(value:Number):void { _vx = value; return; } public function get vy():Number { return _vy; } public function set vy(value:Number):void { _vy = value; return; } public function set gravity(value:Number):void { _gravity = value; return; } public function get gravity():Number { return _gravity; } public function get friction():Number { return _friction; } public function set friction(value:Number):void { _friction = value; return; } public function set isFalling(value:Boolean):void { _isFalling = value; return; } public function get isFalling():Boolean { return _isFalling; } public function set isFallDown(value:Boolean):void { _isFallDown = value; return; } public function get isFallDown():Boolean { return _isFallDown; } public function LiquidPt(xValue:Number=0, yValue:Number=0) { super(xValue, yValue); x = xValue; y = yValue; oldX = x; _vx = 0; _vy = 0; } public function fallDown():void { if(_isFallDown) return; vy = gravity; vy *= friction; y += vy; } public function mouseInteraction(tPt:Point):void { if(Math.abs(x - tPt.x) < 40) { _moved = true; vx = (tPt.x - x) * 0.5; vx *= _friction; x += vx; } else if(!_moved) { return } else { vx = (oldX - x) * 0.5; vx *= _friction; x += vx; if(Math.abs(oldX - x) < 0.1) _moved = false; } if(Math.abs(y - tPt.y) < 40) { _moved = true; _gravity *= 1.2; } else if(!_moved) { return; } } } Code Fullscreen Preview Fullscreen ricserje slint : NPP NPP Boolean Math.abs TimerEvent.ENTER_FRAME dispatchEvent stop TimerEvent.TIMER filter TimerEvent removeEventListener start length addEventListener Timer Point Math.random Vector addChild String uint Sprite