// forked from checkmate's Creek challenge //途中 package { import flash.display.*; import flash.events.*; import flash.geom.*; import flash.net.*; import flash.utils.*; import flash.system.*; import com.flashdynamix.utils.*; [SWF(backgroundColor=0x000000, frameRate=60)] public class Sponsor extends Sprite { private var _gradientMap:BitmapData; private var _timer:Timer; private var _camera:Camera3D; private function setup():void{ _timer = new Timer( 800, 0 ); _timer.addEventListener( TimerEvent.TIMER, timerHadler ); _timer.start(); _camera = new Camera3D(); shotFirework(); _loader = new Loader(); _loader.contentLoaderInfo.addEventListener( Event.COMPLETE, onLoadComplete ); _loader.load( new URLRequest("http://level0.kayac.com/space.jpg"), new LoaderContext(true) ); } private var _loader:Loader; private var _background:DisplayObject; private function onLoadComplete(e:Event):void { _background = addChildAt( _loader.content, 0 ); } private var _fireworks:Vector.<Firework> = new Vector.<Firework>(); private function shotFirework():void { var fw:Firework =new Firework(); fw.shot( Math.random()*5 + 1 ); fw.x = Math.random() * 300 -150; fw.y = -Math.random() * 100 -50; fw.z = Math.random() * 300 -150; _fireworks.push( fw ); } private var _velocityWorldRot:Vector3D = new Vector3D(); private var _preMouse:Point = new Point(); private function updateCalcuration():void{ _velocityWorldRot.x += ( _preMouse.x - mouseX ) * 0.02; _velocityWorldRot.x *= 0.90; _velocityWorldRot.y += ( _preMouse.y- mouseY ) * 0.02; _velocityWorldRot.y *= 0.90; _preMouse.x = mouseX; _preMouse.y = mouseY; _world.appendRotation( _velocityWorldRot.x, Vector3D.Y_AXIS ); _world.appendRotation( _velocityWorldRot.y, Vector3D.X_AXIS ); for each( var fw:Firework in _fireworks ) fw.updateCalcuration(); } private var _world:Matrix3D = new Matrix3D(); private function updateDrawing():void{ //_background.rotationX = _canvas.colorTransform( _canvas.rect, CTF ); _canvas.lock(); for each( var fw:Firework in _fireworks ) { fw.draw( _canvas, _world, _camera ); } _canvas.unlock(); } private function timerHadler (e:Event):void{ var newFireworks:Vector.<Firework>= new Vector.<Firework>(); for each( var fw:Firework in _fireworks ) { fw.cleanup(); if( fw.isLiving ) newFireworks.push(fw); } _fireworks = newFireworks; shotFirework(); } private const CTF:ColorTransform = new ColorTransform( 0.94, 0.94, 0.94, 0.9 ); private var _canvas:BitmapData; private function init():void{ Firework.offset.x = stage.stageWidth*0.5>>0; Firework.offset.y = stage.stageHeight*0.5>>0; _canvas = new BitmapData( stage.stageWidth, stage.stageHeight, true, 0 ); addChild( new Bitmap(_canvas) ); setup(); addEventListener( Event.ENTER_FRAME, enterFrame); SWFProfiler.init( this ); } private function enterFrame( e:Event ):void { updateCalcuration(); updateDrawing(); } public function Sponsor() { addEventListener( Event.ADDED_TO_STAGE, addToStage ); } private function addToStage (e:Event):void { init(); } } } import flash.display.*; import flash.events.*; import flash.geom.*; import flash.net.*; import flash.utils.*; import flash.system.*; class Particle extends Vector3D { public var life:int; public var vx:Number; public var vy:Number; public var vz:Number; public var rmd:Number = Math.random()*0.005-0.0025; public function Particle( x:Number = 0, y:Number = 0, z:Number = 0, vx:Number = 0, vy:Number = 0, vz:Number = 0, life:int = 200 ) { super( x, y, z ); this.vx = vx; this.vy = vy; this.vz = vz; this.life = life; } } class Camera3D extends Vector3D { public var focus:int = 1000; public function Camera3D( x:Number = 0, y:Number = 0, z:Number = 0 ) { super( x, y, z ); } } class Firework extends Vector3D { private static const PARTICLES_LENGTH:int = 600; private static const COLORS:Array = [ 0xFFCCFF, 0xFF9999, 0xFFFF99, 0x99CCFF, 0xCCFF99 ]; private static const FRICTION:Vector3D = new Vector3D ( 0.94, 0.94, 0.94 ); private static const GRAVITY:Vector3D = new Vector3D ( 0, 0.008, 0 ); private static const WIND:Vector3D = new Vector3D ( 0.001, 0,0 ); public static var offset:Point = new Point(); private var _particles:Vector.<Particle> = new Vector.<Particle>(); private var _gradientMap:BitmapData; public function Firework() { updateGradiate(); } public function draw( canvas:BitmapData, world:Matrix3D, camera:Camera3D ):void { for each( var p:Particle in _particles ) { if ( p.life <= 0 ) continue; var projected:Vector3D = Utils3D.projectVector( world, p .add( this ) ); var persepective:Number = camera.focus / ( camera.focus + projected.z ); var px:Number = projected.x * persepective + offset.x; var py:Number = projected.y * persepective + offset.y; var a:uint = ( 255 * 5 / persepective ) << 24; canvas.setPixel32( px, py, getColor(p.life) | a ); } } private function updateGradiate():void { _gradientMap= new BitmapData(200,10, true, 0); var sp:Shape= new Shape(); var color:uint = COLORS[ Math.random()*COLORS.length>>0]; var mtx:Matrix = new Matrix(); mtx.createGradientBox(200, 0, 0, 0, 0); sp.graphics.beginGradientFill( GradientType.LINEAR, [ 0x333333, color, color, color*0.9>>0, 0x000000 ], [ 1, 1, 1, 1, 1 ], [ 8, 64, 102, 204, 255], mtx, InterpolationMethod.RGB ); sp.graphics.drawRect( 0, 0, 200, 10 ); sp.graphics.endFill(); _gradientMap.draw(sp); sp = null; } private function getColor(position:int):uint { return _gradientMap.getPixel( position, 0 ) | 0x00000000; } public function shot( radius:Number ):void { var radian:Number = Math.PI*2; for( var i :int=0; i<PARTICLES_LENGTH; i++ ) { var theta:Number = Math.random() *radian; var phi:Number = Math.random() *radian; var tx:Number = Math.sin(theta) * Math.sin(phi); var ty:Number = Math.sin(theta) * Math.cos(phi); var tz:Number = Math.cos(theta); var sl:Number = Math.random()*radius * 0.5; var vl:Number = Math.random()*( 0.2 )*radius + 0.8 * radius; var particle :Particle= new Particle( tx*sl, ty*sl, tz*sl, tx*vl, ty*vl, tz*vl, 100 ); _particles.push(particle); } } public function get isLiving():Boolean { return _particles.length > 0; } public function updateCalcuration():void{ for each( var p:Particle in _particles ) { p.vx = p.vx * FRICTION.x + WIND.x + GRAVITY.x + p.rmd; p.vy = p.vy * FRICTION.y + WIND.y + GRAVITY.y + p.rmd; p.vz = p.vz * FRICTION.z + WIND.z + GRAVITY.z + p.rmd; p.x = p.x + p.vx; p.y = p.y + p.vy; p.z = p.z + p.vz; p.life--; } _particles = _particles.sort( _sort ); } private function _sort(a:Vector3D, b:Vector3D):Number { return a.z > b.z ? -1 : a.z < b.z ? 1 : 0; } public function cleanup():void { var newParticles:Vector.<Particle> = new Vector.<Particle>(); for each( var p:Particle in _particles ) { if( p.life > 0 ) newParticles.push(p); } _particles = newParticles; } } 3DFireworks