Forked from: tkinjo's パーティクルテスト diff:199 カラーパーティクル カラーパーティクル 色はパーティクルにかかる力の方向で決定 @author tkinjo tkinjo forked:1favorite:1lines:249license : MIT License modified : 2009-11-01 00:36:56 Embed Tweet // forked from tkinjo's パーティクルテスト // forked from tkinjo's パーリンノイズの生成とフレームスキップ package { import flash.display.*; import flash.events.*; import flash.geom.*; import flash.utils.*; import net.hires.debug.Stats; [SWF(width="465", height="465", backgroundColor="0x0", frameRate="30")] /** * カラーパーティクル * * 色はパーティクルにかかる力の方向で決定 * * @author tkinjo */ public class Main extends Sprite { // farame skip setting private const FRAME_SKIP_MARGIN:uint = 0; // force map setting private const FORCE_MAP_CREATE_BY_ENTER_FRAME:Boolean = true; private const FORCE_MAP_SCALE:uint = 3; private const OFFSET_SPEED:Number = 1; private const NUM_OCTAVES:uint = 4; // particle setting private const PARTICLE_NUM:uint = 1000; private const FRAME_SKIP_DRAW_PARTICLE:Boolean = false; // view setting private const FADE_OUT_COLOR_TRANSFORM:ColorTransform = new ColorTransform( 1, 1, 1, 1, -8, -8, -8); private var stageWidth:Number = stage.stageWidth; private var stageHeight:Number = stage.stageHeight; private var frameSkipper:FrameSkipper; private var forceMapBitmap:Bitmap; private var forceMapBitmapData:BitmapData; private var offsets:Array; private var seed:uint; private var particles:Particle; private var viewBitmapData:BitmapData; private var viewBitmap:Bitmap; public function Main() { frameSkipper = new FrameSkipper( stage.frameRate, FRAME_SKIP_MARGIN ); forceMapBitmapData = new BitmapData( stageWidth >> FORCE_MAP_SCALE, stageHeight >> FORCE_MAP_SCALE ); offsets = new Array(); for ( var i:uint = 0; i < NUM_OCTAVES; i++ ) offsets.push( new Point() ); seed = Math.random() * 0xffff; // create particle var previousParticle:Particle = particles = new Particle( Math.random() * 465, Math.random() * 465 ); var particle:Particle; for ( i = 0; i < PARTICLE_NUM; i++) { previousParticle.next = particle = new Particle( Math.random() * 465, Math.random() * 465 ); previousParticle = particle; } // create view bitmap viewBitmapData = new BitmapData( stageWidth, stageHeight, false, 0x0 ); viewBitmap = new Bitmap( viewBitmapData ); addChild( viewBitmap ); addEventListener( Event.ENTER_FRAME, enterFrameHandler ); forceMapBitmap = new Bitmap( forceMapBitmapData ); forceMapBitmap.scaleX = 100 / forceMapBitmap.width forceMapBitmap.scaleY = 100 / forceMapBitmap.height; forceMapBitmap.x = stageWidth - forceMapBitmap.width; addChild( forceMapBitmap ); var hueCircle:HueCircle = new HueCircle( 50, 30 ); hueCircle.x = hueCircle.radius + stageWidth - hueCircle.width; hueCircle.y = hueCircle.radius + forceMapBitmap.height; hueCircle.graphics.beginFill( 0x0 ); hueCircle.graphics.drawRect( -hueCircle.radius, -hueCircle.radius, hueCircle.width, hueCircle.height ); hueCircle.graphics.endFill(); addChild( hueCircle ); if( !FORCE_MAP_CREATE_BY_ENTER_FRAME ) forceMapBitmapData.perlinNoise( stageHeight >> ( FORCE_MAP_SCALE + 1 ), stageHeight >> ( FORCE_MAP_SCALE + 1 ), NUM_OCTAVES, seed, true, true, 3, false, offsets ); addChild(new Stats); } private function enterFrameHandler( event:Event ):void { frameSkipper.update(); if ( FORCE_MAP_CREATE_BY_ENTER_FRAME && !frameSkipper.skip ) { var offset:Number = ( frameSkipper.skipped + 1 ) * ( OFFSET_SPEED / FORCE_MAP_SCALE ); for ( var i:uint = 0; i < NUM_OCTAVES; i++ ) { switch( i % 4 ) { case 0: offsets[i].x += offset; break; case 1: offsets[i].x -= offset; break; case 2: offsets[i].y += offset; break; case 3: offsets[i].y -= offset; break; } } forceMapBitmapData.lock(); forceMapBitmapData.perlinNoise( stageHeight >> ( FORCE_MAP_SCALE + 1 ), stageHeight >> ( FORCE_MAP_SCALE + 1 ), NUM_OCTAVES, seed, true, true, 3, false, offsets ); forceMapBitmapData.unlock(); } var particle:Particle = particles; var color:uint; var centerPoint:Point = new Point(); var force:Point = new Point(); viewBitmapData.lock(); if ( !FRAME_SKIP_DRAW_PARTICLE || ( FRAME_SKIP_DRAW_PARTICLE && !frameSkipper.skip ) ) viewBitmapData.colorTransform( viewBitmapData.rect, FADE_OUT_COLOR_TRANSFORM ); while ( ( particle = particle.next ) != null ) { color = forceMapBitmapData.getPixel( particle.x >> FORCE_MAP_SCALE, particle.y >> FORCE_MAP_SCALE ); particle.x += ( particle.vx = particle.vx * 0.98 + ( ( color >> 16 & 0xff ) - 128 ) * 0.005 ); particle.y += ( particle.vy = particle.vy * 0.98 + ( ( color >> 8 & 0xff ) - 128 ) * 0.005 ) ; if (particle.x < 0) particle.x += stageWidth; else if ( particle.x >= stageWidth ) particle.x -= stageWidth; if ( particle.y < 0 ) particle.y += stageHeight; else if ( particle.y >= stageHeight ) particle.y -= stageHeight; force.x = ( color >> 16 & 0xff ) - 128; force.y = ( color >> 8 & 0xff ) - 128; if ( !FRAME_SKIP_DRAW_PARTICLE || ( FRAME_SKIP_DRAW_PARTICLE && !frameSkipper.skip ) ) viewBitmapData.setPixel( particle.x, particle.y, getHueCircleColor( centerPoint, force ) ); } viewBitmapData.unlock(); } } } import flash.display.*; import flash.events.*; import flash.utils.*; import flash.geom.*; class Particle { public var vx:Number = 0; public var vy:Number = 0; public var x:int; public var y:int; public var next: Particle; function Particle( x:int, y:int ) { this.x = x; this.y = y; } } class FrameSkipper { /* ================================================== * property * ================================================== */ /** * スキップされたフレーム数 */ public function get skipped():uint { return _skipped; } private var _skipped:uint = 0; /** * スキップするべきときなら true、そうでないなら false * * --- 例 --- * if( !frameSkipper.skip ) * // フレームスキップしない時の処理(描画などの重い処理) * else * // フレームスキップするときの処理(描画をせずにデータ地だけ変更するなどの軽い処理) */ public function get skip():Boolean { return skipCounter >= 0; } /** * 保ちたい fps 値 */ public var expectedFPS:uint; /** * */ public var margin:uint; /* ================================================== * field * ================================================== */ private var previousTime:int = 0; private var currentTime:int = 0; private var skipCounter:int = 0; private var fps:uint; /* ================================================== * method * ================================================== */ public function FrameSkipper( expectedFPS:uint = 60, margin:uint = 0 ):void { this.expectedFPS = expectedFPS; this.margin = margin; } public function update():void { currentTime = getTimer(); fps = 1000 / ( currentTime - previousTime ); if ( !skip && fps < expectedFPS ) { _skipped = expectedFPS / fps + margin; skipCounter = skipped; } else skipCounter--; previousTime = currentTime; } } class HueCircle extends Sprite { public function get radius():Number { return _radius; } public function set radius(value:Number):void { _radius = value; draw(); } private var _radius:Number; public function get innerRadius():Number { return _innerRadius; } public function set innerRadius(value:Number):void { _innerRadius = value; draw(); } private var _innerRadius:Number; private var bitmap:Bitmap; private var circleMask:Sprite; public function HueCircle( radius:Number, innerRadius:Number = 0 ) { _radius = radius; _innerRadius = innerRadius; var diameter:Number = radius * 2; if ( hueCircleBitmapData == null ) resizeHueCircleBitmapData( diameter ); bitmap = new Bitmap( hueCircleBitmapData ); bitmap.cacheAsBitmap = true; addChild( bitmap ); circleMask = new Sprite(); circleMask.cacheAsBitmap = true; addChild( circleMask ); bitmap.mask = circleMask; draw(); } private function draw():void { circleMask.graphics.clear(); circleMask.graphics.beginFill( 0xffffff ); circleMask.graphics.drawCircle( radius, radius, radius); if( innerRadius != 0 ) circleMask.graphics.drawCircle( radius, radius, innerRadius ); circleMask.graphics.endFill(); var largeRadius:Number = ( ( radius > innerRadius ) ? radius : innerRadius ); bitmap.x = -largeRadius; bitmap.y = -largeRadius; bitmap.scaleX = largeRadius / ( hueCircleBitmapData.width / 2 ); bitmap.scaleY = largeRadius / ( hueCircleBitmapData.width / 2 ); circleMask.x = -radius; circleMask.y = -radius; } private static var hueCircleBitmapData:BitmapData; public static function resizeHueCircleBitmapData( width:Number ):void { var centerPoint:Point = new Point( width / 2, width / 2 ); var tempPoint:Point = new Point(); hueCircleBitmapData = new BitmapData( width, width, false ); hueCircleBitmapData.lock(); for ( var i:int = 0; i < width; i++ ) { for ( var j:int = 0; j < width; j++ ) { tempPoint.x = i; tempPoint.y = j; hueCircleBitmapData.setPixel( i, j, getHueCircleColor( centerPoint, tempPoint ) ); } } hueCircleBitmapData.unlock(); } } function getHueCircleColor( centerPoint:Point, point:Point ):uint { var pointFromCenterPoint:Point = point.subtract( centerPoint ); var pointBearingFromCenterPoint:Number = Math.atan2( pointFromCenterPoint.y, pointFromCenterPoint.x ) * 180 / Math.PI; if ( pointBearingFromCenterPoint < 0 ) pointBearingFromCenterPoint = pointBearingFromCenterPoint + 360; return HSVtoRGB( pointBearingFromCenterPoint, 1, 1 ); } function HSVtoRGB( h:Number, s:Number, v:Number ):uint { var Hi:uint = ( h / 60 ) % 6; var f:Number = h / 60 - Hi; var p:Number = v * ( 1 - s ); var q:Number = v * ( 1 - f * s ); var t:Number = v * ( 1 - ( 1 - f ) * s ); switch( Hi ) { case 0: return toRGB255( v, t, p ); case 1: return toRGB255( q, v, p ); case 2: return toRGB255( p, v, t ); case 3: return toRGB255( p, q, v ); case 4: return toRGB255( t, p, v ); case 5: return toRGB255( v, p, q ); } return 0; } function toRGB255( r:Number, g:Number, b:Number ):uint { return ( r * 255 << 16 ) + ( g * 255 << 8 ) + b * 255; } Code Fullscreen Preview Fullscreen narahater color color offset offset value value stageHeight stageWidth stageWidth Point Point cacheAsBitmap cacheAsBitmap draw draw perlinNoise perlinNoise addChild addChild Bitmap sort new page view favorite forked pv230 forked from: カラーパーティクル tkinjo forked:0 favorite:1lines:269 (diff:45)