FORKED

forked from: forked from: PS2 Firework (Particles and Motion blur) forked from: forked from: forked from: PS2 Firework (Particles and Motion blur) [diff(4)]

  1. // forked from hacker_fhynon_3's forked from: forked from: PS2 Firework (Particles and Motion blur)
  2. // forked from rintarock's forked from: PS2 Firework (Particles and Motion blur)
  3. // forked from kohring's PS2 Firework (Particles and Motion blur)
  4. package {
  5.     import flash.display.*;
  6.     import flash.events.*;
  7.     import flash.filters.*;
  8.     import flash.geom.*;
  9.     import flash.text.*;
  10.     import flash.utils.*;
  11.     [SWF(width="465", height="465", frameRate="60")]
  12.     public class Firework extends Sprite
  13.     {
  14.         // 火花
  15.         private var position:Vector.<Number> = new Vector.<Number>();
  16.         private var velocity:Vector.<Number> = new Vector.<Number>();
  17.         private var diameters:Vector.<Number> = new Vector.<Number>();
  18.         private var sparkNumber:Number = 0;
  19.         
  20.         private var projectedPosition:Vector.<Number> = new Vector.<Number>();
  21.         private var uvts:Vector.<Number> = new Vector.<Number>();
  22.         
  23.         private var sparkBitmapDatas:Vector.<BitmapData> = new Vector.<BitmapData>();
  24.         private var sparkBitmapDataRectangles:Vector.<Rectangle> = new Vector.<Rectangle>();
  25.         private const SPARK_COLOR:uint = 0x3355ff;
  26.         
  27.         private const GRAVITY:Number = 0.04;
  28.         private const AIR_RESISTANCE:Number = 0.995;
  29.         
  30.         // 1フレームに放出する火花の数
  31.         private const EMIT_SPARK_NUMBER:int = 1;
  32.         
  33.         // 照り返し
  34.         private var reflectionBitmapData:BitmapData;
  35.         private const REFLECTION_COLOR:uint = 0xFF1800;
  36.         private const REFLECTION_RADIUS:Number = 16;
  37.         
  38.         // フレームバッファ
  39.         private var displayBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  40.         private var splitBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  41.         private const NUMBER_OF_SPLIT_FRAME:int = 10;
  42.         
  43.         private var perspective:PerspectiveProjection = new PerspectiveProjection();
  44.         private var projectionMatrix:Matrix3D = new Matrix3D();
  45.         
  46.         private var viewRotationY:Number = 0;
  47.         private var viewRotationX:Number = 25;
  48.         
  49.         private const CENTER_X:Number = stage.stageWidth / 2;
  50.         private const CENTER_Y:Number = stage.stageHeight * 0.65;
  51.         
  52.         private var stats:TextField = new TextField();
  53.         
  54.         public function Firework()
  55.         {
  56.             addChild(new Bitmap(displayBuffer));
  57.             stats.x = 5;
  58.             stats.y = 5;
  59.             stats.autoSize = TextFieldAutoSize.LEFT;
  60.             stats.textColor = 0xFFFFFF;
  61.             addChild(stats);
  62.             
  63.             var shape:Shape = new Shape();
  64.             var g:Graphics = shape.graphics;
  65.             
  66.             // 火花のプリレンダリング
  67.             var bitmapData:BitmapData = new BitmapData(11true, SPARK_COLOR);
  68.             sparkBitmapDatas.push(bitmapData);
  69.             sparkBitmapDataRectangles.push(bitmapData.rect);
  70.             
  71.             for (var diameter:int = 1; diameter <= 32; diameter++) {
  72.                 bitmapData = new BitmapData(diameter, diameter, true0);
  73.                 
  74.                 g.clear();
  75.                 g.beginFill(SPARK_COLOR);
  76.                 var radius:Number = diameter / 2;
  77.                 g.drawCircle(radius, radius, radius);
  78.                 g.endFill();
  79.                 bitmapData.draw(shape);
  80.                 
  81.                 sparkBitmapDatas.push(bitmapData);
  82.                 sparkBitmapDataRectangles.push(bitmapData.rect);
  83.                 // bitmapData.rectはアクセサで重いのでキャッシュしておく。これにより30%ほど高速化
  84.             }
  85.             
  86.             // 照り返しのプリレンダリング
  87.             reflectionBitmapData = new BitmapData(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2true0);
  88.             g.clear();
  89.             var matrix:Matrix = new Matrix();
  90.             matrix.createGradientBox(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2000);
  91.             g.beginGradientFill(GradientType.RADIAL, [ REFLECTION_COLOR, REFLECTION_COLOR ], [ 10 ], [ 0255 ], matrix);
  92.             g.drawCircle(REFLECTION_RADIUS, REFLECTION_RADIUS, REFLECTION_RADIUS);
  93.             g.endFill();
  94.             reflectionBitmapData.draw(shape);
  95.             
  96.             createFireworkModel();
  97.             
  98.             addEventListener(Event.ENTER_FRAME, enterFrameHandler);
  99. //            stage.addEventListener(MouseEvent.CLICK, function (e:Event):void {
  100. //                emitSpark();
  101. //            });
  102.         }
  103.         
  104.         private function enterFrameHandler(e:Event):void
  105.         {
  106.             displayBuffer.fillRect(displayBuffer.rect, 0);
  107.             
  108.             setupProjectionMatrix();
  109.             
  110.             var startTime:uint = getTimer();
  111.             renderFloor();
  112.             var floorRenderingTime:uint = getTimer() - startTime;
  113.             
  114.             startTime = getTimer();
  115.             for (var i:int = 0; i < NUMBER_OF_SPLIT_FRAME; i++) {
  116.                 const FACTOR:Number = 0.06;
  117.                 viewRotationY += (getTimer() * 0.01 + (-(CENTER_X - mouseX) * 0.4) - viewRotationY) * FACTOR;
  118.                 viewRotationX += ((27 + (CENTER_Y - mouseY) * 0.15) - viewRotationX) * FACTOR;
  119.                 
  120.                 setupProjectionMatrix();
  121.                 
  122.                 for (var j:int = 0; j < EMIT_SPARK_NUMBER; j++) {
  123.                     emitSpark();
  124.                 }
  125.                 updateSparks();
  126.                 renderSparks();
  127.             }
  128.             var sparksRenderingTime:uint = getTimer() - startTime;
  129.             
  130.             stats.text = 
  131.                 "Number of Sparks : " + sparkNumber + "\n" + 
  132.                 "Floor Rendering Time : " + floorRenderingTime + " ms\n" + 
  133.                 "Sparks Rendering Time : " + sparksRenderingTime + " ms \n";
  134.         }
  135.         
  136.         private function setupProjectionMatrix():void
  137.         {
  138.             perspective.fieldOfView = 60;
  139.             
  140.             projectionMatrix.identity();
  141.             projectionMatrix.appendRotation(viewRotationY, Vector3D.Y_AXIS);
  142.             projectionMatrix.appendRotation(viewRotationX, Vector3D.X_AXIS);
  143.             projectionMatrix.appendTranslation(00, perspective.focalLength);
  144.             projectionMatrix.append(perspective.toMatrix3D());
  145.             
  146.             correctMatrix3DMultiplyBug(projectionMatrix);
  147.         }
  148.         
  149.         private function correctMatrix3DMultiplyBug(matrix:Matrix3D):void
  150.         {
  151.             // see http://bugs.adobe.com/jira/browse/FP-670
  152.             var m1:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0000,  0010 ]));
  153.             var m2:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0001,  0000 ]));
  154.             m1.append(m2);
  155.             if (m1.rawData[15] == 20) {
  156.                 // バグ持ち!
  157.                 var rawData:Vector.<Number> = matrix.rawData;
  158.                 rawData[15] /= 20;
  159.                 matrix.rawData = rawData;
  160.             }
  161.         }
  162.         
  163.         private function createSpark(x:Number, y:Number, z:Number, vx:Number, vy:Number, vz:Number, diameter:Number):void
  164.         {
  165.             position.push(x, y, z);
  166.             velocity.push(vx, vy, vz);
  167.             diameters.push(diameter);
  168.             sparkNumber++;
  169.         }
  170.         
  171.         private function emitSpark():void
  172.         {
  173.             var azimuth:Number = Math.random() * 2 * Math.PI;
  174.             var vy:Number = -(Math.random() * 0.06 + 0.94);
  175.             var vx:Number = Math.sqrt(1 - vy * vy) * Math.cos(azimuth);
  176.             var vz:Number = Math.sqrt(1 - vy * vy) * Math.sin(azimuth);
  177.             
  178.             var speed:Number = Math.random() * 2.3 + 0.7;
  179.             vx *= speed;
  180.             vy *= speed;
  181.             vz *= speed;
  182.             
  183.             var diameter:Number = 3 + Math.random() * 3;
  184.             createSpark(0, -FIREWORK_HEIGHT, 0, vx, vy, vz, diameter);
  185.         }
  186.         
  187.         private function updateSparks():void
  188.         {
  189.             for (var i:int = 0; i < sparkNumber; ) {
  190.                 var xIndex:int = i * 3;
  191.                 var yIndex:int = xIndex + 1;
  192.                 var zIndex:int = xIndex + 2;
  193.                 
  194.                 velocity[yIndex] += GRAVITY;
  195.                 
  196.                 velocity[xIndex] *= AIR_RESISTANCE;
  197.                 velocity[yIndex] *= AIR_RESISTANCE;
  198.                 velocity[zIndex] *= AIR_RESISTANCE;
  199.                 
  200.                 if (position[yIndex] + velocity[yIndex] > 0) {
  201.                     velocity[yIndex] = -velocity[yIndex] * 0.2;
  202.                     
  203.                     position[xIndex] += velocity[xIndex];
  204.                     position[yIndex] += velocity[yIndex];
  205.                     position[zIndex] += velocity[zIndex];
  206.                     
  207.                     // 小さい火花に分割
  208.                     const DIAMETER_MIN:Number = 2;
  209.                     if (diameters[i] > DIAMETER_MIN) {
  210.                         var diameterLimit:Number = diameters[i];
  211.                         
  212.                         while (1) {
  213.                             var diameter:Number = Math.random() * (4 - DIAMETER_MIN) + DIAMETER_MIN;
  214.                             diameterLimit -= diameter;
  215.                             if (diameterLimit < 0) {
  216.                                 break;
  217.                             }
  218.                             var azimuth:Number = Math.random() * 2 * Math.PI;
  219.                             var r:Number = Math.random() * 2;
  220.                             
  221.                             createSpark(position[xIndex], position[yIndex], position[zIndex], 
  222.                                 (velocity[xIndex] + Math.cos(azimuth) * r) * 0.5
  223.                                 velocity[yIndex], 
  224.                                 (velocity[zIndex] + Math.sin(azimuth) * r) * 0.5
  225.                                 diameter);
  226.                         }
  227.                     }
  228.                     
  229.                     // spliceは重い!
  230. //                    position.splice(xIndex, 3);
  231. //                    velocity.splice(xIndex, 3); 
  232. //                    diameters.splice(i, 1);
  233.                     position[xIndex] = position[sparkNumber * 3 - 3];
  234.                     position[yIndex] = position[sparkNumber * 3 - 2];
  235.                     position[zIndex] = position[sparkNumber * 3 - 1];
  236.                     velocity[xIndex] = velocity[sparkNumber * 3 - 3];
  237.                     velocity[yIndex] = velocity[sparkNumber * 3 - 2];
  238.                     velocity[zIndex] = velocity[sparkNumber * 3 - 1];
  239.                     
  240.                     diameters[i] = diameters[sparkNumber - 1];
  241.                     
  242.                     position.pop();
  243.                     position.pop();
  244.                     position.pop();
  245.                     velocity.pop();
  246.                     velocity.pop();
  247.                     velocity.pop();
  248.                     
  249.                     diameters.pop();
  250.                     
  251.                     sparkNumber--;
  252.                     continue;
  253.                 }
  254.                 position[xIndex] += velocity[xIndex];
  255.                 position[yIndex] += velocity[yIndex];
  256.                 position[zIndex] += velocity[zIndex];
  257.                 
  258.                 i++;
  259.             }
  260.         }
  261.         
  262.         private function renderSparks():void
  263.         {
  264.             splitBuffer.fillRect(splitBuffer.rect, 0x000000);
  265.             
  266.             Utils3D.projectVectors(projectionMatrix, position, projectedPosition, uvts);
  267.             
  268.             // ループ外に追い出したら30%以上高速化
  269.             var p:Point = new Point();
  270.             var focalLength:Number = perspective.focalLength;
  271.             
  272.             for (var i:int = 0; i < sparkNumber; i++) {
  273.                 // パーティクルの大きさ = 1/z * focalLength * pixel
  274.                 var diameter:int = uvts[i * 3 + 2] * focalLength * diameters[i] + 0.5;
  275.                 // (i * 2) => (i << 1)で10%ほど高速化
  276.                 p.x = CENTER_X + projectedPosition[(i << 1)    ] - diameter / 2;
  277.                 p.y = CENTER_Y + projectedPosition[(i << 1) + 1] - diameter / 2;
  278.                 splitBuffer.copyPixels(sparkBitmapDatas[diameter], sparkBitmapDataRectangles[diameter], p);
  279.             }
  280.             
  281.             displayBuffer.draw(splitBuffer, nullnull, BlendMode.ADD);
  282.         }
  283.         
  284.         private const FLOOR_SIZE:Number = 300;
  285.         private const FLOOR_HALFSIZE:Number = FLOOR_SIZE / 2;
  286.         private const FLOOR_VERTICES:Vector.<Number> = Vector.<Number>([
  287.              FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  288.             -FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  289.             -FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  290.              FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  291.              
  292.              FLOOR_HALFSIZE, 0,               0
  293.             -FLOOR_HALFSIZE, 0,               0
  294.                           00,  FLOOR_HALFSIZE, 
  295.                           00, -FLOOR_HALFSIZE, 
  296.         ]);
  297.         private const FLOOR_VERTEX_NUMBER:int = FLOOR_VERTICES.length / 3;
  298.         
  299.         private var floorProjectedVertices:Vector.<Number> = new Vector.<Number>();
  300.         private var floorIndices:Vector.<int> = Vector.<int>([
  301.             012,  230
  302.         ]);
  303.         private var floorUvts:Vector.<Number> = Vector.<Number>([
  304.             100,  000,  010,  110,  
  305.             000,  000,  000,  000
  306.         ]);
  307.         
  308.         private const TEXTURE_SIZE:int = 150;
  309.         private var floorTexture:BitmapData = new BitmapData(TEXTURE_SIZE, TEXTURE_SIZE, false);
  310.         
  311.         private const WIREFRAME_COLOR:uint = 0x555566;
  312.         
  313.         private var sprite:Sprite = new Sprite();
  314.         
  315.         private function renderFloor():void
  316.         {
  317.             // 照り返しを描画する閾値
  318.             const THRESHOLD_Y:Number = 50;
  319.             
  320.             var matrix:Matrix = new Matrix();
  321.             var colorTransform:ColorTransform = new ColorTransform();
  322.             
  323.             floorTexture.fillRect(floorTexture.rect, 0x180C00);
  324.             
  325.             for (var i:int = 0; i < sparkNumber; i++) {
  326.                 var yIndex:int = i * 3 + 1;
  327.                 
  328.                 if (position[yIndex] > -THRESHOLD_Y) {
  329.                     var xIndex:int = i * 3;
  330.                     var zIndex:int = i * 3 + 2;
  331.                     
  332.                     matrix.identity();
  333.                     var scale:Number = (0.2 - (position[yIndex] / THRESHOLD_Y) * 0.8) * diameters[i];
  334.                     matrix.scale(scale, scale);
  335.                     matrix.translate(FLOOR_HALFSIZE + position[xIndex] - REFLECTION_RADIUS * scale, FLOOR_HALFSIZE - position[zIndex] - REFLECTION_RADIUS * scale);
  336.                     matrix.scale(TEXTURE_SIZE / FLOOR_SIZE, TEXTURE_SIZE / FLOOR_SIZE);
  337.                     
  338.                     colorTransform.alphaMultiplier = 1 + position[yIndex] / THRESHOLD_Y;
  339.                     floorTexture.draw(reflectionBitmapData, matrix, colorTransform, BlendMode.ADD);
  340.                 }
  341.             }
  342.             
  343.             Utils3D.projectVectors(projectionMatrix, FLOOR_VERTICES, floorProjectedVertices, floorUvts);
  344.             for (i = 0; i < FLOOR_VERTEX_NUMBER; i++) {
  345.                 floorProjectedVertices[(i << 1)    ] += CENTER_X;
  346.                 floorProjectedVertices[(i << 1) + 1] += CENTER_Y;
  347.             }
  348.             
  349.             Utils3D.projectVectors(projectionMatrix, fireworkVertices, fireworkProjectedVertices, fireworkUvts);
  350.             for (i = 0; i < fireworkProjectedVertices.length / 2; i++) {
  351.                 fireworkProjectedVertices[(i << 1)    ] += CENTER_X;
  352.                 fireworkProjectedVertices[(i << 1) + 1] += CENTER_Y;
  353.             }
  354.             
  355.             var g:Graphics = sprite.graphics;
  356.             g.clear();
  357.             g.beginBitmapFill(floorTexture);
  358.             g.drawTriangles(floorProjectedVertices, floorIndices, floorUvts);
  359.             g.endFill();
  360.             displayBuffer.draw(sprite);
  361.             
  362.             g.clear();
  363.             g.lineStyle(1, WIREFRAME_COLOR);
  364.             g.moveTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  365.             g.lineTo(floorProjectedVertices[2], floorProjectedVertices[3]);
  366.             g.lineTo(floorProjectedVertices[4], floorProjectedVertices[5]);
  367.             g.lineTo(floorProjectedVertices[6], floorProjectedVertices[7]);
  368.             g.lineTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  369.             
  370.             g.moveTo(floorProjectedVertices[8], floorProjectedVertices[9]);
  371.             g.lineTo(floorProjectedVertices[10], floorProjectedVertices[11]);
  372.             g.moveTo(floorProjectedVertices[12], floorProjectedVertices[13]);
  373.             g.lineTo(floorProjectedVertices[14], floorProjectedVertices[15]);
  374.             displayBuffer.draw(sprite, nullnull, BlendMode.ADD);
  375.             
  376.             g.clear();
  377.             g.beginFill(FIREWORK_COLOR);
  378.             g.drawTriangles(fireworkProjectedVertices, fireworkIndices);
  379.             g.endFill();
  380.             displayBuffer.draw(sprite);
  381.         }
  382.         
  383.         private const FIREWORK_RADIUS:Number = 8;
  384.         private const FIREWORK_HEIGHT:Number = 40;
  385.         private const FIREWORK_COLOR:uint = 0xAACCFF;
  386.         
  387.         private var fireworkVertices:Vector.<Number> = new Vector.<Number>();
  388.         private var fireworkIndices:Vector.<int> = new Vector.<int>();
  389.         private var fireworkProjectedVertices:Vector.<Number> = new Vector.<Number>();
  390.         private var fireworkUvts:Vector.<Number> = new Vector.<Number>();
  391.         
  392.         private function createFireworkModel():void
  393.         {
  394.             const SEGMENT:int = 8;
  395.             for (var i:int = 0; i < SEGMENT; i++) {
  396.                 var x:Number = Math.cos(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  397.                 var z:Number = Math.sin(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  398.                 fireworkVertices.push(x, -FIREWORK_HEIGHT, z);
  399.                 fireworkVertices.push(x, 0, z);
  400.                 
  401.                 var i0:int = (i * 2    ) % (SEGMENT * 2);
  402.                 var i1:int = (i * 2 + 1) % (SEGMENT * 2);
  403.                 var i2:int = (i * 2 + 2) % (SEGMENT * 2);
  404.                 var i3:int = (i * 2 + 3) % (SEGMENT * 2);
  405.                 fireworkIndices.push(i2, i0, i1);
  406.                 fireworkIndices.push(i1, i3, i2);
  407.             }
  408.         }
  409.     }
  410. }
noswf

forked from: forked from: PS2 Firework (Particles and Motion blur) forked from: forked from: forked from: PS2 Firework (Particles and Motion blur) [diff(4)]

  1. // forked from hacker_fhynon_3's forked from: forked from: PS2 Firework (Particles and Motion blur)
  2. // forked from rintarock's forked from: PS2 Firework (Particles and Motion blur)
  3. // forked from kohring's PS2 Firework (Particles and Motion blur)
  4. package {
  5.     import flash.display.*;
  6.     import flash.events.*;
  7.     import flash.filters.*;
  8.     import flash.geom.*;
  9.     import flash.text.*;
  10.     import flash.utils.*;
  11.     [SWF(width="465", height="465", frameRate="60")]
  12.     public class Firework extends Sprite
  13.     {
  14.         // 火花
  15.         private var position:Vector.<Number> = new Vector.<Number>();
  16.         private var velocity:Vector.<Number> = new Vector.<Number>();
  17.         private var diameters:Vector.<Number> = new Vector.<Number>();
  18.         private var sparkNumber:Number = 0;
  19.         
  20.         private var projectedPosition:Vector.<Number> = new Vector.<Number>();
  21.         private var uvts:Vector.<Number> = new Vector.<Number>();
  22.         
  23.         private var sparkBitmapDatas:Vector.<BitmapData> = new Vector.<BitmapData>();
  24.         private var sparkBitmapDataRectangles:Vector.<Rectangle> = new Vector.<Rectangle>();
  25.         private const SPARK_COLOR:uint = 0x664020;
  26.         
  27.         private const GRAVITY:Number = 0.02;
  28.         private const AIR_RESISTANCE:Number = 0.999;
  29.         
  30.         // 1フレームに放出する火花の数
  31.         private const EMIT_SPARK_NUMBER:int = 1;
  32.         
  33.         // 照り返し
  34.         private var reflectionBitmapData:BitmapData;
  35.         private const REFLECTION_COLOR:uint = 0xFFac00;
  36.         private const REFLECTION_RADIUS:Number = 16;
  37.         
  38.         // フレームバッファ
  39.         private var displayBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  40.         private var splitBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  41.         private const NUMBER_OF_SPLIT_FRAME:int = 10;
  42.         
  43.         private var perspective:PerspectiveProjection = new PerspectiveProjection();
  44.         private var projectionMatrix:Matrix3D = new Matrix3D();
  45.         
  46.         private var viewRotationY:Number = 0;
  47.         private var viewRotationX:Number = 25;
  48.         
  49.         private const CENTER_X:Number = stage.stageWidth / 2;
  50.         private const CENTER_Y:Number = stage.stageHeight * 1.65;
  51.         
  52.         private var stats:TextField = new TextField();
  53.         
  54.         public function Firework()
  55.         {
  56.             addChild(new Bitmap(displayBuffer));
  57.             stats.x = 5;
  58.             stats.y = 5;
  59.             stats.autoSize = TextFieldAutoSize.LEFT;
  60.             stats.textColor = 0xFFFFFF;
  61.             addChild(stats);
  62.             
  63.             var shape:Shape = new Shape();
  64.             var g:Graphics = shape.graphics;
  65.             
  66.             // 火花のプリレンダリング
  67.             var bitmapData:BitmapData = new BitmapData(11true, SPARK_COLOR);
  68.             sparkBitmapDatas.push(bitmapData);
  69.             sparkBitmapDataRectangles.push(bitmapData.rect);
  70.             
  71.             for (var diameter:int = 1; diameter <= 32; diameter++) {
  72.                 bitmapData = new BitmapData(diameter, diameter, true0);
  73.                 
  74.                 g.clear();
  75.                 g.beginFill(SPARK_COLOR);
  76.                 var radius:Number = diameter / 2;
  77.                 g.drawCircle(radius, radius, radius);
  78.                 g.endFill();
  79.                 bitmapData.draw(shape);
  80.                 
  81.                 sparkBitmapDatas.push(bitmapData);
  82.                 sparkBitmapDataRectangles.push(bitmapData.rect);
  83.                 // bitmapData.rectはアクセサで重いのでキャッシュしておく。これにより30%ほど高速化
  84.             }
  85.             
  86.             // 照り返しのプリレンダリング
  87.             reflectionBitmapData = new BitmapData(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2true0);
  88.             g.clear();
  89.             var matrix:Matrix = new Matrix();
  90.             matrix.createGradientBox(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2000);
  91.             g.beginGradientFill(GradientType.RADIAL, [ REFLECTION_COLOR, REFLECTION_COLOR ], [ 10 ], [ 0255 ], matrix);
  92.             g.drawCircle(REFLECTION_RADIUS, REFLECTION_RADIUS, REFLECTION_RADIUS);
  93.             g.endFill();
  94.             reflectionBitmapData.draw(shape);
  95.             
  96.             createFireworkModel();
  97.             
  98.             addEventListener(Event.ENTER_FRAME, enterFrameHandler);
  99. //            stage.addEventListener(MouseEvent.CLICK, function (e:Event):void {
  100. //                emitSpark();
  101. //            });
  102.         }
  103.         
  104.         private function enterFrameHandler(e:Event):void
  105.         {
  106.             displayBuffer.fillRect(displayBuffer.rect, 0);
  107.             
  108.             setupProjectionMatrix();
  109.             
  110.             var startTime:uint = getTimer();
  111.             renderFloor();
  112.             var floorRenderingTime:uint = getTimer() - startTime;
  113.             
  114.             startTime = getTimer();
  115.             for (var i:int = 0; i < NUMBER_OF_SPLIT_FRAME; i++) {
  116.                 const FACTOR:Number = 0.06;
  117.                 viewRotationY += (getTimer() * 0.01 + (-(CENTER_X - mouseX) * 0.4) - viewRotationY) * FACTOR;
  118.                 viewRotationX += ((27 + (CENTER_Y - mouseY) * 0.15) - viewRotationX) * FACTOR;
  119.                 
  120.                 setupProjectionMatrix();
  121.                 
  122.                 for (var j:int = 0; j < EMIT_SPARK_NUMBER; j++) {
  123.                     emitSpark();
  124.                 }
  125.                 updateSparks();
  126.                 renderSparks();
  127.             }
  128.             var sparksRenderingTime:uint = getTimer() - startTime;
  129.             
  130.             stats.text = 
  131.                 "Number of Sparks : " + sparkNumber + "\n" + 
  132.                 "Floor Rendering Time : " + floorRenderingTime + " ms\n" + 
  133.                 "Sparks Rendering Time : " + sparksRenderingTime + " ms \n";
  134.         }
  135.         
  136.         private function setupProjectionMatrix():void
  137.         {
  138.             perspective.fieldOfView = 60;
  139.             
  140.             projectionMatrix.identity();
  141.             projectionMatrix.appendRotation(viewRotationY, Vector3D.Y_AXIS);
  142.             projectionMatrix.appendRotation(viewRotationX, Vector3D.X_AXIS);
  143.             projectionMatrix.appendTranslation(00, perspective.focalLength);
  144.             projectionMatrix.append(perspective.toMatrix3D());
  145.             
  146.             correctMatrix3DMultiplyBug(projectionMatrix);
  147.         }
  148.         
  149.         private function correctMatrix3DMultiplyBug(matrix:Matrix3D):void
  150.         {
  151.             // see http://bugs.adobe.com/jira/browse/FP-670
  152.             var m1:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0000,  0010 ]));
  153.             var m2:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0001,  0000 ]));
  154.             m1.append(m2);
  155.             if (m1.rawData[15] == 20) {
  156.                 // バグ持ち!
  157.                 var rawData:Vector.<Number> = matrix.rawData;
  158.                 rawData[15] /= 20;
  159.                 matrix.rawData = rawData;
  160.             }
  161.         }
  162.         
  163.         private function createSpark(x:Number, y:Number, z:Number, vx:Number, vy:Number, vz:Number, diameter:Number):void
  164.         {
  165.             position.push(x, y, z);
  166.             velocity.push(vx, vy, vz);
  167.             diameters.push(diameter);
  168.             sparkNumber++;
  169.         }
  170.         
  171.         private function emitSpark():void
  172.         {
  173.             var azimuth:Number = Math.random() * 2 * Math.PI;
  174.             var vy:Number = -(Math.random() * 0.06 + 0.94);
  175.             var vx:Number = Math.sqrt(1 - vy * vy) * Math.cos(azimuth);
  176.             var vz:Number = Math.sqrt(1 - vy * vy) * Math.sin(azimuth);
  177.             
  178.             var speed:Number = Math.random() * 2.3 + 0.7;
  179.             vx *= speed;
  180.             vy *= speed;
  181.             vz *= speed;
  182.             
  183.             var diameter:Number = 3 + Math.random() * 3;
  184.             createSpark(0, -FIREWORK_HEIGHT, 0, vx, vy, vz, diameter);
  185.         }
  186.         
  187.         private function updateSparks():void
  188.         {
  189.             for (var i:int = 0; i < sparkNumber; ) {
  190.                 var xIndex:int = i * 3;
  191.                 var yIndex:int = xIndex + 1;
  192.                 var zIndex:int = xIndex + 2;
  193.                 
  194.                 velocity[yIndex] += GRAVITY;
  195.                 
  196.                 velocity[xIndex] *= AIR_RESISTANCE;
  197.                 velocity[yIndex] *= AIR_RESISTANCE;
  198.                 velocity[zIndex] *= AIR_RESISTANCE;
  199.                 
  200.                 if (position[yIndex] + velocity[yIndex] > 0) {
  201.                     velocity[yIndex] = -velocity[yIndex] * 0.2;
  202.                     
  203.                     position[xIndex] += velocity[xIndex];
  204.                     position[yIndex] += velocity[yIndex];
  205.                     position[zIndex] += velocity[zIndex];
  206.                     
  207.                     // 小さい火花に分割
  208.                     const DIAMETER_MIN:Number = 2;
  209.                     if (diameters[i] > DIAMETER_MIN) {
  210.                         var diameterLimit:Number = diameters[i];
  211.                         
  212.                         while (1) {
  213.                             var diameter:Number = Math.random() * (4 - DIAMETER_MIN) + DIAMETER_MIN;
  214.                             diameterLimit -= diameter;
  215.                             if (diameterLimit < 0) {
  216.                                 break;
  217.                             }
  218.                             var azimuth:Number = Math.random() * 2 * Math.PI;
  219.                             var r:Number = Math.random() * 2;
  220.                             
  221.                             createSpark(position[xIndex], position[yIndex], position[zIndex], 
  222.                                 (velocity[xIndex] + Math.cos(azimuth) * r) * 0.5
  223.                                 velocity[yIndex], 
  224.                                 (velocity[zIndex] + Math.sin(azimuth) * r) * 0.5
  225.                                 diameter);
  226.                         }
  227.                     }
  228.                     
  229.                     // spliceは重い!
  230. //                    position.splice(xIndex, 3);
  231. //                    velocity.splice(xIndex, 3); 
  232. //                    diameters.splice(i, 1);
  233.                     position[xIndex] = position[sparkNumber * 3 - 3];
  234.                     position[yIndex] = position[sparkNumber * 3 - 2];
  235.                     position[zIndex] = position[sparkNumber * 3 - 1];
  236.                     velocity[xIndex] = velocity[sparkNumber * 3 - 3];
  237.                     velocity[yIndex] = velocity[sparkNumber * 3 - 2];
  238.                     velocity[zIndex] = velocity[sparkNumber * 3 - 1];
  239.                     
  240.                     diameters[i] = diameters[sparkNumber - 1];
  241.                     
  242.                     position.pop();
  243.                     position.pop();
  244.                     position.pop();
  245.                     velocity.pop();
  246.                     velocity.pop();
  247.                     velocity.pop();
  248.                     
  249.                     diameters.pop();
  250.                     
  251.                     sparkNumber--;
  252.                     continue;
  253.                 }
  254.                 position[xIndex] += velocity[xIndex];
  255.                 position[yIndex] += velocity[yIndex];
  256.                 position[zIndex] += velocity[zIndex];
  257.                 
  258.                 i++;
  259.             }
  260.         }
  261.         
  262.         private function renderSparks():void
  263.         {
  264.             splitBuffer.fillRect(splitBuffer.rect, 0x000000);
  265.             
  266.             Utils3D.projectVectors(projectionMatrix, position, projectedPosition, uvts);
  267.             
  268.             // ループ外に追い出したら30%以上高速化
  269.             var p:Point = new Point();
  270.             var focalLength:Number = perspective.focalLength;
  271.             
  272.             for (var i:int = 0; i < sparkNumber; i++) {
  273.                 // パーティクルの大きさ = 1/z * focalLength * pixel
  274.                 var diameter:int = uvts[i * 3 + 2] * focalLength * diameters[i] + 0.5;
  275.                 // (i * 2) => (i << 1)で10%ほど高速化
  276.                 p.x = CENTER_X + projectedPosition[(i << 1)    ] - diameter / 2;
  277.                 p.y = CENTER_Y + projectedPosition[(i << 1) + 1] - diameter / 2;
  278.                 splitBuffer.copyPixels(sparkBitmapDatas[diameter], sparkBitmapDataRectangles[diameter], p);
  279.             }
  280.             
  281.             displayBuffer.draw(splitBuffer, nullnull, BlendMode.ADD);
  282.         }
  283.         
  284.         private const FLOOR_SIZE:Number = 300;
  285.         private const FLOOR_HALFSIZE:Number = FLOOR_SIZE / 2;
  286.         private const FLOOR_VERTICES:Vector.<Number> = Vector.<Number>([
  287.              FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  288.             -FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  289.             -FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  290.              FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  291.              
  292.              FLOOR_HALFSIZE, 0,               0
  293.             -FLOOR_HALFSIZE, 0,               0
  294.                           00,  FLOOR_HALFSIZE, 
  295.                           00, -FLOOR_HALFSIZE, 
  296.         ]);
  297.         private const FLOOR_VERTEX_NUMBER:int = FLOOR_VERTICES.length / 3;
  298.         
  299.         private var floorProjectedVertices:Vector.<Number> = new Vector.<Number>();
  300.         private var floorIndices:Vector.<int> = Vector.<int>([
  301.             012,  230
  302.         ]);
  303.         private var floorUvts:Vector.<Number> = Vector.<Number>([
  304.             100,  000,  010,  110,  
  305.             000,  000,  000,  000
  306.         ]);
  307.         
  308.         private const TEXTURE_SIZE:int = 150;
  309.         private var floorTexture:BitmapData = new BitmapData(TEXTURE_SIZE, TEXTURE_SIZE, false);
  310.         
  311.         private const WIREFRAME_COLOR:uint = 0x555566;
  312.         
  313.         private var sprite:Sprite = new Sprite();
  314.         
  315.         private function renderFloor():void
  316.         {
  317.             // 照り返しを描画する閾値
  318.             const THRESHOLD_Y:Number = 60;
  319.             
  320.             var matrix:Matrix = new Matrix();
  321.             var colorTransform:ColorTransform = new ColorTransform();
  322.             
  323.             floorTexture.fillRect(floorTexture.rect, 0x180C00);
  324.             
  325.             for (var i:int = 0; i < sparkNumber; i++) {
  326.                 var yIndex:int = i * 3 + 1;
  327.                 
  328.                 if (position[yIndex] > -THRESHOLD_Y) {
  329.                     var xIndex:int = i * 3;
  330.                     var zIndex:int = i * 3 + 2;
  331.                     
  332.                     matrix.identity();
  333.                     var scale:Number = (0.2 - (position[yIndex] / THRESHOLD_Y) * 0.8) * diameters[i];
  334.                     matrix.scale(scale, scale);
  335.                     matrix.translate(FLOOR_HALFSIZE + position[xIndex] - REFLECTION_RADIUS * scale, FLOOR_HALFSIZE - position[zIndex] - REFLECTION_RADIUS * scale);
  336.                     matrix.scale(TEXTURE_SIZE / FLOOR_SIZE, TEXTURE_SIZE / FLOOR_SIZE);
  337.                     
  338.                     colorTransform.alphaMultiplier = 1 + position[yIndex] / THRESHOLD_Y;
  339.                     floorTexture.draw(reflectionBitmapData, matrix, colorTransform, BlendMode.ADD);
  340.                 }
  341.             }
  342.             
  343.             Utils3D.projectVectors(projectionMatrix, FLOOR_VERTICES, floorProjectedVertices, floorUvts);
  344.             for (i = 0; i < FLOOR_VERTEX_NUMBER; i++) {
  345.                 floorProjectedVertices[(i << 1)    ] += CENTER_X;
  346.                 floorProjectedVertices[(i << 1) + 1] += CENTER_Y;
  347.             }
  348.             
  349.             Utils3D.projectVectors(projectionMatrix, fireworkVertices, fireworkProjectedVertices, fireworkUvts);
  350.             for (i = 0; i < fireworkProjectedVertices.length / 2; i++) {
  351.                 fireworkProjectedVertices[(i << 1)    ] += CENTER_X;
  352.                 fireworkProjectedVertices[(i << 1) + 1] += CENTER_Y;
  353.             }
  354.             
  355.             var g:Graphics = sprite.graphics;
  356.             g.clear();
  357.             g.beginBitmapFill(floorTexture);
  358.             g.drawTriangles(floorProjectedVertices, floorIndices, floorUvts);
  359.             g.endFill();
  360.             displayBuffer.draw(sprite);
  361.             
  362.             g.clear();
  363.             g.lineStyle(1, WIREFRAME_COLOR);
  364.             g.moveTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  365.             g.lineTo(floorProjectedVertices[2], floorProjectedVertices[3]);
  366.             g.lineTo(floorProjectedVertices[4], floorProjectedVertices[5]);
  367.             g.lineTo(floorProjectedVertices[6], floorProjectedVertices[7]);
  368.             g.lineTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  369.             
  370.             g.moveTo(floorProjectedVertices[8], floorProjectedVertices[9]);
  371.             g.lineTo(floorProjectedVertices[10], floorProjectedVertices[11]);
  372.             g.moveTo(floorProjectedVertices[12], floorProjectedVertices[13]);
  373.             g.lineTo(floorProjectedVertices[14], floorProjectedVertices[15]);
  374.             displayBuffer.draw(sprite, nullnull, BlendMode.ADD);
  375.             
  376.             g.clear();
  377.             g.beginFill(FIREWORK_COLOR);
  378.             g.drawTriangles(fireworkProjectedVertices, fireworkIndices);
  379.             g.endFill();
  380.             displayBuffer.draw(sprite);
  381.         }
  382.         
  383.         private const FIREWORK_RADIUS:Number = 8;
  384.         private const FIREWORK_HEIGHT:Number = 40;
  385.         private const FIREWORK_COLOR:uint = 0xAACCFF;
  386.         
  387.         private var fireworkVertices:Vector.<Number> = new Vector.<Number>();
  388.         private var fireworkIndices:Vector.<int> = new Vector.<int>();
  389.         private var fireworkProjectedVertices:Vector.<Number> = new Vector.<Number>();
  390.         private var fireworkUvts:Vector.<Number> = new Vector.<Number>();
  391.         
  392.         private function createFireworkModel():void
  393.         {
  394.             const SEGMENT:int = 8;
  395.             for (var i:int = 0; i < SEGMENT; i++) {
  396.                 var x:Number = Math.cos(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  397.                 var z:Number = Math.sin(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  398.                 fireworkVertices.push(x, -FIREWORK_HEIGHT, z);
  399.                 fireworkVertices.push(x, 0, z);
  400.                 
  401.                 var i0:int = (i * 2    ) % (SEGMENT * 2);
  402.                 var i1:int = (i * 2 + 1) % (SEGMENT * 2);
  403.                 var i2:int = (i * 2 + 2) % (SEGMENT * 2);
  404.                 var i3:int = (i * 2 + 3) % (SEGMENT * 2);
  405.                 fireworkIndices.push(i2, i0, i1);
  406.                 fireworkIndices.push(i1, i3, i2);
  407.             }
  408.         }
  409.     }
  410. }
noswf

forked from: forked from: PS2 Firework (Particles and Motion blur) forked from: forked from: forked from: PS2 Firework (Particles and Motion blur) [diff(9)]

  1. // forked from hacker_fhynon_3's forked from: forked from: PS2 Firework (Particles and Motion blur)
  2. // forked from rintarock's forked from: PS2 Firework (Particles and Motion blur)
  3. // forked from kohring's PS2 Firework (Particles and Motion blur)
  4. package {
  5.     import flash.display.*;
  6.     import flash.events.*;
  7.     import flash.filters.*;
  8.     import flash.geom.*;
  9.     import flash.text.*;
  10.     import flash.utils.*;
  11.     [SWF(width="465", height="465", frameRate="60")]
  12.     public class Firework extends Sprite
  13.     {
  14.         // 火花
  15.         private var position:Vector.<Number> = new Vector.<Number>();
  16.         private var velocity:Vector.<Number> = new Vector.<Number>();
  17.         private var diameters:Vector.<Number> = new Vector.<Number>();
  18.         private var sparkNumber:Number = 0;
  19.         
  20.         private var projectedPosition:Vector.<Number> = new Vector.<Number>();
  21.         private var uvts:Vector.<Number> = new Vector.<Number>();
  22.         
  23.         private var sparkBitmapDatas:Vector.<BitmapData> = new Vector.<BitmapData>();
  24.         private var sparkBitmapDataRectangles:Vector.<Rectangle> = new Vector.<Rectangle>();
  25.                 private var c_r:uint  = Math.random() *0xFF0000;
  26.                 private var c_g:uint  = Math.random() *0x00FF00;
  27.                 private var c_b:uint  = Math.random() *0x0000FF;
  28.         private var SPARK_COLOR:uint = 0x289733;
  29.                 //private var SPARK_COLOR:uint = c_r + c_g + c_b;
  30.         
  31.         private const GRAVITY:Number = 0.02;
  32.         private const AIR_RESISTANCE:Number = 0.999;
  33.         
  34.         // 1フレームに放出する火花の数
  35.         private const EMIT_SPARK_NUMBER:int = 1;
  36.         
  37.         // 照り返し
  38.         private var reflectionBitmapData:BitmapData;
  39.         private const REFLECTION_COLOR:uint = 0xFF1800;
  40.         private const REFLECTION_RADIUS:Number = 16;
  41.         
  42.         // フレームバッファ
  43.         private var displayBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  44.         private var splitBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  45.         private const NUMBER_OF_SPLIT_FRAME:int = 10;
  46.         
  47.         private var perspective:PerspectiveProjection = new PerspectiveProjection();
  48.         private var projectionMatrix:Matrix3D = new Matrix3D();
  49.         
  50.         private var viewRotationY:Number = 0;
  51.         private var viewRotationX:Number = 25;
  52.         
  53.         private const CENTER_X:Number = stage.stageWidth / 2;
  54.         private const CENTER_Y:Number = stage.stageHeight * 0.65;
  55.         
  56.         private var stats:TextField = new TextField();
  57.         
  58.         public function Firework()
  59.         {
  60.             addChild(new Bitmap(displayBuffer));
  61.             stats.x = 5;
  62.             stats.y = 5;
  63.             stats.autoSize = TextFieldAutoSize.LEFT;
  64.             stats.textColor = 0xFFFFFF;
  65.             addChild(stats);
  66.             
  67.             var shape:Shape = new Shape();
  68.             var g:Graphics = shape.graphics;
  69.             
  70.             // 火花のプリレンダリング
  71.             var bitmapData:BitmapData = new BitmapData(11true, SPARK_COLOR);
  72.             sparkBitmapDatas.push(bitmapData);
  73.             sparkBitmapDataRectangles.push(bitmapData.rect);
  74.             
  75.             for (var diameter:int = 1; diameter <= 32; diameter++) {
  76.                 bitmapData = new BitmapData(diameter, diameter, true0);
  77.                 
  78.                 g.clear();
  79.                 g.beginFill(SPARK_COLOR);
  80.                 var radius:Number = diameter / 2;
  81.                 g.drawCircle(radius, radius, radius);
  82.                 g.endFill();
  83.                 bitmapData.draw(shape);
  84.                 
  85.                 sparkBitmapDatas.push(bitmapData);
  86.                 sparkBitmapDataRectangles.push(bitmapData.rect);
  87.                 // bitmapData.rectはアクセサで重いのでキャッシュしておく。これにより30%ほど高速化
  88.             }
  89.             
  90.             // 照り返しのプリレンダリング
  91.             reflectionBitmapData = new BitmapData(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2true0);
  92.             g.clear();
  93.             var matrix:Matrix = new Matrix();
  94.             matrix.createGradientBox(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2000);
  95.             g.beginGradientFill(GradientType.RADIAL, [ REFLECTION_COLOR, REFLECTION_COLOR ], [ 10 ], [ 0255 ], matrix);
  96.             g.drawCircle(REFLECTION_RADIUS, REFLECTION_RADIUS, REFLECTION_RADIUS);
  97.             g.endFill();
  98.             reflectionBitmapData.draw(shape);
  99.             
  100.             createFireworkModel();
  101.             
  102.             addEventListener(Event.ENTER_FRAME, enterFrameHandler);
  103. //            stage.addEventListener(MouseEvent.CLICK, function (e:Event):void {
  104. //                emitSpark();
  105. //            });
  106.         }
  107.         
  108.         private function enterFrameHandler(e:Event):void
  109.         {
  110.             displayBuffer.fillRect(displayBuffer.rect, 0);
  111.             
  112.             setupProjectionMatrix();
  113.             
  114.             var startTime:uint = getTimer();
  115.             renderFloor();
  116.             var floorRenderingTime:uint = getTimer() - startTime;
  117.             
  118.             startTime = getTimer();
  119.             for (var i:int = 0; i < NUMBER_OF_SPLIT_FRAME; i++) {
  120.                 const FACTOR:Number = 0.06;
  121.                 viewRotationY += (getTimer() * 0.01 + (-(CENTER_X - mouseX) * 0.4) - viewRotationY) * FACTOR;
  122.                 viewRotationX += ((27 + (CENTER_Y - mouseY) * 0.15) - viewRotationX) * FACTOR;
  123.                 
  124.                 setupProjectionMatrix();
  125.                 
  126.                 for (var j:int = 0; j < EMIT_SPARK_NUMBER; j++) {
  127.                     emitSpark();
  128.                 }
  129.                 updateSparks();
  130.                 renderSparks();
  131.             }
  132.             var sparksRenderingTime:uint = getTimer() - startTime;
  133.             
  134.             stats.text = 
  135.                 "Number of Sparks : " + sparkNumber + "\n" + 
  136.                 "Floor Rendering Time : " + floorRenderingTime + " ms\n" + 
  137.                 "Sparks Rendering Time : " + sparksRenderingTime + " ms \n";
  138.         }
  139.         
  140.         private function setupProjectionMatrix():void
  141.         {
  142.             perspective.fieldOfView = 60;
  143.             
  144.             projectionMatrix.identity();
  145.             projectionMatrix.appendRotation(viewRotationY, Vector3D.Y_AXIS);
  146.             projectionMatrix.appendRotation(viewRotationX, Vector3D.X_AXIS);
  147.             projectionMatrix.appendTranslation(00, perspective.focalLength);
  148.             projectionMatrix.append(perspective.toMatrix3D());
  149.             
  150.             correctMatrix3DMultiplyBug(projectionMatrix);
  151.         }
  152.         
  153.         private function correctMatrix3DMultiplyBug(matrix:Matrix3D):void
  154.         {
  155.             // see http://bugs.adobe.com/jira/browse/FP-670
  156.             var m1:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0000,  0010 ]));
  157.             var m2:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0001,  0000 ]));
  158.             m1.append(m2);
  159.             if (m1.rawData[15] == 20) {
  160.                 // バグ持ち!
  161.                 var rawData:Vector.<Number> = matrix.rawData;
  162.                 rawData[15] /= 20;
  163.                 matrix.rawData = rawData;
  164.             }
  165.         }
  166.         
  167.         private function createSpark(x:Number, y:Number, z:Number, vx:Number, vy:Number, vz:Number, diameter:Number):void
  168.         {
  169.             position.push(x, y, z);
  170.             velocity.push(vx, vy, vz);
  171.             diameters.push(diameter);
  172.             sparkNumber++;
  173.         }
  174.         
  175.         private function emitSpark():void
  176.         {
  177.             var azimuth:Number = Math.random() * 2 * Math.PI;
  178.             var vy:Number = -(Math.random() * 0.06 + 0.94);
  179.             var vx:Number = Math.sqrt(1 - vy * vy) * Math.cos(azimuth);
  180.             var vz:Number = Math.sqrt(1 - vy * vy) * Math.sin(azimuth);
  181.             
  182.             var speed:Number = Math.random() * 2.3 + 0.7;
  183.             vx *= speed;
  184.             vy *= speed;
  185.             vz *= speed;
  186.             
  187.             var diameter:Number = 3 + Math.random() * 3;
  188.             createSpark(0, -FIREWORK_HEIGHT, 0, vx, vy, vz, diameter);
  189.         }
  190.         
  191.         private function updateSparks():void
  192.         {
  193.             for (var i:int = 0; i < sparkNumber; ) {
  194.                 var xIndex:int = i * 3;
  195.                 var yIndex:int = xIndex + 1;
  196.                 var zIndex:int = xIndex + 2;
  197.                 
  198.                 velocity[yIndex] += GRAVITY;
  199.                 
  200.                 velocity[xIndex] *= AIR_RESISTANCE;
  201.                 velocity[yIndex] *= AIR_RESISTANCE;
  202.                 velocity[zIndex] *= AIR_RESISTANCE;
  203.                 
  204.                 if (position[yIndex] + velocity[yIndex] > 0) {
  205.                     velocity[yIndex] = -velocity[yIndex] * 0.2;
  206.                     
  207.                     position[xIndex] += velocity[xIndex];
  208.                     position[yIndex] += velocity[yIndex];
  209.                     position[zIndex] += velocity[zIndex];
  210.                     
  211.                     // 小さい火花に分割
  212.                     const DIAMETER_MIN:Number = 2;
  213.                     if (diameters[i] > DIAMETER_MIN) {
  214.                         var diameterLimit:Number = diameters[i];
  215.                         
  216.                         while (1) {
  217.                             var diameter:Number = Math.random() * (4 - DIAMETER_MIN) + DIAMETER_MIN;
  218.                             diameterLimit -= diameter;
  219.                             if (diameterLimit < 0) {
  220.                                 break;
  221.                             }
  222.                             var azimuth:Number = Math.random() * 2 * Math.PI;
  223.                             var r:Number = Math.random() * 2;
  224.                             
  225.                             createSpark(position[xIndex], position[yIndex], position[zIndex], 
  226.                                 (velocity[xIndex] + Math.cos(azimuth) * r) * 0.5
  227.                                 velocity[yIndex], 
  228.                                 (velocity[zIndex] + Math.sin(azimuth) * r) * 0.5
  229.                                 diameter);
  230.                         }
  231.                     }
  232.                     
  233.                     // spliceは重い!
  234. //                    position.splice(xIndex, 3);
  235. //                    velocity.splice(xIndex, 3); 
  236. //                    diameters.splice(i, 1);
  237.                     position[xIndex] = position[sparkNumber * 3 - 3];
  238.                     position[yIndex] = position[sparkNumber * 3 - 2];
  239.                     position[zIndex] = position[sparkNumber * 3 - 1];
  240.                     velocity[xIndex] = velocity[sparkNumber * 3 - 3];
  241.                     velocity[yIndex] = velocity[sparkNumber * 3 - 2];
  242.                     velocity[zIndex] = velocity[sparkNumber * 3 - 1];
  243.                     
  244.                     diameters[i] = diameters[sparkNumber - 1];
  245.                     
  246.                     position.pop();
  247.                     position.pop();
  248.                     position.pop();
  249.                     velocity.pop();
  250.                     velocity.pop();
  251.                     velocity.pop();
  252.                     
  253.                     diameters.pop();
  254.                     
  255.                     sparkNumber--;
  256.                     continue;
  257.                 }
  258.                 position[xIndex] += velocity[xIndex];
  259.                 position[yIndex] += velocity[yIndex];
  260.                 position[zIndex] += velocity[zIndex];
  261.                 
  262.                 i++;
  263.             }
  264.         }
  265.         
  266.         private function renderSparks():void
  267.         {
  268.             splitBuffer.fillRect(splitBuffer.rect, 0x000000);
  269.             
  270.             Utils3D.projectVectors(projectionMatrix, position, projectedPosition, uvts);
  271.             
  272.             // ループ外に追い出したら30%以上高速化
  273.             var p:Point = new Point();
  274.             var focalLength:Number = perspective.focalLength;
  275.             
  276.             for (var i:int = 0; i < sparkNumber; i++) {
  277.                 // パーティクルの大きさ = 1/z * focalLength * pixel
  278.                 var diameter:int = uvts[i * 3 + 2] * focalLength * diameters[i] + 0.5;
  279.                 // (i * 2) => (i << 1)で10%ほど高速化
  280.                 p.x = CENTER_X + projectedPosition[(i << 1)    ] - diameter / 2;
  281.                 p.y = CENTER_Y + projectedPosition[(i << 1) + 1] - diameter / 2;
  282.                 splitBuffer.copyPixels(sparkBitmapDatas[diameter], sparkBitmapDataRectangles[diameter], p);
  283.             }
  284.             
  285.             displayBuffer.draw(splitBuffer, nullnull, BlendMode.ADD);
  286.         }
  287.         
  288.         private const FLOOR_SIZE:Number = 300;
  289.         private const FLOOR_HALFSIZE:Number = FLOOR_SIZE / 2;
  290.         private const FLOOR_VERTICES:Vector.<Number> = Vector.<Number>([
  291.              FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  292.             -FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  293.             -FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  294.              FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  295.              
  296.              FLOOR_HALFSIZE, 0,               0
  297.             -FLOOR_HALFSIZE, 0,               0
  298.                           00,  FLOOR_HALFSIZE, 
  299.                           00, -FLOOR_HALFSIZE, 
  300.         ]);
  301.         private const FLOOR_VERTEX_NUMBER:int = FLOOR_VERTICES.length / 3;
  302.         
  303.         private var floorProjectedVertices:Vector.<Number> = new Vector.<Number>();
  304.         private var floorIndices:Vector.<int> = Vector.<int>([
  305.             012,  230
  306.         ]);
  307.         private var floorUvts:Vector.<Number> = Vector.<Number>([
  308.             100,  000,  010,  110,  
  309.             000,  000,  000,  000
  310.         ]);
  311.         
  312.         private const TEXTURE_SIZE:int = 150;
  313.         private var floorTexture:BitmapData = new BitmapData(TEXTURE_SIZE, TEXTURE_SIZE, false);
  314.         
  315.         private const WIREFRAME_COLOR:uint = 0x555566;
  316.         
  317.         private var sprite:Sprite = new Sprite();
  318.         
  319.         private function renderFloor():void
  320.         {
  321.             // 照り返しを描画する閾値
  322.             const THRESHOLD_Y:Number = 50;
  323.             
  324.             var matrix:Matrix = new Matrix();
  325.             var colorTransform:ColorTransform = new ColorTransform();
  326.             
  327.             floorTexture.fillRect(floorTexture.rect, 0x180C00);
  328.             
  329.             for (var i:int = 0; i < sparkNumber; i++) {
  330.                 var yIndex:int = i * 3 + 1;
  331.                 
  332.                 if (position[yIndex] > -THRESHOLD_Y) {
  333.                     var xIndex:int = i * 3;
  334.                     var zIndex:int = i * 3 + 2;
  335.                     
  336.                     matrix.identity();
  337.                     var scale:Number = (0.2 - (position[yIndex] / THRESHOLD_Y) * 0.8) * diameters[i];
  338.                     matrix.scale(scale, scale);
  339.                     matrix.translate(FLOOR_HALFSIZE + position[xIndex] - REFLECTION_RADIUS * scale, FLOOR_HALFSIZE - position[zIndex] - REFLECTION_RADIUS * scale);
  340.                     matrix.scale(TEXTURE_SIZE / FLOOR_SIZE, TEXTURE_SIZE / FLOOR_SIZE);
  341.                     
  342.                     colorTransform.alphaMultiplier = 1 + position[yIndex] / THRESHOLD_Y;
  343.                     floorTexture.draw(reflectionBitmapData, matrix, colorTransform, BlendMode.ADD);
  344.                 }
  345.             }
  346.             
  347.             Utils3D.projectVectors(projectionMatrix, FLOOR_VERTICES, floorProjectedVertices, floorUvts);
  348.             for (i = 0; i < FLOOR_VERTEX_NUMBER; i++) {
  349.                 floorProjectedVertices[(i << 1)    ] += CENTER_X;
  350.                 floorProjectedVertices[(i << 1) + 1] += CENTER_Y;
  351.             }
  352.             
  353.             Utils3D.projectVectors(projectionMatrix, fireworkVertices, fireworkProjectedVertices, fireworkUvts);
  354.             for (i = 0; i < fireworkProjectedVertices.length / 2; i++) {
  355.                 fireworkProjectedVertices[(i << 1)    ] += CENTER_X;
  356.                 fireworkProjectedVertices[(i << 1) + 1] += CENTER_Y;
  357.             }
  358.             
  359.             var g:Graphics = sprite.graphics;
  360.             g.clear();
  361.             g.beginBitmapFill(floorTexture);
  362.             g.drawTriangles(floorProjectedVertices, floorIndices, floorUvts);
  363.             g.endFill();
  364.             displayBuffer.draw(sprite);
  365.             
  366.             g.clear();
  367.             g.lineStyle(1, WIREFRAME_COLOR);
  368.             g.moveTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  369.             g.lineTo(floorProjectedVertices[2], floorProjectedVertices[3]);
  370.             g.lineTo(floorProjectedVertices[4], floorProjectedVertices[5]);
  371.             g.lineTo(floorProjectedVertices[6], floorProjectedVertices[7]);
  372.             g.lineTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  373.             
  374.             g.moveTo(floorProjectedVertices[8], floorProjectedVertices[9]);
  375.             g.lineTo(floorProjectedVertices[10], floorProjectedVertices[11]);
  376.             g.moveTo(floorProjectedVertices[12], floorProjectedVertices[13]);
  377.             g.lineTo(floorProjectedVertices[14], floorProjectedVertices[15]);
  378.             displayBuffer.draw(sprite, nullnull, BlendMode.ADD);
  379.             
  380.             g.clear();
  381.             g.beginFill(FIREWORK_COLOR);
  382.             g.drawTriangles(fireworkProjectedVertices, fireworkIndices);
  383.             g.endFill();
  384.             displayBuffer.draw(sprite);
  385.         }
  386.         
  387.         private const FIREWORK_RADIUS:Number = 8;
  388.         private const FIREWORK_HEIGHT:Number = 40;
  389.         private const FIREWORK_COLOR:uint = 0xAACCFF;
  390.         
  391.         private var fireworkVertices:Vector.<Number> = new Vector.<Number>();
  392.         private var fireworkIndices:Vector.<int> = new Vector.<int>();
  393.         private var fireworkProjectedVertices:Vector.<Number> = new Vector.<Number>();
  394.         private var fireworkUvts:Vector.<Number> = new Vector.<Number>();
  395.         
  396.         private function createFireworkModel():void
  397.         {
  398.             const SEGMENT:int = 8;
  399.             for (var i:int = 0; i < SEGMENT; i++) {
  400.                 var x:Number = Math.cos(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  401.                 var z:Number = Math.sin(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  402.                 fireworkVertices.push(x, -FIREWORK_HEIGHT, z);
  403.                 fireworkVertices.push(x, 0, z);
  404.                 
  405.                 var i0:int = (i * 2    ) % (SEGMENT * 2);
  406.                 var i1:int = (i * 2 + 1) % (SEGMENT * 2);
  407.                 var i2:int = (i * 2 + 2) % (SEGMENT * 2);
  408.                 var i3:int = (i * 2 + 3) % (SEGMENT * 2);
  409.                 fireworkIndices.push(i2, i0, i1);
  410.                 fireworkIndices.push(i1, i3, i2);
  411.             }
  412.         }
  413.     }
  414. }
noswf

forked from: forked from: PS2 Firework (Particles and Motion blur) forked from: forked from: forked from: PS2 Firework (Particles and Motion blur) [diff(4)]

  1. // forked from hacker_fhynon_3's forked from: forked from: PS2 Firework (Particles and Motion blur)
  2. // forked from rintarock's forked from: PS2 Firework (Particles and Motion blur)
  3. // forked from kohring's PS2 Firework (Particles and Motion blur)
  4. package {
  5.     import flash.display.*;
  6.     import flash.events.*;
  7.     import flash.filters.*;
  8.     import flash.geom.*;
  9.     import flash.text.*;
  10.     import flash.utils.*;
  11.     [SWF(width="465", height="465", frameRate="60")]
  12.     public class Firework extends Sprite
  13.     {
  14.         // 火花
  15.         private var position:Vector.<Number> = new Vector.<Number>();
  16.         private var velocity:Vector.<Number> = new Vector.<Number>();
  17.         private var diameters:Vector.<Number> = new Vector.<Number>();
  18.         private var sparkNumber:Number = 0;
  19.         
  20.         private var projectedPosition:Vector.<Number> = new Vector.<Number>();
  21.         private var uvts:Vector.<Number> = new Vector.<Number>();
  22.         
  23.         private var sparkBitmapDatas:Vector.<BitmapData> = new Vector.<BitmapData>();
  24.         private var sparkBitmapDataRectangles:Vector.<Rectangle> = new Vector.<Rectangle>();
  25.         private const SPARK_COLOR:uint = 0xE0E215;
  26.         
  27.         private const GRAVITY:Number = 0.05;
  28.         private const AIR_RESISTANCE:Number = 1;
  29.         
  30.         // 1フレームに放出する火花の数
  31.         private const EMIT_SPARK_NUMBER:int = 1;
  32.         
  33.         // 照り返し
  34.         private var reflectionBitmapData:BitmapData;
  35.         private const REFLECTION_COLOR:uint = 0xFF1800;
  36.         private const REFLECTION_RADIUS:Number = 16;
  37.         
  38.         // フレームバッファ
  39.         private var displayBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  40.         private var splitBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  41.         private const NUMBER_OF_SPLIT_FRAME:int = 10;
  42.         
  43.         private var perspective:PerspectiveProjection = new PerspectiveProjection();
  44.         private var projectionMatrix:Matrix3D = new Matrix3D();
  45.         
  46.         private var viewRotationY:Number = 0;
  47.         private var viewRotationX:Number = 25;
  48.         
  49.         private const CENTER_X:Number = stage.stageWidth / 2;
  50.         private const CENTER_Y:Number = stage.stageHeight * 0.65;
  51.         
  52.         private var stats:TextField = new TextField();
  53.         
  54.         public function Firework()
  55.         {
  56.             addChild(new Bitmap(displayBuffer));
  57.             stats.x = 5;
  58.             stats.y = 5;
  59.             stats.autoSize = TextFieldAutoSize.LEFT;
  60.             stats.textColor = 0xFFFFFF;
  61.             addChild(stats);
  62.             
  63.             var shape:Shape = new Shape();
  64.             var g:Graphics = shape.graphics;
  65.             
  66.             // 火花のプリレンダリング
  67.             var bitmapData:BitmapData = new BitmapData(11true, SPARK_COLOR);
  68.             sparkBitmapDatas.push(bitmapData);
  69.             sparkBitmapDataRectangles.push(bitmapData.rect);
  70.             
  71.             for (var diameter:int = 1; diameter <= 32; diameter++) {
  72.                 bitmapData = new BitmapData(diameter, diameter, true0);
  73.                 
  74.                 g.clear();
  75.                 g.beginFill(SPARK_COLOR);
  76.                 var radius:Number = diameter / 2;
  77.                 g.drawCircle(radius, radius, radius);
  78.                 g.endFill();
  79.                 bitmapData.draw(shape);
  80.                 
  81.                 sparkBitmapDatas.push(bitmapData);
  82.                 sparkBitmapDataRectangles.push(bitmapData.rect);
  83.                 // bitmapData.rectはアクセサで重いのでキャッシュしておく。これにより30%ほど高速化
  84.             }
  85.             
  86.             // 照り返しのプリレンダリング
  87.             reflectionBitmapData = new BitmapData(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2true0);
  88.             g.clear();
  89.             var matrix:Matrix = new Matrix();
  90.             matrix.createGradientBox(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2000);
  91.             g.beginGradientFill(GradientType.RADIAL, [ REFLECTION_COLOR, REFLECTION_COLOR ], [ 10 ], [ 0255 ], matrix);
  92.             g.drawCircle(REFLECTION_RADIUS, REFLECTION_RADIUS, REFLECTION_RADIUS);
  93.             g.endFill();
  94.             reflectionBitmapData.draw(shape);
  95.             
  96.             createFireworkModel();
  97.             
  98.             addEventListener(Event.ENTER_FRAME, enterFrameHandler);
  99. //            stage.addEventListener(MouseEvent.CLICK, function (e:Event):void {
  100. //                emitSpark();
  101. //            });
  102.         }
  103.         
  104.         private function enterFrameHandler(e:Event):void
  105.         {
  106.             displayBuffer.fillRect(displayBuffer.rect, 0);
  107.             
  108.             setupProjectionMatrix();
  109.             
  110.             var startTime:uint = getTimer();
  111.             renderFloor();
  112.             var floorRenderingTime:uint = getTimer() - startTime;
  113.             
  114.             startTime = getTimer();
  115.             for (var i:int = 0; i < NUMBER_OF_SPLIT_FRAME; i++) {
  116.                 const FACTOR:Number = 0.06;
  117.                 viewRotationY += (getTimer() * 0.01 + (-(CENTER_X - mouseX) * 0.4) - viewRotationY) * FACTOR;
  118.                 viewRotationX += ((27 + (CENTER_Y - mouseY) * 0.15) - viewRotationX) * FACTOR;
  119.                 
  120.                 setupProjectionMatrix();
  121.                 
  122.                 for (var j:int = 0; j < EMIT_SPARK_NUMBER; j++) {
  123.                     emitSpark();
  124.                 }
  125.                 updateSparks();
  126.                 renderSparks();
  127.             }
  128.             var sparksRenderingTime:uint = getTimer() - startTime;
  129.             
  130.             stats.text = 
  131.                 "Number of Sparks : " + sparkNumber + "\n" + 
  132.                 "Floor Rendering Time : " + floorRenderingTime + " ms\n" + 
  133.                 "Sparks Rendering Time : " + sparksRenderingTime + " ms \n";
  134.         }
  135.         
  136.         private function setupProjectionMatrix():void
  137.         {
  138.             perspective.fieldOfView = 60;
  139.             
  140.             projectionMatrix.identity();
  141.             projectionMatrix.appendRotation(viewRotationY, Vector3D.Y_AXIS);
  142.             projectionMatrix.appendRotation(viewRotationX, Vector3D.X_AXIS);
  143.             projectionMatrix.appendTranslation(00, perspective.focalLength);
  144.             projectionMatrix.append(perspective.toMatrix3D());
  145.             
  146.             correctMatrix3DMultiplyBug(projectionMatrix);
  147.         }
  148.         
  149.         private function correctMatrix3DMultiplyBug(matrix:Matrix3D):void
  150.         {
  151.             // see http://bugs.adobe.com/jira/browse/FP-670
  152.             var m1:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0000,  0010 ]));
  153.             var m2:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0001,  0000 ]));
  154.             m1.append(m2);
  155.             if (m1.rawData[15] == 20) {
  156.                 // バグ持ち!
  157.                 var rawData:Vector.<Number> = matrix.rawData;
  158.                 rawData[15] /= 20;
  159.                 matrix.rawData = rawData;
  160.             }
  161.         }
  162.         
  163.         private function createSpark(x:Number, y:Number, z:Number, vx:Number, vy:Number, vz:Number, diameter:Number):void
  164.         {
  165.             position.push(x, y, z);
  166.             velocity.push(vx, vy, vz);
  167.             diameters.push(diameter);
  168.             sparkNumber++;
  169.         }
  170.         
  171.         private function emitSpark():void
  172.         {
  173.             var azimuth:Number = Math.random() * 2 * Math.PI;
  174.             var vy:Number = -(Math.random() * 0.06 + 0.94);
  175.             var vx:Number = Math.sqrt(1 - vy * vy) * Math.cos(azimuth);
  176.             var vz:Number = Math.sqrt(1 - vy * vy) * Math.sin(azimuth);
  177.             
  178.             var speed:Number = Math.random() * 2.3 + 0.7;
  179.             vx *= speed;
  180.             vy *= speed;
  181.             vz *= speed;
  182.             
  183.             var diameter:Number = 3 + Math.random() * 3;
  184.             createSpark(0, -FIREWORK_HEIGHT, 0, vx, vy, vz, diameter);
  185.         }
  186.         
  187.         private function updateSparks():void
  188.         {
  189.             for (var i:int = 0; i < sparkNumber; ) {
  190.                 var xIndex:int = i * 3;
  191.                 var yIndex:int = xIndex + 1;
  192.                 var zIndex:int = xIndex + 2;
  193.                 
  194.                 velocity[yIndex] += GRAVITY;
  195.                 
  196.                 velocity[xIndex] *= AIR_RESISTANCE;
  197.                 velocity[yIndex] *= AIR_RESISTANCE;
  198.                 velocity[zIndex] *= AIR_RESISTANCE;
  199.                 
  200.                 if (position[yIndex] + velocity[yIndex] > 0) {
  201.                     velocity[yIndex] = -velocity[yIndex] * 0.2;
  202.                     
  203.                     position[xIndex] += velocity[xIndex];
  204.                     position[yIndex] += velocity[yIndex];
  205.                     position[zIndex] += velocity[zIndex];
  206.                     
  207.                     // 小さい火花に分割
  208.                     const DIAMETER_MIN:Number = 2;
  209.                     if (diameters[i] > DIAMETER_MIN) {
  210.                         var diameterLimit:Number = diameters[i];
  211.                         
  212.                         while (1) {
  213.                             var diameter:Number = Math.random() * (4 - DIAMETER_MIN) + DIAMETER_MIN;
  214.                             diameterLimit -= diameter;
  215.                             if (diameterLimit < 0) {
  216.                                 break;
  217.                             }
  218.                             var azimuth:Number = Math.random() * 2 * Math.PI;
  219.                             var r:Number = Math.random() * 2;
  220.                             
  221.                             createSpark(position[xIndex], position[yIndex], position[zIndex], 
  222.                                 (velocity[xIndex] + Math.cos(azimuth) * r) * 0.5
  223.                                 velocity[yIndex], 
  224.                                 (velocity[zIndex] + Math.sin(azimuth) * r) * 0.5
  225.                                 diameter);
  226.                         }
  227.                     }
  228.                     
  229.                     // spliceは重い!
  230. //                    position.splice(xIndex, 3);
  231. //                    velocity.splice(xIndex, 3); 
  232. //                    diameters.splice(i, 1);
  233.                     position[xIndex] = position[sparkNumber * 3 - 3];
  234.                     position[yIndex] = position[sparkNumber * 3 - 2];
  235.                     position[zIndex] = position[sparkNumber * 3 - 1];
  236.                     velocity[xIndex] = velocity[sparkNumber * 3 - 3];
  237.                     velocity[yIndex] = velocity[sparkNumber * 3 - 2];
  238.                     velocity[zIndex] = velocity[sparkNumber * 3 - 1];
  239.                     
  240.                     diameters[i] = diameters[sparkNumber - 1];
  241.                     
  242.                     position.pop();
  243.                     position.pop();
  244.                     position.pop();
  245.                     velocity.pop();
  246.                     velocity.pop();
  247.                     velocity.pop();
  248.                     
  249.                     diameters.pop();
  250.                     
  251.                     sparkNumber--;
  252.                     continue;
  253.                 }
  254.                 position[xIndex] += velocity[xIndex];
  255.                 position[yIndex] += velocity[yIndex];
  256.                 position[zIndex] += velocity[zIndex];
  257.                 
  258.                 i++;
  259.             }
  260.         }
  261.         
  262.         private function renderSparks():void
  263.         {
  264.             splitBuffer.fillRect(splitBuffer.rect, 0x000000);
  265.             
  266.             Utils3D.projectVectors(projectionMatrix, position, projectedPosition, uvts);
  267.             
  268.             // ループ外に追い出したら30%以上高速化
  269.             var p:Point = new Point();
  270.             var focalLength:Number = perspective.focalLength;
  271.             
  272.             for (var i:int = 0; i < sparkNumber; i++) {
  273.                 // パーティクルの大きさ = 1/z * focalLength * pixel
  274.                 var diameter:int = uvts[i * 3 + 2] * focalLength * diameters[i] + 0.5;
  275.                 // (i * 2) => (i << 1)で10%ほど高速化
  276.                 p.x = CENTER_X + projectedPosition[(i << 1)    ] - diameter / 2;
  277.                 p.y = CENTER_Y + projectedPosition[(i << 1) + 1] - diameter / 2;
  278.                 splitBuffer.copyPixels(sparkBitmapDatas[diameter], sparkBitmapDataRectangles[diameter], p);
  279.             }
  280.             
  281.             displayBuffer.draw(splitBuffer, nullnull, BlendMode.ADD);
  282.         }
  283.         
  284.         private const FLOOR_SIZE:Number = 300;
  285.         private const FLOOR_HALFSIZE:Number = FLOOR_SIZE / 2;
  286.         private const FLOOR_VERTICES:Vector.<Number> = Vector.<Number>([
  287.              FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  288.             -FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  289.             -FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  290.              FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  291.              
  292.              FLOOR_HALFSIZE, 0,               0
  293.             -FLOOR_HALFSIZE, 0,               0
  294.                           00,  FLOOR_HALFSIZE, 
  295.                           00, -FLOOR_HALFSIZE, 
  296.         ]);
  297.         private const FLOOR_VERTEX_NUMBER:int = FLOOR_VERTICES.length / 3;
  298.         
  299.         private var floorProjectedVertices:Vector.<Number> = new Vector.<Number>();
  300.         private var floorIndices:Vector.<int> = Vector.<int>([
  301.             012,  230
  302.         ]);
  303.         private var floorUvts:Vector.<Number> = Vector.<Number>([
  304.             100,  000,  010,  110,  
  305.             000,  000,  000,  000
  306.         ]);
  307.         
  308.         private const TEXTURE_SIZE:int = 150;
  309.         private var floorTexture:BitmapData = new BitmapData(TEXTURE_SIZE, TEXTURE_SIZE, false);
  310.         
  311.         private const WIREFRAME_COLOR:uint = 0x555566;
  312.         
  313.         private var sprite:Sprite = new Sprite();
  314.         
  315.         private function renderFloor():void
  316.         {
  317.             // 照り返しを描画する閾値
  318.             const THRESHOLD_Y:Number = 50;
  319.             
  320.             var matrix:Matrix = new Matrix();
  321.             var colorTransform:ColorTransform = new ColorTransform();
  322.             
  323.             floorTexture.fillRect(floorTexture.rect, 0x180C00);
  324.             
  325.             for (var i:int = 0; i < sparkNumber; i++) {
  326.                 var yIndex:int = i * 3 + 1;
  327.                 
  328.                 if (position[yIndex] > -THRESHOLD_Y) {
  329.                     var xIndex:int = i * 3;
  330.                     var zIndex:int = i * 3 + 2;
  331.                     
  332.                     matrix.identity();
  333.                     var scale:Number = (0.2 - (position[yIndex] / THRESHOLD_Y) * 0.8) * diameters[i];
  334.                     matrix.scale(scale, scale);
  335.                     matrix.translate(FLOOR_HALFSIZE + position[xIndex] - REFLECTION_RADIUS * scale, FLOOR_HALFSIZE - position[zIndex] - REFLECTION_RADIUS * scale);
  336.                     matrix.scale(TEXTURE_SIZE / FLOOR_SIZE, TEXTURE_SIZE / FLOOR_SIZE);
  337.                     
  338.                     colorTransform.alphaMultiplier = 1 + position[yIndex] / THRESHOLD_Y;
  339.                     floorTexture.draw(reflectionBitmapData, matrix, colorTransform, BlendMode.ADD);
  340.                 }
  341.             }
  342.             
  343.             Utils3D.projectVectors(projectionMatrix, FLOOR_VERTICES, floorProjectedVertices, floorUvts);
  344.             for (i = 0; i < FLOOR_VERTEX_NUMBER; i++) {
  345.                 floorProjectedVertices[(i << 1)    ] += CENTER_X;
  346.                 floorProjectedVertices[(i << 1) + 1] += CENTER_Y;
  347.             }
  348.             
  349.             Utils3D.projectVectors(projectionMatrix, fireworkVertices, fireworkProjectedVertices, fireworkUvts);
  350.             for (i = 0; i < fireworkProjectedVertices.length / 2; i++) {
  351.                 fireworkProjectedVertices[(i << 1)    ] += CENTER_X;
  352.                 fireworkProjectedVertices[(i << 1) + 1] += CENTER_Y;
  353.             }
  354.             
  355.             var g:Graphics = sprite.graphics;
  356.             g.clear();
  357.             g.beginBitmapFill(floorTexture);
  358.             g.drawTriangles(floorProjectedVertices, floorIndices, floorUvts);
  359.             g.endFill();
  360.             displayBuffer.draw(sprite);
  361.             
  362.             g.clear();
  363.             g.lineStyle(1, WIREFRAME_COLOR);
  364.             g.moveTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  365.             g.lineTo(floorProjectedVertices[2], floorProjectedVertices[3]);
  366.             g.lineTo(floorProjectedVertices[4], floorProjectedVertices[5]);
  367.             g.lineTo(floorProjectedVertices[6], floorProjectedVertices[7]);
  368.             g.lineTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  369.             
  370.             g.moveTo(floorProjectedVertices[8], floorProjectedVertices[9]);
  371.             g.lineTo(floorProjectedVertices[10], floorProjectedVertices[11]);
  372.             g.moveTo(floorProjectedVertices[12], floorProjectedVertices[13]);
  373.             g.lineTo(floorProjectedVertices[14], floorProjectedVertices[15]);
  374.             displayBuffer.draw(sprite, nullnull, BlendMode.ADD);
  375.             
  376.             g.clear();
  377.             g.beginFill(FIREWORK_COLOR);
  378.             g.drawTriangles(fireworkProjectedVertices, fireworkIndices);
  379.             g.endFill();
  380.             displayBuffer.draw(sprite);
  381.         }
  382.         
  383.         private const FIREWORK_RADIUS:Number = 8;
  384.         private const FIREWORK_HEIGHT:Number = 40;
  385.         private const FIREWORK_COLOR:uint = 0xAACCFF;
  386.         
  387.         private var fireworkVertices:Vector.<Number> = new Vector.<Number>();
  388.         private var fireworkIndices:Vector.<int> = new Vector.<int>();
  389.         private var fireworkProjectedVertices:Vector.<Number> = new Vector.<Number>();
  390.         private var fireworkUvts:Vector.<Number> = new Vector.<Number>();
  391.         
  392.         private function createFireworkModel():void
  393.         {
  394.             const SEGMENT:int = 8;
  395.             for (var i:int = 0; i < SEGMENT; i++) {
  396.                 var x:Number = Math.cos(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  397.                 var z:Number = Math.sin(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  398.                 fireworkVertices.push(x, -FIREWORK_HEIGHT, z);
  399.                 fireworkVertices.push(x, 0, z);
  400.                 
  401.                 var i0:int = (i * 2    ) % (SEGMENT * 2);
  402.                 var i1:int = (i * 2 + 1) % (SEGMENT * 2);
  403.                 var i2:int = (i * 2 + 2) % (SEGMENT * 2);
  404.                 var i3:int = (i * 2 + 3) % (SEGMENT * 2);
  405.                 fireworkIndices.push(i2, i0, i1);
  406.                 fireworkIndices.push(i1, i3, i2);
  407.             }
  408.         }
  409.     }
  410. }
noswf

forked from: forked from: PS2 Firework (Particles and Motion blur) forked from: forked from: forked from: PS2 Firework (Particles and Motion blur) [diff(7)]

  1. // forked from hacker_fhynon_3's forked from: forked from: PS2 Firework (Particles and Motion blur)
  2. // forked from rintarock's forked from: PS2 Firework (Particles and Motion blur)
  3. // forked from kohring's PS2 Firework (Particles and Motion blur)
  4. package {
  5.     import flash.display.*;
  6.     import flash.events.*;
  7.     import flash.filters.*;
  8.     import flash.geom.*;
  9.     import flash.text.*;
  10.     import flash.utils.*;
  11.     [SWF(width="465", height="465", frameRate="60")]
  12.     public class Firework extends Sprite
  13.     {
  14.         // 火花
  15.         private var position:Vector.<Number> = new Vector.<Number>();
  16.         private var velocity:Vector.<Number> = new Vector.<Number>();
  17.         private var diameters:Vector.<Number> = new Vector.<Number>();
  18.         private var sparkNumber:Number = 0;
  19.         
  20.         private var projectedPosition:Vector.<Number> = new Vector.<Number>();
  21.         private var uvts:Vector.<Number> = new Vector.<Number>();
  22.         
  23.         private var sparkBitmapDatas:Vector.<BitmapData> = new Vector.<BitmapData>();
  24.         private var sparkBitmapDataRectangles:Vector.<Rectangle> = new Vector.<Rectangle>();
  25.         private const SPARK_COLOR:uint = 0x002299;
  26.         
  27.         private const GRAVITY:Number = 0.04;
  28.         private const AIR_RESISTANCE:Number = 1.006;
  29.         
  30.         // 1フレームに放出する火花の数
  31.         private const EMIT_SPARK_NUMBER:int = 8;
  32.         
  33.         // 照り返し
  34.         private var reflectionBitmapData:BitmapData;
  35.         private const REFLECTION_COLOR:uint = 0x002299;
  36.         private const REFLECTION_RADIUS:Number = 4;
  37.         
  38.         // フレームバッファ
  39.         private var displayBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  40.         private var splitBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
  41.         private const NUMBER_OF_SPLIT_FRAME:int = 10;
  42.         
  43.         private var perspective:PerspectiveProjection = new PerspectiveProjection();
  44.         private var projectionMatrix:Matrix3D = new Matrix3D();
  45.         
  46.         private var viewRotationY:Number = 0;
  47.         private var viewRotationX:Number = 25;
  48.         
  49.         private const CENTER_X:Number = stage.stageWidth / 2;
  50.         private const CENTER_Y:Number = stage.stageHeight * 0.65;
  51.         
  52.         private var stats:TextField = new TextField();
  53.         
  54.         public function Firework()
  55.         {
  56.             addChild(new Bitmap(displayBuffer));
  57.             stats.x = 5;
  58.             stats.y = 5;
  59.             stats.autoSize = TextFieldAutoSize.LEFT;
  60.             stats.textColor = 0xFFFFFF;
  61.             addChild(stats);
  62.             
  63.             var shape:Shape = new Shape();
  64.             var g:Graphics = shape.graphics;
  65.             
  66.             // 火花のプリレンダリング
  67.             var bitmapData:BitmapData = new BitmapData(11true, SPARK_COLOR);
  68.             sparkBitmapDatas.push(bitmapData);
  69.             sparkBitmapDataRectangles.push(bitmapData.rect);
  70.             
  71.             for (var diameter:int = 1; diameter <= 32; diameter++) {
  72.                 bitmapData = new BitmapData(diameter, diameter, true0);
  73.                 
  74.                 g.clear();
  75.                 g.beginFill(SPARK_COLOR);
  76.                 var radius:Number = diameter / 2;
  77.                 g.drawCircle(radius, radius, radius);
  78.                 g.endFill();
  79.                 bitmapData.draw(shape);
  80.                 
  81.                 sparkBitmapDatas.push(bitmapData);
  82.                 sparkBitmapDataRectangles.push(bitmapData.rect);
  83.                 // bitmapData.rectはアクセサで重いのでキャッシュしておく。これにより30%ほど高速化
  84.             }
  85.             
  86.             // 照り返しのプリレンダリング
  87.             reflectionBitmapData = new BitmapData(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2true0);
  88.             g.clear();
  89.             var matrix:Matrix = new Matrix();
  90.             matrix.createGradientBox(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2000);
  91.             g.beginGradientFill(GradientType.RADIAL, [ REFLECTION_COLOR, REFLECTION_COLOR ], [ 10 ], [ 0255 ], matrix);
  92.             g.drawCircle(REFLECTION_RADIUS, REFLECTION_RADIUS, REFLECTION_RADIUS);
  93.             g.endFill();
  94.             reflectionBitmapData.draw(shape);
  95.             
  96.             createFireworkModel();
  97.             
  98.             addEventListener(Event.ENTER_FRAME, enterFrameHandler);
  99. //            stage.addEventListener(MouseEvent.CLICK, function (e:Event):void {
  100. //                emitSpark();
  101. //            });
  102.         }
  103.         
  104.         private function enterFrameHandler(e:Event):void
  105.         {
  106.             displayBuffer.fillRect(displayBuffer.rect, 0);
  107.             
  108.             setupProjectionMatrix();
  109.             
  110.             var startTime:uint = getTimer();
  111.             renderFloor();
  112.             var floorRenderingTime:uint = getTimer() - startTime;
  113.             
  114.             startTime = getTimer();
  115.             for (var i:int = 0; i < NUMBER_OF_SPLIT_FRAME; i++) {
  116.                 const FACTOR:Number = 0.06;
  117.                 viewRotationY += (getTimer() * 0.01 + (-(CENTER_X - mouseX) * 0.4) - viewRotationY) * FACTOR;
  118.                 viewRotationX += ((27 + (CENTER_Y - mouseY) * 0.15) - viewRotationX) * FACTOR;
  119.                 
  120.                 setupProjectionMatrix();
  121.                 
  122.                 for (var j:int = 0; j < EMIT_SPARK_NUMBER; j++) {
  123.                     emitSpark();
  124.                 }
  125.                 updateSparks();
  126.                 renderSparks();
  127.             }
  128.             var sparksRenderingTime:uint = getTimer() - startTime;
  129.             
  130.             stats.text = 
  131.                 "Number of Sparks : " + sparkNumber + "\n" + 
  132.                 "Floor Rendering Time : " + floorRenderingTime + " ms\n" + 
  133.                 "Sparks Rendering Time : " + sparksRenderingTime + " ms \n";
  134.         }
  135.         
  136.         private function setupProjectionMatrix():void
  137.         {
  138.             perspective.fieldOfView = 60;
  139.             
  140.             projectionMatrix.identity();
  141.             projectionMatrix.appendRotation(viewRotationY, Vector3D.Y_AXIS);
  142.             projectionMatrix.appendRotation(viewRotationX, Vector3D.X_AXIS);
  143.             projectionMatrix.appendTranslation(00, perspective.focalLength);
  144.             projectionMatrix.append(perspective.toMatrix3D());
  145.             
  146.             correctMatrix3DMultiplyBug(projectionMatrix);
  147.         }
  148.         
  149.         private function correctMatrix3DMultiplyBug(matrix:Matrix3D):void
  150.         {
  151.             // see http://bugs.adobe.com/jira/browse/FP-670
  152.             var m1:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0000,  0010 ]));
  153.             var m2:Matrix3D = new Matrix3D(Vector.<Number>([ 0000,  0000,  0001,  0000 ]));
  154.             m1.append(m2);
  155.             if (m1.rawData[15] == 20) {
  156.                 // バグ持ち!
  157.                 var rawData:Vector.<Number> = matrix.rawData;
  158.                 rawData[15] /= 20;
  159.                 matrix.rawData = rawData;
  160.             }
  161.         }
  162.         
  163.         private function createSpark(x:Number, y:Number, z:Number, vx:Number, vy:Number, vz:Number, diameter:Number):void
  164.         {
  165.             position.push(x, y, z);
  166.             velocity.push(vx, vy, vz);
  167.             diameters.push(diameter);
  168.             sparkNumber++;
  169.         }
  170.         
  171.         private function emitSpark():void
  172.         {
  173.             var azimuth:Number = Math.random() * 2 * Math.PI;
  174.             var vy:Number = -(Math.random() * 0.06 + 0.94);
  175.             var vx:Number = Math.sqrt(1 - vy * vy) * Math.cos(azimuth);
  176.             var vz:Number = Math.sqrt(1 - vy * vy) * Math.sin(azimuth);
  177.             
  178.             var speed:Number = Math.random() * 2.3 + 0.7;
  179.             vx *= speed;
  180.             vy *= speed;
  181.             vz *= speed;
  182.             
  183.             var diameter:Number = 3 + Math.random() * 3;
  184.             createSpark(0, -FIREWORK_HEIGHT, 0, vx, vy, vz, diameter);
  185.         }
  186.         
  187.         private function updateSparks():void
  188.         {
  189.             for (var i:int = 0; i < sparkNumber; ) {
  190.                 var xIndex:int = i * 3;
  191.                 var yIndex:int = xIndex + 1;
  192.                 var zIndex:int = xIndex + 2;
  193.                 
  194.                 velocity[yIndex] += GRAVITY;
  195.                 
  196.                 velocity[xIndex] *= AIR_RESISTANCE;
  197.                 velocity[yIndex] *= AIR_RESISTANCE;
  198.                 velocity[zIndex] *= AIR_RESISTANCE;
  199.                 
  200.                 if (position[yIndex] + velocity[yIndex] > 0) {
  201.                     velocity[yIndex] = -velocity[yIndex] * 0.2;
  202.                     
  203.                     position[xIndex] += velocity[xIndex];
  204.                     position[yIndex] += velocity[yIndex];
  205.                     position[zIndex] += velocity[zIndex];
  206.                     
  207.                     // 小さい火花に分割
  208.                     const DIAMETER_MIN:Number = 2;
  209.                     if (diameters[i] > DIAMETER_MIN) {
  210.                         var diameterLimit:Number = diameters[i];
  211.                         
  212.                         while (1) {
  213.                             var diameter:Number = Math.random() * (4 - DIAMETER_MIN) + DIAMETER_MIN;
  214.                             diameterLimit -= diameter;
  215.                             if (diameterLimit < 0) {
  216.                                 break;
  217.                             }
  218.                             var azimuth:Number = Math.random() * 2 * Math.PI;
  219.                             var r:Number = Math.random() * 2;
  220.                             
  221.                             createSpark(position[xIndex], position[yIndex], position[zIndex], 
  222.                                 (velocity[xIndex] + Math.cos(azimuth) * r) * 0.5
  223.                                 velocity[yIndex], 
  224.                                 (velocity[zIndex] + Math.sin(azimuth) * r) * 0.5
  225.                                 diameter);
  226.                         }
  227.                     }
  228.                     
  229.                     // spliceは重い!
  230. //                    position.splice(xIndex, 3);
  231. //                    velocity.splice(xIndex, 3); 
  232. //                    diameters.splice(i, 1);
  233.                     position[xIndex] = position[sparkNumber * 3 - 3];
  234.                     position[yIndex] = position[sparkNumber * 3 - 2];
  235.                     position[zIndex] = position[sparkNumber * 3 - 1];
  236.                     velocity[xIndex] = velocity[sparkNumber * 3 - 3];
  237.                     velocity[yIndex] = velocity[sparkNumber * 3 - 2];
  238.                     velocity[zIndex] = velocity[sparkNumber * 3 - 1];
  239.                     
  240.                     diameters[i] = diameters[sparkNumber - 1];
  241.                     
  242.                     position.pop();
  243.                     position.pop();
  244.                     position.pop();
  245.                     velocity.pop();
  246.                     velocity.pop();
  247.                     velocity.pop();
  248.                     
  249.                     diameters.pop();
  250.                     
  251.                     sparkNumber--;
  252.                     continue;
  253.                 }
  254.                 position[xIndex] += velocity[xIndex];
  255.                 position[yIndex] += velocity[yIndex];
  256.                 position[zIndex] += velocity[zIndex];
  257.                 
  258.                 i++;
  259.             }
  260.         }
  261.         
  262.         private function renderSparks():void
  263.         {
  264.             splitBuffer.fillRect(splitBuffer.rect, 0x000000);
  265.             
  266.             Utils3D.projectVectors(projectionMatrix, position, projectedPosition, uvts);
  267.             
  268.             // ループ外に追い出したら30%以上高速化
  269.             var p:Point = new Point();
  270.             var focalLength:Number = perspective.focalLength;
  271.             
  272.             for (var i:int = 0; i < sparkNumber; i++) {
  273.                 // パーティクルの大きさ = 1/z * focalLength * pixel
  274.                 var diameter:int = uvts[i * 3 + 2] * focalLength * diameters[i] + 0.5;
  275.                 // (i * 2) => (i << 1)で10%ほど高速化
  276.                 p.x = CENTER_X + projectedPosition[(i << 1)    ] - diameter / 2;
  277.                 p.y = CENTER_Y + projectedPosition[(i << 1) + 1] - diameter / 2;
  278.                 splitBuffer.copyPixels(sparkBitmapDatas[diameter], sparkBitmapDataRectangles[diameter], p);
  279.             }
  280.             
  281.             displayBuffer.draw(splitBuffer, nullnull, BlendMode.ADD);
  282.         }
  283.         
  284.         private const FLOOR_SIZE:Number = 300;
  285.         private const FLOOR_HALFSIZE:Number = FLOOR_SIZE / 2;
  286.         private const FLOOR_VERTICES:Vector.<Number> = Vector.<Number>([
  287.              FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  288.             -FLOOR_HALFSIZE, 0,  FLOOR_HALFSIZE, 
  289.             -FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  290.              FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE, 
  291.              
  292.              FLOOR_HALFSIZE, 0,               0
  293.             -FLOOR_HALFSIZE, 0,               0
  294.                           00,  FLOOR_HALFSIZE, 
  295.                           00, -FLOOR_HALFSIZE, 
  296.         ]);
  297.         private const FLOOR_VERTEX_NUMBER:int = FLOOR_VERTICES.length / 3;
  298.         
  299.         private var floorProjectedVertices:Vector.<Number> = new Vector.<Number>();
  300.         private var floorIndices:Vector.<int> = Vector.<int>([
  301.             012,  230
  302.         ]);
  303.         private var floorUvts:Vector.<Number> = Vector.<Number>([
  304.             100,  000,  010,  110,  
  305.             000,  000,  000,  000
  306.         ]);
  307.         
  308.         private const TEXTURE_SIZE:int = 150;
  309.         private var floorTexture:BitmapData = new BitmapData(TEXTURE_SIZE, TEXTURE_SIZE, false);
  310.         
  311.         private const WIREFRAME_COLOR:uint = 0x555566;
  312.         
  313.         private var sprite:Sprite = new Sprite();
  314.         
  315.         private function renderFloor():void
  316.         {
  317.             // 照り返しを描画する閾値
  318.             const THRESHOLD_Y:Number = 50;
  319.             
  320.             var matrix:Matrix = new Matrix();
  321.             var colorTransform:ColorTransform = new ColorTransform();
  322.             
  323.             floorTexture.fillRect(floorTexture.rect, 0x180C00);
  324.             
  325.             for (var i:int = 0; i < sparkNumber; i++) {
  326.                 var yIndex:int = i * 3 + 1;
  327.                 
  328.                 if (position[yIndex] > -THRESHOLD_Y) {
  329.                     var xIndex:int = i * 3;
  330.                     var zIndex:int = i * 3 + 2;
  331.                     
  332.                     matrix.identity();
  333.                     var scale:Number = (0.2 - (position[yIndex] / THRESHOLD_Y) * 0.8) * diameters[i];
  334.                     matrix.scale(scale, scale);
  335.                     matrix.translate(FLOOR_HALFSIZE + position[xIndex] - REFLECTION_RADIUS * scale, FLOOR_HALFSIZE - position[zIndex] - REFLECTION_RADIUS * scale);
  336.                     matrix.scale(TEXTURE_SIZE / FLOOR_SIZE, TEXTURE_SIZE / FLOOR_SIZE);
  337.                     
  338.                     colorTransform.alphaMultiplier = 1 + position[yIndex] / THRESHOLD_Y;
  339.                     floorTexture.draw(reflectionBitmapData, matrix, colorTransform, BlendMode.ADD);
  340.                 }
  341.             }
  342.             
  343.             Utils3D.projectVectors(projectionMatrix, FLOOR_VERTICES, floorProjectedVertices, floorUvts);
  344.             for (i = 0; i < FLOOR_VERTEX_NUMBER; i++) {
  345.                 floorProjectedVertices[(i << 1)    ] += CENTER_X;
  346.                 floorProjectedVertices[(i << 1) + 1] += CENTER_Y;
  347.             }
  348.             
  349.             Utils3D.projectVectors(projectionMatrix, fireworkVertices, fireworkProjectedVertices, fireworkUvts);
  350.             for (i = 0; i < fireworkProjectedVertices.length / 2; i++) {
  351.                 fireworkProjectedVertices[(i << 1)    ] += CENTER_X;
  352.                 fireworkProjectedVertices[(i << 1) + 1] += CENTER_Y;
  353.             }
  354.             
  355.             var g:Graphics = sprite.graphics;
  356.             g.clear();
  357.             g.beginBitmapFill(floorTexture);
  358.             g.drawTriangles(floorProjectedVertices, floorIndices, floorUvts);
  359.             g.endFill();
  360.             displayBuffer.draw(sprite);
  361.             
  362.             g.clear();
  363.             g.lineStyle(1, WIREFRAME_COLOR);
  364.             g.moveTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  365.             g.lineTo(floorProjectedVertices[2], floorProjectedVertices[3]);
  366.             g.lineTo(floorProjectedVertices[4], floorProjectedVertices[5]);
  367.             g.lineTo(floorProjectedVertices[6], floorProjectedVertices[7]);
  368.             g.lineTo(floorProjectedVertices[0], floorProjectedVertices[1]);
  369.             
  370.             g.moveTo(floorProjectedVertices[8], floorProjectedVertices[9]);
  371.             g.lineTo(floorProjectedVertices[10], floorProjectedVertices[11]);
  372.             g.moveTo(floorProjectedVertices[12], floorProjectedVertices[13]);
  373.             g.lineTo(floorProjectedVertices[14], floorProjectedVertices[15]);
  374.             displayBuffer.draw(sprite, nullnull, BlendMode.ADD);
  375.             
  376.             g.clear();
  377.             g.beginFill(FIREWORK_COLOR);
  378.             g.drawTriangles(fireworkProjectedVertices, fireworkIndices);
  379.             g.endFill();
  380.             displayBuffer.draw(sprite);
  381.         }
  382.         
  383.         private const FIREWORK_RADIUS:Number = 8;
  384.         private const FIREWORK_HEIGHT:Number = 40;
  385.         private const FIREWORK_COLOR:uint = 0xAACCFF;
  386.         
  387.         private var fireworkVertices:Vector.<Number> = new Vector.<Number>();
  388.         private var fireworkIndices:Vector.<int> = new Vector.<int>();
  389.         private var fireworkProjectedVertices:Vector.<Number> = new Vector.<Number>();
  390.         private var fireworkUvts:Vector.<Number> = new Vector.<Number>();
  391.         
  392.         private function createFireworkModel():void
  393.         {
  394.             const SEGMENT:int = 8;
  395.             for (var i:int = 0; i < SEGMENT; i++) {
  396.                 var x:Number = Math.cos(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  397.                 var z:Number = Math.sin(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
  398.                 fireworkVertices.push(x, -FIREWORK_HEIGHT, z);
  399.                 fireworkVertices.push(x, 0, z);
  400.                 
  401.                 var i0:int = (i * 2    ) % (SEGMENT * 2);
  402.                 var i1:int = (i * 2 + 1) % (SEGMENT * 2);
  403.                 var i2:int = (i * 2 + 2) % (SEGMENT * 2);
  404.                 var i3:int = (i * 2 + 3) % (SEGMENT * 2);
  405.                 fireworkIndices.push(i2, i0, i1);
  406.                 fireworkIndices.push(i1, i3, i2);
  407.             }
  408.         }
  409.     }
  410. }
noswf
Get Adobe Flash Player