Forked from: nutsu's forked from: Marimo : moves by mouse. diff:58 forked from: forked from: Marimo : moves by mouse. もうちょっと草っぽくしないと。 dizgid forked:0favorite:1lines:147license : MIT License modified : 2009-12-07 19:26:19 Embed Tweet // forked from nutsu's forked from: Marimo : moves by mouse. // forked from tail_y's Marimo // もうちょっと草っぽくしないと。 package { import flash.display.GradientType; import flash.display.Graphics; import flash.display.Sprite; import flash.events.Event; import frocessing.geom.FGradientMatrix; import frocessing.math.FMath; [SWF(width="465", height="465", backgroundColor="0x000000", frameRate="30")] public class Marimo extends Sprite { // 空飛ぶマリモ的な物を作る。 // 実際の構造は、マリモというか、やわらかいウニ。 // 球形の表面からパーティクルを飛ばして、それを線で繋ぐ。 // 問題点:線のつなぎ目が汚い 毛の長さが重力によって伸びてしまう ちょっと重い // できそうなこと:ビットマップにピクセルで描いて縮小するようにすれば、軽くなるかも。パーティクルを制御すれば、地面と毛が接する表現になるかも public static const STAGE_W:uint = 465; public static const STAGE_H:uint = 465; public static const SPHERE_R:Number = 10; // マリモの体の(毛以外の部分の)半径。 public static const PARTICLE_NUM_RATE:uint = 15; // 球体の半円を分割する数。 public static const PARTICLE_STEP:uint = 6; // 線の描画回数。大きいほど長くなる。 public static const PARTICLE_V:uint = 8*PARTICLE_STEP; // 線の勢い。大きいほど長く、粗くなる。 public static const GRAVITY:Number = 0.9; // 重力。毛の長さ補正をしていないので、重力が強すぎると毛が伸びる public static const RANDOM_RATE:Number = 0.8; // バラつき具合 public static const COLOR_RANDOM_RATE:Number = 0.3; // 色のバラつき具合 public static const GROUND_Y:Number = 400; // 地面位置 public static const SHADOW_W:Number = 150; // 影サイズ public static const GROUND_H:Number = 30; // 影サイズ private var _marimoX:Number = STAGE_W/2; // マリモの位置 private var _marimoY:Number = STAGE_H -20; private var _display2:Sprite; public static const COLOR_TIP_TOP:Number = 0x77cc44; // 毛先上部 public static const COLOR_TIP_BOTTOM:Number = 0x339900; // 毛先下部 public static const COLOR_BACE_TOP:Number = 0x116600; // 本体上部 public static const COLOR_BACE_BOTTOM:Number = 0x003300; // 本体下部 private var g:Graphics; private var gmtx:FGradientMatrix; private var furalphas:Array = [0.6,0.1]; private var furratios:Array = [0,180]; private var furs:Array; private var offsetX:Number; private var offsetY:Number; private var targetX:Number; private var targetY:Number; private var draw_gravity:Number; private var eyeX1:Number = SPHERE_R / 2; private var eyeX2:Number = -eyeX1; private var eyeY:Number = -SPHERE_R/4; private var eyeR:Number = 6; public function Marimo() { addEventListener( Event.ADDED_TO_STAGE, init ); } private function init(e:Event):void { stage.quality = "best"; // _display2 = new Sprite(); addChild(_display2); //matrix for gradient gmtx = new FGradientMatrix(); // graphics g = _display2.graphics; g.lineStyle(); // makeFurs(); offsetX = targetX = 0; offsetY = targetY = 0; // addEventListener( Event.ENTER_FRAME, drawMarimo ); } private function makeFurs():void { furs = []; // 毛 for (var xri:uint = 0; xri < PARTICLE_NUM_RATE; xri++){ // zを先に計算して、奥から手前へ描画 var xAngle:Number = Math.PI*xri / PARTICLE_NUM_RATE; // マリモ中心点から、マリモ表面へのx方向に対する角度 //var z:Number = Math.cos(xAngle) * SPHERE_R; // パーティクルを飛ばす原点Z var r:Number = Math.sin(xAngle) * SPHERE_R; // その時の、断面の半径 // z方向に向いた面の円周上にある点の数。円周の比(=半径の比)で割り出すが、整数に丸めるので、正確ではない。 // (右側でそろっちゃうのが気持ち悪い。ランダムでz回転させてもいいかも。) var particleRateZ:int = PARTICLE_NUM_RATE * 2 * r / SPHERE_R; for (var zri:uint = 0; zri < particleRateZ; zri++){ // z方向面に対して、時計回りに描画 var zAngle:Number = Math.PI*zri*2 / particleRateZ; // マリモ中心点から、マリモ表面へのz方向に対する角度 //var x:Number = Math.cos(zAngle) * r; // パーティクルを飛ばす原点X //var y:Number = Math.sin(zAngle) * r; // パーティクルを飛ばす原点Y var x:Number = STAGE_W / particleRateZ * zri - STAGE_W /2; var y:Number = Math.random() * 40; //var vx:Number = PARTICLE_V * x / SPHERE_R; // パーティクルの速度X //var vy:Number = PARTICLE_V * y / SPHERE_R; // パーティクルの速度Y var vx:Number = 0; // パーティクルの速度X var vy:Number = -100; // パーティクルの速度Y // 方向をランダムでバラす。(本来は、円形方向へランダムにしなきゃいけないのだけど、面倒なのでこれで) vx += (PARTICLE_V * RANDOM_RATE) * (0.5 - Math.random()); vy += (PARTICLE_V * RANDOM_RATE) * (0.5 - Math.random()); // 色を決める。上下の位置と、根本までの割合で色を決定する。ランダムもちょっと入れておく。 var yColorRate:Number = ((SPHERE_R + y)/ 2 / SPHERE_R) + COLOR_RANDOM_RATE * (0.5 - Math.random()); var color0:Number = mixColor(COLOR_BACE_TOP, COLOR_BACE_BOTTOM, yColorRate); var color1:Number = mixColor(COLOR_TIP_TOP, COLOR_TIP_BOTTOM, yColorRate); // 毛 if( FMath.dist(x,y,eyeX1,eyeY)<eyeR || FMath.dist(x,y,eyeX2,eyeY)<eyeR )continue; var fur:FurInfo = new FurInfo(); fur.x = _marimoX + x; fur.y = _marimoY + y; fur.vx = vx; fur.vy = vy; fur.dx = Math.random() * 2; fur.colors = [color0, color1]; furs.push( fur ); } } eyeX1 += _marimoX; eyeX2 += _marimoX; eyeY += _marimoY; } private function drawMarimo( e:Event ):void { g.clear(); targetX = (mouseX - _marimoX); targetY = (mouseY - _marimoY); var ax:Number = ( targetX - offsetX ); var ay:Number = ( targetY - offsetY ); //var gr:Number = FMath.constrain( GRAVITY - ax / 20, -GRAVITY, 1.5 * GRAVITY ); var gr:Number = -ax * 0.02; offsetX += ax * 0.2; offsetY += ay * 0.2; draw_gravity = GRAVITY * gr * PARTICLE_STEP * PARTICLE_STEP; //ax = FMath.constrain( ax, -PARTICLE_V/2, PARTICLE_V/2 ); ax *= 0.4; /* // 本体 g.beginFill(COLOR_BACE_BOTTOM); g.drawCircle(_marimoX+offsetX, _marimoY+offsetY, SPHERE_R); g.endFill(); */ var len:int = furs.length; for ( var i:int = 0; i < len; i++ ) { var fur:FurInfo = furs[i]; drawFur( fur.x, fur.y, fur.vx - ax, fur.vy + Math.abs(ax), fur.dx, fur.colors); } } // 毛を描く private function drawFur(x:Number, y:Number, vx:Number, vy:Number, dx:Number, colors:Array):void { var x0:Number = x + vx * 0.45; var y0:Number = y + vy * 0.65; var x1:Number = x + vx + draw_gravity; var y1:Number = y + vy; var d:Number = Math.sqrt( vx * vx + vy * vy ) / 1.75; gmtx.createLinear( x, y, x1, y1 ); g.beginGradientFill( "linear", colors, furalphas, furratios, gmtx ); g.moveTo( x, y ); g.curveTo( x0+3, y0, x1, y1 ); vx /= d; vy /= d; g.curveTo( x0+vy, y0-vx, x+vy, y-vx ); g.endFill(); } // 2つの色を指定した割合で混ぜた色を返す(rate=0ならcolor0)。(ここもかなり軽量化できるはず。グラデーションをキャッシュとして使うとか) private function mixColor(color0:uint, color1:uint, rate:Number):uint{ if (rate <= 0) return color0; if (rate >= 1) return color1; var r:uint = (color0>>16) * (1-rate) + (color1>>16) * rate; var g:uint = ((color0 & 0x00ff00 ) >>8) * (1-rate) + ((color1 & 0x00ff00 ) >>8) * rate; var b:uint = (color0 & 0xff) * (1-rate) + (color1 & 0xff) * rate; return (r << 16) | (g << 8) | (b); } } } class FurInfo { public var x:Number; public var y:Number; public var vx:Number; public var vy:Number; public var dx:Number; public var colors:Array; public function FurInfo() { } } Code Fullscreen Preview Fullscreen hacker_97ryb.. FMath.dist graphics addEventListener mouseY mouseX Event.ADDED_TO_STAGE Math.abs Math.sqrt Math.PI push Array Event addChild length Event.ENTER_FRAME Math.sin uint Math.random Sprite int