forked from: forked from: PS2 Firework (Particles and Motion blur) forked from: forked from: forked from: PS2 Firework (Particles and Motion blur)
- // forked from hacker_fhynon_3's forked from: forked from: PS2 Firework (Particles and Motion blur)
- // forked from rintarock's forked from: PS2 Firework (Particles and Motion blur)
- // forked from kohring's PS2 Firework (Particles and Motion blur)
- package {
- import flash.display.*;
- import flash.events.*;
- import flash.filters.*;
- import flash.geom.*;
- import flash.text.*;
- import flash.utils.*;
- [SWF(width="465", height="465", frameRate="60")]
- public class Firework extends Sprite
- {
- // 火花
- private var position:Vector.<Number> = new Vector.<Number>();
- private var velocity:Vector.<Number> = new Vector.<Number>();
- private var diameters:Vector.<Number> = new Vector.<Number>();
- private var sparkNumber:Number = 0;
- private var projectedPosition:Vector.<Number> = new Vector.<Number>();
- private var uvts:Vector.<Number> = new Vector.<Number>();
- private var sparkBitmapDatas:Vector.<BitmapData> = new Vector.<BitmapData>();
- private var sparkBitmapDataRectangles:Vector.<Rectangle> = new Vector.<Rectangle>();
- private const SPARK_COLOR:uint = 0x3355ff;
- private const GRAVITY:Number = 0.04;
- private const AIR_RESISTANCE:Number = 0.995;
- // 1フレームに放出する火花の数
- private const EMIT_SPARK_NUMBER:int = 1;
- // 照り返し
- private var reflectionBitmapData:BitmapData;
- private const REFLECTION_COLOR:uint = 0xFF1800;
- private const REFLECTION_RADIUS:Number = 16;
- // フレームバッファ
- private var displayBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
- private var splitBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
- private const NUMBER_OF_SPLIT_FRAME:int = 10;
- private var perspective:PerspectiveProjection = new PerspectiveProjection();
- private var projectionMatrix:Matrix3D = new Matrix3D();
- private var viewRotationY:Number = 0;
- private var viewRotationX:Number = 25;
- private const CENTER_X:Number = stage.stageWidth / 2;
- private const CENTER_Y:Number = stage.stageHeight * 0.65;
- private var stats:TextField = new TextField();
- public function Firework()
- {
- addChild(new Bitmap(displayBuffer));
- stats.x = 5;
- stats.y = 5;
- stats.autoSize = TextFieldAutoSize.LEFT;
- stats.textColor = 0xFFFFFF;
- addChild(stats);
- var shape:Shape = new Shape();
- var g:Graphics = shape.graphics;
- // 火花のプリレンダリング
- var bitmapData:BitmapData = new BitmapData(1, 1, true, SPARK_COLOR);
- sparkBitmapDatas.push(bitmapData);
- sparkBitmapDataRectangles.push(bitmapData.rect);
- for (var diameter:int = 1; diameter <= 32; diameter++) {
- bitmapData = new BitmapData(diameter, diameter, true, 0);
- g.clear();
- g.beginFill(SPARK_COLOR);
- var radius:Number = diameter / 2;
- g.drawCircle(radius, radius, radius);
- g.endFill();
- bitmapData.draw(shape);
- sparkBitmapDatas.push(bitmapData);
- sparkBitmapDataRectangles.push(bitmapData.rect);
- // bitmapData.rectはアクセサで重いのでキャッシュしておく。これにより30%ほど高速化
- }
- // 照り返しのプリレンダリング
- reflectionBitmapData = new BitmapData(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2, true, 0);
- g.clear();
- var matrix:Matrix = new Matrix();
- matrix.createGradientBox(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2, 0, 0, 0);
- g.beginGradientFill(GradientType.RADIAL, [ REFLECTION_COLOR, REFLECTION_COLOR ], [ 1, 0 ], [ 0, 255 ], matrix);
- g.drawCircle(REFLECTION_RADIUS, REFLECTION_RADIUS, REFLECTION_RADIUS);
- g.endFill();
- reflectionBitmapData.draw(shape);
- createFireworkModel();
- addEventListener(Event.ENTER_FRAME, enterFrameHandler);
- // stage.addEventListener(MouseEvent.CLICK, function (e:Event):void {
- // emitSpark();
- // });
- }
- private function enterFrameHandler(e:Event):void
- {
- displayBuffer.fillRect(displayBuffer.rect, 0);
- setupProjectionMatrix();
- var startTime:uint = getTimer();
- renderFloor();
- var floorRenderingTime:uint = getTimer() - startTime;
- startTime = getTimer();
- for (var i:int = 0; i < NUMBER_OF_SPLIT_FRAME; i++) {
- const FACTOR:Number = 0.06;
- viewRotationY += (getTimer() * 0.01 + (-(CENTER_X - mouseX) * 0.4) - viewRotationY) * FACTOR;
- viewRotationX += ((27 + (CENTER_Y - mouseY) * 0.15) - viewRotationX) * FACTOR;
- setupProjectionMatrix();
- for (var j:int = 0; j < EMIT_SPARK_NUMBER; j++) {
- emitSpark();
- }
- updateSparks();
- renderSparks();
- }
- var sparksRenderingTime:uint = getTimer() - startTime;
- stats.text =
- "Number of Sparks : " + sparkNumber + "\n" +
- "Floor Rendering Time : " + floorRenderingTime + " ms\n" +
- "Sparks Rendering Time : " + sparksRenderingTime + " ms \n";
- }
- private function setupProjectionMatrix():void
- {
- perspective.fieldOfView = 60;
- projectionMatrix.identity();
- projectionMatrix.appendRotation(viewRotationY, Vector3D.Y_AXIS);
- projectionMatrix.appendRotation(viewRotationX, Vector3D.X_AXIS);
- projectionMatrix.appendTranslation(0, 0, perspective.focalLength);
- projectionMatrix.append(perspective.toMatrix3D());
- correctMatrix3DMultiplyBug(projectionMatrix);
- }
- private function correctMatrix3DMultiplyBug(matrix:Matrix3D):void
- {
- // see http://bugs.adobe.com/jira/browse/FP-670
- var m1:Matrix3D = new Matrix3D(Vector.<Number>([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 ]));
- var m2:Matrix3D = new Matrix3D(Vector.<Number>([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ]));
- m1.append(m2);
- if (m1.rawData[15] == 20) {
- // バグ持ち!
- var rawData:Vector.<Number> = matrix.rawData;
- rawData[15] /= 20;
- matrix.rawData = rawData;
- }
- }
- private function createSpark(x:Number, y:Number, z:Number, vx:Number, vy:Number, vz:Number, diameter:Number):void
- {
- position.push(x, y, z);
- velocity.push(vx, vy, vz);
- diameters.push(diameter);
- sparkNumber++;
- }
- private function emitSpark():void
- {
- var azimuth:Number = Math.random() * 2 * Math.PI;
- var vy:Number = -(Math.random() * 0.06 + 0.94);
- var vx:Number = Math.sqrt(1 - vy * vy) * Math.cos(azimuth);
- var vz:Number = Math.sqrt(1 - vy * vy) * Math.sin(azimuth);
- var speed:Number = Math.random() * 2.3 + 0.7;
- vx *= speed;
- vy *= speed;
- vz *= speed;
- var diameter:Number = 3 + Math.random() * 3;
- createSpark(0, -FIREWORK_HEIGHT, 0, vx, vy, vz, diameter);
- }
- private function updateSparks():void
- {
- for (var i:int = 0; i < sparkNumber; ) {
- var xIndex:int = i * 3;
- var yIndex:int = xIndex + 1;
- var zIndex:int = xIndex + 2;
- velocity[yIndex] += GRAVITY;
- velocity[xIndex] *= AIR_RESISTANCE;
- velocity[yIndex] *= AIR_RESISTANCE;
- velocity[zIndex] *= AIR_RESISTANCE;
- if (position[yIndex] + velocity[yIndex] > 0) {
- velocity[yIndex] = -velocity[yIndex] * 0.2;
- position[xIndex] += velocity[xIndex];
- position[yIndex] += velocity[yIndex];
- position[zIndex] += velocity[zIndex];
- // 小さい火花に分割
- const DIAMETER_MIN:Number = 2;
- if (diameters[i] > DIAMETER_MIN) {
- var diameterLimit:Number = diameters[i];
- while (1) {
- var diameter:Number = Math.random() * (4 - DIAMETER_MIN) + DIAMETER_MIN;
- diameterLimit -= diameter;
- if (diameterLimit < 0) {
- break;
- }
- var azimuth:Number = Math.random() * 2 * Math.PI;
- var r:Number = Math.random() * 2;
- createSpark(position[xIndex], position[yIndex], position[zIndex],
- (velocity[xIndex] + Math.cos(azimuth) * r) * 0.5,
- velocity[yIndex],
- (velocity[zIndex] + Math.sin(azimuth) * r) * 0.5,
- diameter);
- }
- }
- // spliceは重い!
- // position.splice(xIndex, 3);
- // velocity.splice(xIndex, 3);
- // diameters.splice(i, 1);
- position[xIndex] = position[sparkNumber * 3 - 3];
- position[yIndex] = position[sparkNumber * 3 - 2];
- position[zIndex] = position[sparkNumber * 3 - 1];
- velocity[xIndex] = velocity[sparkNumber * 3 - 3];
- velocity[yIndex] = velocity[sparkNumber * 3 - 2];
- velocity[zIndex] = velocity[sparkNumber * 3 - 1];
- diameters[i] = diameters[sparkNumber - 1];
- position.pop();
- position.pop();
- position.pop();
- velocity.pop();
- velocity.pop();
- velocity.pop();
- diameters.pop();
- sparkNumber--;
- continue;
- }
- position[xIndex] += velocity[xIndex];
- position[yIndex] += velocity[yIndex];
- position[zIndex] += velocity[zIndex];
- i++;
- }
- }
- private function renderSparks():void
- {
- splitBuffer.fillRect(splitBuffer.rect, 0x000000);
- Utils3D.projectVectors(projectionMatrix, position, projectedPosition, uvts);
- // ループ外に追い出したら30%以上高速化
- var p:Point = new Point();
- var focalLength:Number = perspective.focalLength;
- for (var i:int = 0; i < sparkNumber; i++) {
- // パーティクルの大きさ = 1/z * focalLength * pixel
- var diameter:int = uvts[i * 3 + 2] * focalLength * diameters[i] + 0.5;
- // (i * 2) => (i << 1)で10%ほど高速化
- p.x = CENTER_X + projectedPosition[(i << 1) ] - diameter / 2;
- p.y = CENTER_Y + projectedPosition[(i << 1) + 1] - diameter / 2;
- splitBuffer.copyPixels(sparkBitmapDatas[diameter], sparkBitmapDataRectangles[diameter], p);
- }
- displayBuffer.draw(splitBuffer, null, null, BlendMode.ADD);
- }
- private const FLOOR_SIZE:Number = 300;
- private const FLOOR_HALFSIZE:Number = FLOOR_SIZE / 2;
- private const FLOOR_VERTICES:Vector.<Number> = Vector.<Number>([
- FLOOR_HALFSIZE, 0, FLOOR_HALFSIZE,
- -FLOOR_HALFSIZE, 0, FLOOR_HALFSIZE,
- -FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE,
- FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE,
- FLOOR_HALFSIZE, 0, 0,
- -FLOOR_HALFSIZE, 0, 0,
- 0, 0, FLOOR_HALFSIZE,
- 0, 0, -FLOOR_HALFSIZE,
- ]);
- private const FLOOR_VERTEX_NUMBER:int = FLOOR_VERTICES.length / 3;
- private var floorProjectedVertices:Vector.<Number> = new Vector.<Number>();
- private var floorIndices:Vector.<int> = Vector.<int>([
- 0, 1, 2, 2, 3, 0
- ]);
- private var floorUvts:Vector.<Number> = Vector.<Number>([
- 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- ]);
- private const TEXTURE_SIZE:int = 150;
- private var floorTexture:BitmapData = new BitmapData(TEXTURE_SIZE, TEXTURE_SIZE, false);
- private const WIREFRAME_COLOR:uint = 0x555566;
- private var sprite:Sprite = new Sprite();
- private function renderFloor():void
- {
- // 照り返しを描画する閾値
- const THRESHOLD_Y:Number = 50;
- var matrix:Matrix = new Matrix();
- var colorTransform:ColorTransform = new ColorTransform();
- floorTexture.fillRect(floorTexture.rect, 0x180C00);
- for (var i:int = 0; i < sparkNumber; i++) {
- var yIndex:int = i * 3 + 1;
- if (position[yIndex] > -THRESHOLD_Y) {
- var xIndex:int = i * 3;
- var zIndex:int = i * 3 + 2;
- matrix.identity();
- var scale:Number = (0.2 - (position[yIndex] / THRESHOLD_Y) * 0.8) * diameters[i];
- matrix.scale(scale, scale);
- matrix.translate(FLOOR_HALFSIZE + position[xIndex] - REFLECTION_RADIUS * scale, FLOOR_HALFSIZE - position[zIndex] - REFLECTION_RADIUS * scale);
- matrix.scale(TEXTURE_SIZE / FLOOR_SIZE, TEXTURE_SIZE / FLOOR_SIZE);
- colorTransform.alphaMultiplier = 1 + position[yIndex] / THRESHOLD_Y;
- floorTexture.draw(reflectionBitmapData, matrix, colorTransform, BlendMode.ADD);
- }
- }
- Utils3D.projectVectors(projectionMatrix, FLOOR_VERTICES, floorProjectedVertices, floorUvts);
- for (i = 0; i < FLOOR_VERTEX_NUMBER; i++) {
- floorProjectedVertices[(i << 1) ] += CENTER_X;
- floorProjectedVertices[(i << 1) + 1] += CENTER_Y;
- }
- Utils3D.projectVectors(projectionMatrix, fireworkVertices, fireworkProjectedVertices, fireworkUvts);
- for (i = 0; i < fireworkProjectedVertices.length / 2; i++) {
- fireworkProjectedVertices[(i << 1) ] += CENTER_X;
- fireworkProjectedVertices[(i << 1) + 1] += CENTER_Y;
- }
- var g:Graphics = sprite.graphics;
- g.clear();
- g.beginBitmapFill(floorTexture);
- g.drawTriangles(floorProjectedVertices, floorIndices, floorUvts);
- g.endFill();
- displayBuffer.draw(sprite);
- g.clear();
- g.lineStyle(1, WIREFRAME_COLOR);
- g.moveTo(floorProjectedVertices[0], floorProjectedVertices[1]);
- g.lineTo(floorProjectedVertices[2], floorProjectedVertices[3]);
- g.lineTo(floorProjectedVertices[4], floorProjectedVertices[5]);
- g.lineTo(floorProjectedVertices[6], floorProjectedVertices[7]);
- g.lineTo(floorProjectedVertices[0], floorProjectedVertices[1]);
- g.moveTo(floorProjectedVertices[8], floorProjectedVertices[9]);
- g.lineTo(floorProjectedVertices[10], floorProjectedVertices[11]);
- g.moveTo(floorProjectedVertices[12], floorProjectedVertices[13]);
- g.lineTo(floorProjectedVertices[14], floorProjectedVertices[15]);
- displayBuffer.draw(sprite, null, null, BlendMode.ADD);
- g.clear();
- g.beginFill(FIREWORK_COLOR);
- g.drawTriangles(fireworkProjectedVertices, fireworkIndices);
- g.endFill();
- displayBuffer.draw(sprite);
- }
- private const FIREWORK_RADIUS:Number = 8;
- private const FIREWORK_HEIGHT:Number = 40;
- private const FIREWORK_COLOR:uint = 0xAACCFF;
- private var fireworkVertices:Vector.<Number> = new Vector.<Number>();
- private var fireworkIndices:Vector.<int> = new Vector.<int>();
- private var fireworkProjectedVertices:Vector.<Number> = new Vector.<Number>();
- private var fireworkUvts:Vector.<Number> = new Vector.<Number>();
- private function createFireworkModel():void
- {
- const SEGMENT:int = 8;
- for (var i:int = 0; i < SEGMENT; i++) {
- var x:Number = Math.cos(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
- var z:Number = Math.sin(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
- fireworkVertices.push(x, -FIREWORK_HEIGHT, z);
- fireworkVertices.push(x, 0, z);
- var i0:int = (i * 2 ) % (SEGMENT * 2);
- var i1:int = (i * 2 + 1) % (SEGMENT * 2);
- var i2:int = (i * 2 + 2) % (SEGMENT * 2);
- var i3:int = (i * 2 + 3) % (SEGMENT * 2);
- fireworkIndices.push(i2, i0, i1);
- fireworkIndices.push(i1, i3, i2);
- }
- }
- }
- }
forked from: forked from: PS2 Firework (Particles and Motion blur) forked from: forked from: forked from: PS2 Firework (Particles and Motion blur)
- // forked from hacker_fhynon_3's forked from: forked from: PS2 Firework (Particles and Motion blur)
- // forked from rintarock's forked from: PS2 Firework (Particles and Motion blur)
- // forked from kohring's PS2 Firework (Particles and Motion blur)
- package {
- import flash.display.*;
- import flash.events.*;
- import flash.filters.*;
- import flash.geom.*;
- import flash.text.*;
- import flash.utils.*;
- [SWF(width="465", height="465", frameRate="60")]
- public class Firework extends Sprite
- {
- // 火花
- private var position:Vector.<Number> = new Vector.<Number>();
- private var velocity:Vector.<Number> = new Vector.<Number>();
- private var diameters:Vector.<Number> = new Vector.<Number>();
- private var sparkNumber:Number = 0;
- private var projectedPosition:Vector.<Number> = new Vector.<Number>();
- private var uvts:Vector.<Number> = new Vector.<Number>();
- private var sparkBitmapDatas:Vector.<BitmapData> = new Vector.<BitmapData>();
- private var sparkBitmapDataRectangles:Vector.<Rectangle> = new Vector.<Rectangle>();
- private const SPARK_COLOR:uint = 0x664020;
- private const GRAVITY:Number = 0.02;
- private const AIR_RESISTANCE:Number = 0.999;
- // 1フレームに放出する火花の数
- private const EMIT_SPARK_NUMBER:int = 1;
- // 照り返し
- private var reflectionBitmapData:BitmapData;
- private const REFLECTION_COLOR:uint = 0xFFac00;
- private const REFLECTION_RADIUS:Number = 16;
- // フレームバッファ
- private var displayBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
- private var splitBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
- private const NUMBER_OF_SPLIT_FRAME:int = 10;
- private var perspective:PerspectiveProjection = new PerspectiveProjection();
- private var projectionMatrix:Matrix3D = new Matrix3D();
- private var viewRotationY:Number = 0;
- private var viewRotationX:Number = 25;
- private const CENTER_X:Number = stage.stageWidth / 2;
- private const CENTER_Y:Number = stage.stageHeight * 1.65;
- private var stats:TextField = new TextField();
- public function Firework()
- {
- addChild(new Bitmap(displayBuffer));
- stats.x = 5;
- stats.y = 5;
- stats.autoSize = TextFieldAutoSize.LEFT;
- stats.textColor = 0xFFFFFF;
- addChild(stats);
- var shape:Shape = new Shape();
- var g:Graphics = shape.graphics;
- // 火花のプリレンダリング
- var bitmapData:BitmapData = new BitmapData(1, 1, true, SPARK_COLOR);
- sparkBitmapDatas.push(bitmapData);
- sparkBitmapDataRectangles.push(bitmapData.rect);
- for (var diameter:int = 1; diameter <= 32; diameter++) {
- bitmapData = new BitmapData(diameter, diameter, true, 0);
- g.clear();
- g.beginFill(SPARK_COLOR);
- var radius:Number = diameter / 2;
- g.drawCircle(radius, radius, radius);
- g.endFill();
- bitmapData.draw(shape);
- sparkBitmapDatas.push(bitmapData);
- sparkBitmapDataRectangles.push(bitmapData.rect);
- // bitmapData.rectはアクセサで重いのでキャッシュしておく。これにより30%ほど高速化
- }
- // 照り返しのプリレンダリング
- reflectionBitmapData = new BitmapData(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2, true, 0);
- g.clear();
- var matrix:Matrix = new Matrix();
- matrix.createGradientBox(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2, 0, 0, 0);
- g.beginGradientFill(GradientType.RADIAL, [ REFLECTION_COLOR, REFLECTION_COLOR ], [ 1, 0 ], [ 0, 255 ], matrix);
- g.drawCircle(REFLECTION_RADIUS, REFLECTION_RADIUS, REFLECTION_RADIUS);
- g.endFill();
- reflectionBitmapData.draw(shape);
- createFireworkModel();
- addEventListener(Event.ENTER_FRAME, enterFrameHandler);
- // stage.addEventListener(MouseEvent.CLICK, function (e:Event):void {
- // emitSpark();
- // });
- }
- private function enterFrameHandler(e:Event):void
- {
- displayBuffer.fillRect(displayBuffer.rect, 0);
- setupProjectionMatrix();
- var startTime:uint = getTimer();
- renderFloor();
- var floorRenderingTime:uint = getTimer() - startTime;
- startTime = getTimer();
- for (var i:int = 0; i < NUMBER_OF_SPLIT_FRAME; i++) {
- const FACTOR:Number = 0.06;
- viewRotationY += (getTimer() * 0.01 + (-(CENTER_X - mouseX) * 0.4) - viewRotationY) * FACTOR;
- viewRotationX += ((27 + (CENTER_Y - mouseY) * 0.15) - viewRotationX) * FACTOR;
- setupProjectionMatrix();
- for (var j:int = 0; j < EMIT_SPARK_NUMBER; j++) {
- emitSpark();
- }
- updateSparks();
- renderSparks();
- }
- var sparksRenderingTime:uint = getTimer() - startTime;
- stats.text =
- "Number of Sparks : " + sparkNumber + "\n" +
- "Floor Rendering Time : " + floorRenderingTime + " ms\n" +
- "Sparks Rendering Time : " + sparksRenderingTime + " ms \n";
- }
- private function setupProjectionMatrix():void
- {
- perspective.fieldOfView = 60;
- projectionMatrix.identity();
- projectionMatrix.appendRotation(viewRotationY, Vector3D.Y_AXIS);
- projectionMatrix.appendRotation(viewRotationX, Vector3D.X_AXIS);
- projectionMatrix.appendTranslation(0, 0, perspective.focalLength);
- projectionMatrix.append(perspective.toMatrix3D());
- correctMatrix3DMultiplyBug(projectionMatrix);
- }
- private function correctMatrix3DMultiplyBug(matrix:Matrix3D):void
- {
- // see http://bugs.adobe.com/jira/browse/FP-670
- var m1:Matrix3D = new Matrix3D(Vector.<Number>([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 ]));
- var m2:Matrix3D = new Matrix3D(Vector.<Number>([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ]));
- m1.append(m2);
- if (m1.rawData[15] == 20) {
- // バグ持ち!
- var rawData:Vector.<Number> = matrix.rawData;
- rawData[15] /= 20;
- matrix.rawData = rawData;
- }
- }
- private function createSpark(x:Number, y:Number, z:Number, vx:Number, vy:Number, vz:Number, diameter:Number):void
- {
- position.push(x, y, z);
- velocity.push(vx, vy, vz);
- diameters.push(diameter);
- sparkNumber++;
- }
- private function emitSpark():void
- {
- var azimuth:Number = Math.random() * 2 * Math.PI;
- var vy:Number = -(Math.random() * 0.06 + 0.94);
- var vx:Number = Math.sqrt(1 - vy * vy) * Math.cos(azimuth);
- var vz:Number = Math.sqrt(1 - vy * vy) * Math.sin(azimuth);
- var speed:Number = Math.random() * 2.3 + 0.7;
- vx *= speed;
- vy *= speed;
- vz *= speed;
- var diameter:Number = 3 + Math.random() * 3;
- createSpark(0, -FIREWORK_HEIGHT, 0, vx, vy, vz, diameter);
- }
- private function updateSparks():void
- {
- for (var i:int = 0; i < sparkNumber; ) {
- var xIndex:int = i * 3;
- var yIndex:int = xIndex + 1;
- var zIndex:int = xIndex + 2;
- velocity[yIndex] += GRAVITY;
- velocity[xIndex] *= AIR_RESISTANCE;
- velocity[yIndex] *= AIR_RESISTANCE;
- velocity[zIndex] *= AIR_RESISTANCE;
- if (position[yIndex] + velocity[yIndex] > 0) {
- velocity[yIndex] = -velocity[yIndex] * 0.2;
- position[xIndex] += velocity[xIndex];
- position[yIndex] += velocity[yIndex];
- position[zIndex] += velocity[zIndex];
- // 小さい火花に分割
- const DIAMETER_MIN:Number = 2;
- if (diameters[i] > DIAMETER_MIN) {
- var diameterLimit:Number = diameters[i];
- while (1) {
- var diameter:Number = Math.random() * (4 - DIAMETER_MIN) + DIAMETER_MIN;
- diameterLimit -= diameter;
- if (diameterLimit < 0) {
- break;
- }
- var azimuth:Number = Math.random() * 2 * Math.PI;
- var r:Number = Math.random() * 2;
- createSpark(position[xIndex], position[yIndex], position[zIndex],
- (velocity[xIndex] + Math.cos(azimuth) * r) * 0.5,
- velocity[yIndex],
- (velocity[zIndex] + Math.sin(azimuth) * r) * 0.5,
- diameter);
- }
- }
- // spliceは重い!
- // position.splice(xIndex, 3);
- // velocity.splice(xIndex, 3);
- // diameters.splice(i, 1);
- position[xIndex] = position[sparkNumber * 3 - 3];
- position[yIndex] = position[sparkNumber * 3 - 2];
- position[zIndex] = position[sparkNumber * 3 - 1];
- velocity[xIndex] = velocity[sparkNumber * 3 - 3];
- velocity[yIndex] = velocity[sparkNumber * 3 - 2];
- velocity[zIndex] = velocity[sparkNumber * 3 - 1];
- diameters[i] = diameters[sparkNumber - 1];
- position.pop();
- position.pop();
- position.pop();
- velocity.pop();
- velocity.pop();
- velocity.pop();
- diameters.pop();
- sparkNumber--;
- continue;
- }
- position[xIndex] += velocity[xIndex];
- position[yIndex] += velocity[yIndex];
- position[zIndex] += velocity[zIndex];
- i++;
- }
- }
- private function renderSparks():void
- {
- splitBuffer.fillRect(splitBuffer.rect, 0x000000);
- Utils3D.projectVectors(projectionMatrix, position, projectedPosition, uvts);
- // ループ外に追い出したら30%以上高速化
- var p:Point = new Point();
- var focalLength:Number = perspective.focalLength;
- for (var i:int = 0; i < sparkNumber; i++) {
- // パーティクルの大きさ = 1/z * focalLength * pixel
- var diameter:int = uvts[i * 3 + 2] * focalLength * diameters[i] + 0.5;
- // (i * 2) => (i << 1)で10%ほど高速化
- p.x = CENTER_X + projectedPosition[(i << 1) ] - diameter / 2;
- p.y = CENTER_Y + projectedPosition[(i << 1) + 1] - diameter / 2;
- splitBuffer.copyPixels(sparkBitmapDatas[diameter], sparkBitmapDataRectangles[diameter], p);
- }
- displayBuffer.draw(splitBuffer, null, null, BlendMode.ADD);
- }
- private const FLOOR_SIZE:Number = 300;
- private const FLOOR_HALFSIZE:Number = FLOOR_SIZE / 2;
- private const FLOOR_VERTICES:Vector.<Number> = Vector.<Number>([
- FLOOR_HALFSIZE, 0, FLOOR_HALFSIZE,
- -FLOOR_HALFSIZE, 0, FLOOR_HALFSIZE,
- -FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE,
- FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE,
- FLOOR_HALFSIZE, 0, 0,
- -FLOOR_HALFSIZE, 0, 0,
- 0, 0, FLOOR_HALFSIZE,
- 0, 0, -FLOOR_HALFSIZE,
- ]);
- private const FLOOR_VERTEX_NUMBER:int = FLOOR_VERTICES.length / 3;
- private var floorProjectedVertices:Vector.<Number> = new Vector.<Number>();
- private var floorIndices:Vector.<int> = Vector.<int>([
- 0, 1, 2, 2, 3, 0
- ]);
- private var floorUvts:Vector.<Number> = Vector.<Number>([
- 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- ]);
- private const TEXTURE_SIZE:int = 150;
- private var floorTexture:BitmapData = new BitmapData(TEXTURE_SIZE, TEXTURE_SIZE, false);
- private const WIREFRAME_COLOR:uint = 0x555566;
- private var sprite:Sprite = new Sprite();
- private function renderFloor():void
- {
- // 照り返しを描画する閾値
- const THRESHOLD_Y:Number = 60;
- var matrix:Matrix = new Matrix();
- var colorTransform:ColorTransform = new ColorTransform();
- floorTexture.fillRect(floorTexture.rect, 0x180C00);
- for (var i:int = 0; i < sparkNumber; i++) {
- var yIndex:int = i * 3 + 1;
- if (position[yIndex] > -THRESHOLD_Y) {
- var xIndex:int = i * 3;
- var zIndex:int = i * 3 + 2;
- matrix.identity();
- var scale:Number = (0.2 - (position[yIndex] / THRESHOLD_Y) * 0.8) * diameters[i];
- matrix.scale(scale, scale);
- matrix.translate(FLOOR_HALFSIZE + position[xIndex] - REFLECTION_RADIUS * scale, FLOOR_HALFSIZE - position[zIndex] - REFLECTION_RADIUS * scale);
- matrix.scale(TEXTURE_SIZE / FLOOR_SIZE, TEXTURE_SIZE / FLOOR_SIZE);
- colorTransform.alphaMultiplier = 1 + position[yIndex] / THRESHOLD_Y;
- floorTexture.draw(reflectionBitmapData, matrix, colorTransform, BlendMode.ADD);
- }
- }
- Utils3D.projectVectors(projectionMatrix, FLOOR_VERTICES, floorProjectedVertices, floorUvts);
- for (i = 0; i < FLOOR_VERTEX_NUMBER; i++) {
- floorProjectedVertices[(i << 1) ] += CENTER_X;
- floorProjectedVertices[(i << 1) + 1] += CENTER_Y;
- }
- Utils3D.projectVectors(projectionMatrix, fireworkVertices, fireworkProjectedVertices, fireworkUvts);
- for (i = 0; i < fireworkProjectedVertices.length / 2; i++) {
- fireworkProjectedVertices[(i << 1) ] += CENTER_X;
- fireworkProjectedVertices[(i << 1) + 1] += CENTER_Y;
- }
- var g:Graphics = sprite.graphics;
- g.clear();
- g.beginBitmapFill(floorTexture);
- g.drawTriangles(floorProjectedVertices, floorIndices, floorUvts);
- g.endFill();
- displayBuffer.draw(sprite);
- g.clear();
- g.lineStyle(1, WIREFRAME_COLOR);
- g.moveTo(floorProjectedVertices[0], floorProjectedVertices[1]);
- g.lineTo(floorProjectedVertices[2], floorProjectedVertices[3]);
- g.lineTo(floorProjectedVertices[4], floorProjectedVertices[5]);
- g.lineTo(floorProjectedVertices[6], floorProjectedVertices[7]);
- g.lineTo(floorProjectedVertices[0], floorProjectedVertices[1]);
- g.moveTo(floorProjectedVertices[8], floorProjectedVertices[9]);
- g.lineTo(floorProjectedVertices[10], floorProjectedVertices[11]);
- g.moveTo(floorProjectedVertices[12], floorProjectedVertices[13]);
- g.lineTo(floorProjectedVertices[14], floorProjectedVertices[15]);
- displayBuffer.draw(sprite, null, null, BlendMode.ADD);
- g.clear();
- g.beginFill(FIREWORK_COLOR);
- g.drawTriangles(fireworkProjectedVertices, fireworkIndices);
- g.endFill();
- displayBuffer.draw(sprite);
- }
- private const FIREWORK_RADIUS:Number = 8;
- private const FIREWORK_HEIGHT:Number = 40;
- private const FIREWORK_COLOR:uint = 0xAACCFF;
- private var fireworkVertices:Vector.<Number> = new Vector.<Number>();
- private var fireworkIndices:Vector.<int> = new Vector.<int>();
- private var fireworkProjectedVertices:Vector.<Number> = new Vector.<Number>();
- private var fireworkUvts:Vector.<Number> = new Vector.<Number>();
- private function createFireworkModel():void
- {
- const SEGMENT:int = 8;
- for (var i:int = 0; i < SEGMENT; i++) {
- var x:Number = Math.cos(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
- var z:Number = Math.sin(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
- fireworkVertices.push(x, -FIREWORK_HEIGHT, z);
- fireworkVertices.push(x, 0, z);
- var i0:int = (i * 2 ) % (SEGMENT * 2);
- var i1:int = (i * 2 + 1) % (SEGMENT * 2);
- var i2:int = (i * 2 + 2) % (SEGMENT * 2);
- var i3:int = (i * 2 + 3) % (SEGMENT * 2);
- fireworkIndices.push(i2, i0, i1);
- fireworkIndices.push(i1, i3, i2);
- }
- }
- }
- }
forked from: forked from: PS2 Firework (Particles and Motion blur) forked from: forked from: forked from: PS2 Firework (Particles and Motion blur)
- // forked from hacker_fhynon_3's forked from: forked from: PS2 Firework (Particles and Motion blur)
- // forked from rintarock's forked from: PS2 Firework (Particles and Motion blur)
- // forked from kohring's PS2 Firework (Particles and Motion blur)
- package {
- import flash.display.*;
- import flash.events.*;
- import flash.filters.*;
- import flash.geom.*;
- import flash.text.*;
- import flash.utils.*;
- [SWF(width="465", height="465", frameRate="60")]
- public class Firework extends Sprite
- {
- // 火花
- private var position:Vector.<Number> = new Vector.<Number>();
- private var velocity:Vector.<Number> = new Vector.<Number>();
- private var diameters:Vector.<Number> = new Vector.<Number>();
- private var sparkNumber:Number = 0;
- private var projectedPosition:Vector.<Number> = new Vector.<Number>();
- private var uvts:Vector.<Number> = new Vector.<Number>();
- private var sparkBitmapDatas:Vector.<BitmapData> = new Vector.<BitmapData>();
- private var sparkBitmapDataRectangles:Vector.<Rectangle> = new Vector.<Rectangle>();
- private var c_r:uint = Math.random() *0xFF0000;
- private var c_g:uint = Math.random() *0x00FF00;
- private var c_b:uint = Math.random() *0x0000FF;
- private var SPARK_COLOR:uint = 0x289733;
- //private var SPARK_COLOR:uint = c_r + c_g + c_b;
- private const GRAVITY:Number = 0.02;
- private const AIR_RESISTANCE:Number = 0.999;
- // 1フレームに放出する火花の数
- private const EMIT_SPARK_NUMBER:int = 1;
- // 照り返し
- private var reflectionBitmapData:BitmapData;
- private const REFLECTION_COLOR:uint = 0xFF1800;
- private const REFLECTION_RADIUS:Number = 16;
- // フレームバッファ
- private var displayBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
- private var splitBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
- private const NUMBER_OF_SPLIT_FRAME:int = 10;
- private var perspective:PerspectiveProjection = new PerspectiveProjection();
- private var projectionMatrix:Matrix3D = new Matrix3D();
- private var viewRotationY:Number = 0;
- private var viewRotationX:Number = 25;
- private const CENTER_X:Number = stage.stageWidth / 2;
- private const CENTER_Y:Number = stage.stageHeight * 0.65;
- private var stats:TextField = new TextField();
- public function Firework()
- {
- addChild(new Bitmap(displayBuffer));
- stats.x = 5;
- stats.y = 5;
- stats.autoSize = TextFieldAutoSize.LEFT;
- stats.textColor = 0xFFFFFF;
- addChild(stats);
- var shape:Shape = new Shape();
- var g:Graphics = shape.graphics;
- // 火花のプリレンダリング
- var bitmapData:BitmapData = new BitmapData(1, 1, true, SPARK_COLOR);
- sparkBitmapDatas.push(bitmapData);
- sparkBitmapDataRectangles.push(bitmapData.rect);
- for (var diameter:int = 1; diameter <= 32; diameter++) {
- bitmapData = new BitmapData(diameter, diameter, true, 0);
- g.clear();
- g.beginFill(SPARK_COLOR);
- var radius:Number = diameter / 2;
- g.drawCircle(radius, radius, radius);
- g.endFill();
- bitmapData.draw(shape);
- sparkBitmapDatas.push(bitmapData);
- sparkBitmapDataRectangles.push(bitmapData.rect);
- // bitmapData.rectはアクセサで重いのでキャッシュしておく。これにより30%ほど高速化
- }
- // 照り返しのプリレンダリング
- reflectionBitmapData = new BitmapData(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2, true, 0);
- g.clear();
- var matrix:Matrix = new Matrix();
- matrix.createGradientBox(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2, 0, 0, 0);
- g.beginGradientFill(GradientType.RADIAL, [ REFLECTION_COLOR, REFLECTION_COLOR ], [ 1, 0 ], [ 0, 255 ], matrix);
- g.drawCircle(REFLECTION_RADIUS, REFLECTION_RADIUS, REFLECTION_RADIUS);
- g.endFill();
- reflectionBitmapData.draw(shape);
- createFireworkModel();
- addEventListener(Event.ENTER_FRAME, enterFrameHandler);
- // stage.addEventListener(MouseEvent.CLICK, function (e:Event):void {
- // emitSpark();
- // });
- }
- private function enterFrameHandler(e:Event):void
- {
- displayBuffer.fillRect(displayBuffer.rect, 0);
- setupProjectionMatrix();
- var startTime:uint = getTimer();
- renderFloor();
- var floorRenderingTime:uint = getTimer() - startTime;
- startTime = getTimer();
- for (var i:int = 0; i < NUMBER_OF_SPLIT_FRAME; i++) {
- const FACTOR:Number = 0.06;
- viewRotationY += (getTimer() * 0.01 + (-(CENTER_X - mouseX) * 0.4) - viewRotationY) * FACTOR;
- viewRotationX += ((27 + (CENTER_Y - mouseY) * 0.15) - viewRotationX) * FACTOR;
- setupProjectionMatrix();
- for (var j:int = 0; j < EMIT_SPARK_NUMBER; j++) {
- emitSpark();
- }
- updateSparks();
- renderSparks();
- }
- var sparksRenderingTime:uint = getTimer() - startTime;
- stats.text =
- "Number of Sparks : " + sparkNumber + "\n" +
- "Floor Rendering Time : " + floorRenderingTime + " ms\n" +
- "Sparks Rendering Time : " + sparksRenderingTime + " ms \n";
- }
- private function setupProjectionMatrix():void
- {
- perspective.fieldOfView = 60;
- projectionMatrix.identity();
- projectionMatrix.appendRotation(viewRotationY, Vector3D.Y_AXIS);
- projectionMatrix.appendRotation(viewRotationX, Vector3D.X_AXIS);
- projectionMatrix.appendTranslation(0, 0, perspective.focalLength);
- projectionMatrix.append(perspective.toMatrix3D());
- correctMatrix3DMultiplyBug(projectionMatrix);
- }
- private function correctMatrix3DMultiplyBug(matrix:Matrix3D):void
- {
- // see http://bugs.adobe.com/jira/browse/FP-670
- var m1:Matrix3D = new Matrix3D(Vector.<Number>([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 ]));
- var m2:Matrix3D = new Matrix3D(Vector.<Number>([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ]));
- m1.append(m2);
- if (m1.rawData[15] == 20) {
- // バグ持ち!
- var rawData:Vector.<Number> = matrix.rawData;
- rawData[15] /= 20;
- matrix.rawData = rawData;
- }
- }
- private function createSpark(x:Number, y:Number, z:Number, vx:Number, vy:Number, vz:Number, diameter:Number):void
- {
- position.push(x, y, z);
- velocity.push(vx, vy, vz);
- diameters.push(diameter);
- sparkNumber++;
- }
- private function emitSpark():void
- {
- var azimuth:Number = Math.random() * 2 * Math.PI;
- var vy:Number = -(Math.random() * 0.06 + 0.94);
- var vx:Number = Math.sqrt(1 - vy * vy) * Math.cos(azimuth);
- var vz:Number = Math.sqrt(1 - vy * vy) * Math.sin(azimuth);
- var speed:Number = Math.random() * 2.3 + 0.7;
- vx *= speed;
- vy *= speed;
- vz *= speed;
- var diameter:Number = 3 + Math.random() * 3;
- createSpark(0, -FIREWORK_HEIGHT, 0, vx, vy, vz, diameter);
- }
- private function updateSparks():void
- {
- for (var i:int = 0; i < sparkNumber; ) {
- var xIndex:int = i * 3;
- var yIndex:int = xIndex + 1;
- var zIndex:int = xIndex + 2;
- velocity[yIndex] += GRAVITY;
- velocity[xIndex] *= AIR_RESISTANCE;
- velocity[yIndex] *= AIR_RESISTANCE;
- velocity[zIndex] *= AIR_RESISTANCE;
- if (position[yIndex] + velocity[yIndex] > 0) {
- velocity[yIndex] = -velocity[yIndex] * 0.2;
- position[xIndex] += velocity[xIndex];
- position[yIndex] += velocity[yIndex];
- position[zIndex] += velocity[zIndex];
- // 小さい火花に分割
- const DIAMETER_MIN:Number = 2;
- if (diameters[i] > DIAMETER_MIN) {
- var diameterLimit:Number = diameters[i];
- while (1) {
- var diameter:Number = Math.random() * (4 - DIAMETER_MIN) + DIAMETER_MIN;
- diameterLimit -= diameter;
- if (diameterLimit < 0) {
- break;
- }
- var azimuth:Number = Math.random() * 2 * Math.PI;
- var r:Number = Math.random() * 2;
- createSpark(position[xIndex], position[yIndex], position[zIndex],
- (velocity[xIndex] + Math.cos(azimuth) * r) * 0.5,
- velocity[yIndex],
- (velocity[zIndex] + Math.sin(azimuth) * r) * 0.5,
- diameter);
- }
- }
- // spliceは重い!
- // position.splice(xIndex, 3);
- // velocity.splice(xIndex, 3);
- // diameters.splice(i, 1);
- position[xIndex] = position[sparkNumber * 3 - 3];
- position[yIndex] = position[sparkNumber * 3 - 2];
- position[zIndex] = position[sparkNumber * 3 - 1];
- velocity[xIndex] = velocity[sparkNumber * 3 - 3];
- velocity[yIndex] = velocity[sparkNumber * 3 - 2];
- velocity[zIndex] = velocity[sparkNumber * 3 - 1];
- diameters[i] = diameters[sparkNumber - 1];
- position.pop();
- position.pop();
- position.pop();
- velocity.pop();
- velocity.pop();
- velocity.pop();
- diameters.pop();
- sparkNumber--;
- continue;
- }
- position[xIndex] += velocity[xIndex];
- position[yIndex] += velocity[yIndex];
- position[zIndex] += velocity[zIndex];
- i++;
- }
- }
- private function renderSparks():void
- {
- splitBuffer.fillRect(splitBuffer.rect, 0x000000);
- Utils3D.projectVectors(projectionMatrix, position, projectedPosition, uvts);
- // ループ外に追い出したら30%以上高速化
- var p:Point = new Point();
- var focalLength:Number = perspective.focalLength;
- for (var i:int = 0; i < sparkNumber; i++) {
- // パーティクルの大きさ = 1/z * focalLength * pixel
- var diameter:int = uvts[i * 3 + 2] * focalLength * diameters[i] + 0.5;
- // (i * 2) => (i << 1)で10%ほど高速化
- p.x = CENTER_X + projectedPosition[(i << 1) ] - diameter / 2;
- p.y = CENTER_Y + projectedPosition[(i << 1) + 1] - diameter / 2;
- splitBuffer.copyPixels(sparkBitmapDatas[diameter], sparkBitmapDataRectangles[diameter], p);
- }
- displayBuffer.draw(splitBuffer, null, null, BlendMode.ADD);
- }
- private const FLOOR_SIZE:Number = 300;
- private const FLOOR_HALFSIZE:Number = FLOOR_SIZE / 2;
- private const FLOOR_VERTICES:Vector.<Number> = Vector.<Number>([
- FLOOR_HALFSIZE, 0, FLOOR_HALFSIZE,
- -FLOOR_HALFSIZE, 0, FLOOR_HALFSIZE,
- -FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE,
- FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE,
- FLOOR_HALFSIZE, 0, 0,
- -FLOOR_HALFSIZE, 0, 0,
- 0, 0, FLOOR_HALFSIZE,
- 0, 0, -FLOOR_HALFSIZE,
- ]);
- private const FLOOR_VERTEX_NUMBER:int = FLOOR_VERTICES.length / 3;
- private var floorProjectedVertices:Vector.<Number> = new Vector.<Number>();
- private var floorIndices:Vector.<int> = Vector.<int>([
- 0, 1, 2, 2, 3, 0
- ]);
- private var floorUvts:Vector.<Number> = Vector.<Number>([
- 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- ]);
- private const TEXTURE_SIZE:int = 150;
- private var floorTexture:BitmapData = new BitmapData(TEXTURE_SIZE, TEXTURE_SIZE, false);
- private const WIREFRAME_COLOR:uint = 0x555566;
- private var sprite:Sprite = new Sprite();
- private function renderFloor():void
- {
- // 照り返しを描画する閾値
- const THRESHOLD_Y:Number = 50;
- var matrix:Matrix = new Matrix();
- var colorTransform:ColorTransform = new ColorTransform();
- floorTexture.fillRect(floorTexture.rect, 0x180C00);
- for (var i:int = 0; i < sparkNumber; i++) {
- var yIndex:int = i * 3 + 1;
- if (position[yIndex] > -THRESHOLD_Y) {
- var xIndex:int = i * 3;
- var zIndex:int = i * 3 + 2;
- matrix.identity();
- var scale:Number = (0.2 - (position[yIndex] / THRESHOLD_Y) * 0.8) * diameters[i];
- matrix.scale(scale, scale);
- matrix.translate(FLOOR_HALFSIZE + position[xIndex] - REFLECTION_RADIUS * scale, FLOOR_HALFSIZE - position[zIndex] - REFLECTION_RADIUS * scale);
- matrix.scale(TEXTURE_SIZE / FLOOR_SIZE, TEXTURE_SIZE / FLOOR_SIZE);
- colorTransform.alphaMultiplier = 1 + position[yIndex] / THRESHOLD_Y;
- floorTexture.draw(reflectionBitmapData, matrix, colorTransform, BlendMode.ADD);
- }
- }
- Utils3D.projectVectors(projectionMatrix, FLOOR_VERTICES, floorProjectedVertices, floorUvts);
- for (i = 0; i < FLOOR_VERTEX_NUMBER; i++) {
- floorProjectedVertices[(i << 1) ] += CENTER_X;
- floorProjectedVertices[(i << 1) + 1] += CENTER_Y;
- }
- Utils3D.projectVectors(projectionMatrix, fireworkVertices, fireworkProjectedVertices, fireworkUvts);
- for (i = 0; i < fireworkProjectedVertices.length / 2; i++) {
- fireworkProjectedVertices[(i << 1) ] += CENTER_X;
- fireworkProjectedVertices[(i << 1) + 1] += CENTER_Y;
- }
- var g:Graphics = sprite.graphics;
- g.clear();
- g.beginBitmapFill(floorTexture);
- g.drawTriangles(floorProjectedVertices, floorIndices, floorUvts);
- g.endFill();
- displayBuffer.draw(sprite);
- g.clear();
- g.lineStyle(1, WIREFRAME_COLOR);
- g.moveTo(floorProjectedVertices[0], floorProjectedVertices[1]);
- g.lineTo(floorProjectedVertices[2], floorProjectedVertices[3]);
- g.lineTo(floorProjectedVertices[4], floorProjectedVertices[5]);
- g.lineTo(floorProjectedVertices[6], floorProjectedVertices[7]);
- g.lineTo(floorProjectedVertices[0], floorProjectedVertices[1]);
- g.moveTo(floorProjectedVertices[8], floorProjectedVertices[9]);
- g.lineTo(floorProjectedVertices[10], floorProjectedVertices[11]);
- g.moveTo(floorProjectedVertices[12], floorProjectedVertices[13]);
- g.lineTo(floorProjectedVertices[14], floorProjectedVertices[15]);
- displayBuffer.draw(sprite, null, null, BlendMode.ADD);
- g.clear();
- g.beginFill(FIREWORK_COLOR);
- g.drawTriangles(fireworkProjectedVertices, fireworkIndices);
- g.endFill();
- displayBuffer.draw(sprite);
- }
- private const FIREWORK_RADIUS:Number = 8;
- private const FIREWORK_HEIGHT:Number = 40;
- private const FIREWORK_COLOR:uint = 0xAACCFF;
- private var fireworkVertices:Vector.<Number> = new Vector.<Number>();
- private var fireworkIndices:Vector.<int> = new Vector.<int>();
- private var fireworkProjectedVertices:Vector.<Number> = new Vector.<Number>();
- private var fireworkUvts:Vector.<Number> = new Vector.<Number>();
- private function createFireworkModel():void
- {
- const SEGMENT:int = 8;
- for (var i:int = 0; i < SEGMENT; i++) {
- var x:Number = Math.cos(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
- var z:Number = Math.sin(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
- fireworkVertices.push(x, -FIREWORK_HEIGHT, z);
- fireworkVertices.push(x, 0, z);
- var i0:int = (i * 2 ) % (SEGMENT * 2);
- var i1:int = (i * 2 + 1) % (SEGMENT * 2);
- var i2:int = (i * 2 + 2) % (SEGMENT * 2);
- var i3:int = (i * 2 + 3) % (SEGMENT * 2);
- fireworkIndices.push(i2, i0, i1);
- fireworkIndices.push(i1, i3, i2);
- }
- }
- }
- }
forked from: forked from: PS2 Firework (Particles and Motion blur) forked from: forked from: forked from: PS2 Firework (Particles and Motion blur)
- // forked from hacker_fhynon_3's forked from: forked from: PS2 Firework (Particles and Motion blur)
- // forked from rintarock's forked from: PS2 Firework (Particles and Motion blur)
- // forked from kohring's PS2 Firework (Particles and Motion blur)
- package {
- import flash.display.*;
- import flash.events.*;
- import flash.filters.*;
- import flash.geom.*;
- import flash.text.*;
- import flash.utils.*;
- [SWF(width="465", height="465", frameRate="60")]
- public class Firework extends Sprite
- {
- // 火花
- private var position:Vector.<Number> = new Vector.<Number>();
- private var velocity:Vector.<Number> = new Vector.<Number>();
- private var diameters:Vector.<Number> = new Vector.<Number>();
- private var sparkNumber:Number = 0;
- private var projectedPosition:Vector.<Number> = new Vector.<Number>();
- private var uvts:Vector.<Number> = new Vector.<Number>();
- private var sparkBitmapDatas:Vector.<BitmapData> = new Vector.<BitmapData>();
- private var sparkBitmapDataRectangles:Vector.<Rectangle> = new Vector.<Rectangle>();
- private const SPARK_COLOR:uint = 0xE0E215;
- private const GRAVITY:Number = 0.05;
- private const AIR_RESISTANCE:Number = 1;
- // 1フレームに放出する火花の数
- private const EMIT_SPARK_NUMBER:int = 1;
- // 照り返し
- private var reflectionBitmapData:BitmapData;
- private const REFLECTION_COLOR:uint = 0xFF1800;
- private const REFLECTION_RADIUS:Number = 16;
- // フレームバッファ
- private var displayBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
- private var splitBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
- private const NUMBER_OF_SPLIT_FRAME:int = 10;
- private var perspective:PerspectiveProjection = new PerspectiveProjection();
- private var projectionMatrix:Matrix3D = new Matrix3D();
- private var viewRotationY:Number = 0;
- private var viewRotationX:Number = 25;
- private const CENTER_X:Number = stage.stageWidth / 2;
- private const CENTER_Y:Number = stage.stageHeight * 0.65;
- private var stats:TextField = new TextField();
- public function Firework()
- {
- addChild(new Bitmap(displayBuffer));
- stats.x = 5;
- stats.y = 5;
- stats.autoSize = TextFieldAutoSize.LEFT;
- stats.textColor = 0xFFFFFF;
- addChild(stats);
- var shape:Shape = new Shape();
- var g:Graphics = shape.graphics;
- // 火花のプリレンダリング
- var bitmapData:BitmapData = new BitmapData(1, 1, true, SPARK_COLOR);
- sparkBitmapDatas.push(bitmapData);
- sparkBitmapDataRectangles.push(bitmapData.rect);
- for (var diameter:int = 1; diameter <= 32; diameter++) {
- bitmapData = new BitmapData(diameter, diameter, true, 0);
- g.clear();
- g.beginFill(SPARK_COLOR);
- var radius:Number = diameter / 2;
- g.drawCircle(radius, radius, radius);
- g.endFill();
- bitmapData.draw(shape);
- sparkBitmapDatas.push(bitmapData);
- sparkBitmapDataRectangles.push(bitmapData.rect);
- // bitmapData.rectはアクセサで重いのでキャッシュしておく。これにより30%ほど高速化
- }
- // 照り返しのプリレンダリング
- reflectionBitmapData = new BitmapData(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2, true, 0);
- g.clear();
- var matrix:Matrix = new Matrix();
- matrix.createGradientBox(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2, 0, 0, 0);
- g.beginGradientFill(GradientType.RADIAL, [ REFLECTION_COLOR, REFLECTION_COLOR ], [ 1, 0 ], [ 0, 255 ], matrix);
- g.drawCircle(REFLECTION_RADIUS, REFLECTION_RADIUS, REFLECTION_RADIUS);
- g.endFill();
- reflectionBitmapData.draw(shape);
- createFireworkModel();
- addEventListener(Event.ENTER_FRAME, enterFrameHandler);
- // stage.addEventListener(MouseEvent.CLICK, function (e:Event):void {
- // emitSpark();
- // });
- }
- private function enterFrameHandler(e:Event):void
- {
- displayBuffer.fillRect(displayBuffer.rect, 0);
- setupProjectionMatrix();
- var startTime:uint = getTimer();
- renderFloor();
- var floorRenderingTime:uint = getTimer() - startTime;
- startTime = getTimer();
- for (var i:int = 0; i < NUMBER_OF_SPLIT_FRAME; i++) {
- const FACTOR:Number = 0.06;
- viewRotationY += (getTimer() * 0.01 + (-(CENTER_X - mouseX) * 0.4) - viewRotationY) * FACTOR;
- viewRotationX += ((27 + (CENTER_Y - mouseY) * 0.15) - viewRotationX) * FACTOR;
- setupProjectionMatrix();
- for (var j:int = 0; j < EMIT_SPARK_NUMBER; j++) {
- emitSpark();
- }
- updateSparks();
- renderSparks();
- }
- var sparksRenderingTime:uint = getTimer() - startTime;
- stats.text =
- "Number of Sparks : " + sparkNumber + "\n" +
- "Floor Rendering Time : " + floorRenderingTime + " ms\n" +
- "Sparks Rendering Time : " + sparksRenderingTime + " ms \n";
- }
- private function setupProjectionMatrix():void
- {
- perspective.fieldOfView = 60;
- projectionMatrix.identity();
- projectionMatrix.appendRotation(viewRotationY, Vector3D.Y_AXIS);
- projectionMatrix.appendRotation(viewRotationX, Vector3D.X_AXIS);
- projectionMatrix.appendTranslation(0, 0, perspective.focalLength);
- projectionMatrix.append(perspective.toMatrix3D());
- correctMatrix3DMultiplyBug(projectionMatrix);
- }
- private function correctMatrix3DMultiplyBug(matrix:Matrix3D):void
- {
- // see http://bugs.adobe.com/jira/browse/FP-670
- var m1:Matrix3D = new Matrix3D(Vector.<Number>([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 ]));
- var m2:Matrix3D = new Matrix3D(Vector.<Number>([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ]));
- m1.append(m2);
- if (m1.rawData[15] == 20) {
- // バグ持ち!
- var rawData:Vector.<Number> = matrix.rawData;
- rawData[15] /= 20;
- matrix.rawData = rawData;
- }
- }
- private function createSpark(x:Number, y:Number, z:Number, vx:Number, vy:Number, vz:Number, diameter:Number):void
- {
- position.push(x, y, z);
- velocity.push(vx, vy, vz);
- diameters.push(diameter);
- sparkNumber++;
- }
- private function emitSpark():void
- {
- var azimuth:Number = Math.random() * 2 * Math.PI;
- var vy:Number = -(Math.random() * 0.06 + 0.94);
- var vx:Number = Math.sqrt(1 - vy * vy) * Math.cos(azimuth);
- var vz:Number = Math.sqrt(1 - vy * vy) * Math.sin(azimuth);
- var speed:Number = Math.random() * 2.3 + 0.7;
- vx *= speed;
- vy *= speed;
- vz *= speed;
- var diameter:Number = 3 + Math.random() * 3;
- createSpark(0, -FIREWORK_HEIGHT, 0, vx, vy, vz, diameter);
- }
- private function updateSparks():void
- {
- for (var i:int = 0; i < sparkNumber; ) {
- var xIndex:int = i * 3;
- var yIndex:int = xIndex + 1;
- var zIndex:int = xIndex + 2;
- velocity[yIndex] += GRAVITY;
- velocity[xIndex] *= AIR_RESISTANCE;
- velocity[yIndex] *= AIR_RESISTANCE;
- velocity[zIndex] *= AIR_RESISTANCE;
- if (position[yIndex] + velocity[yIndex] > 0) {
- velocity[yIndex] = -velocity[yIndex] * 0.2;
- position[xIndex] += velocity[xIndex];
- position[yIndex] += velocity[yIndex];
- position[zIndex] += velocity[zIndex];
- // 小さい火花に分割
- const DIAMETER_MIN:Number = 2;
- if (diameters[i] > DIAMETER_MIN) {
- var diameterLimit:Number = diameters[i];
- while (1) {
- var diameter:Number = Math.random() * (4 - DIAMETER_MIN) + DIAMETER_MIN;
- diameterLimit -= diameter;
- if (diameterLimit < 0) {
- break;
- }
- var azimuth:Number = Math.random() * 2 * Math.PI;
- var r:Number = Math.random() * 2;
- createSpark(position[xIndex], position[yIndex], position[zIndex],
- (velocity[xIndex] + Math.cos(azimuth) * r) * 0.5,
- velocity[yIndex],
- (velocity[zIndex] + Math.sin(azimuth) * r) * 0.5,
- diameter);
- }
- }
- // spliceは重い!
- // position.splice(xIndex, 3);
- // velocity.splice(xIndex, 3);
- // diameters.splice(i, 1);
- position[xIndex] = position[sparkNumber * 3 - 3];
- position[yIndex] = position[sparkNumber * 3 - 2];
- position[zIndex] = position[sparkNumber * 3 - 1];
- velocity[xIndex] = velocity[sparkNumber * 3 - 3];
- velocity[yIndex] = velocity[sparkNumber * 3 - 2];
- velocity[zIndex] = velocity[sparkNumber * 3 - 1];
- diameters[i] = diameters[sparkNumber - 1];
- position.pop();
- position.pop();
- position.pop();
- velocity.pop();
- velocity.pop();
- velocity.pop();
- diameters.pop();
- sparkNumber--;
- continue;
- }
- position[xIndex] += velocity[xIndex];
- position[yIndex] += velocity[yIndex];
- position[zIndex] += velocity[zIndex];
- i++;
- }
- }
- private function renderSparks():void
- {
- splitBuffer.fillRect(splitBuffer.rect, 0x000000);
- Utils3D.projectVectors(projectionMatrix, position, projectedPosition, uvts);
- // ループ外に追い出したら30%以上高速化
- var p:Point = new Point();
- var focalLength:Number = perspective.focalLength;
- for (var i:int = 0; i < sparkNumber; i++) {
- // パーティクルの大きさ = 1/z * focalLength * pixel
- var diameter:int = uvts[i * 3 + 2] * focalLength * diameters[i] + 0.5;
- // (i * 2) => (i << 1)で10%ほど高速化
- p.x = CENTER_X + projectedPosition[(i << 1) ] - diameter / 2;
- p.y = CENTER_Y + projectedPosition[(i << 1) + 1] - diameter / 2;
- splitBuffer.copyPixels(sparkBitmapDatas[diameter], sparkBitmapDataRectangles[diameter], p);
- }
- displayBuffer.draw(splitBuffer, null, null, BlendMode.ADD);
- }
- private const FLOOR_SIZE:Number = 300;
- private const FLOOR_HALFSIZE:Number = FLOOR_SIZE / 2;
- private const FLOOR_VERTICES:Vector.<Number> = Vector.<Number>([
- FLOOR_HALFSIZE, 0, FLOOR_HALFSIZE,
- -FLOOR_HALFSIZE, 0, FLOOR_HALFSIZE,
- -FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE,
- FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE,
- FLOOR_HALFSIZE, 0, 0,
- -FLOOR_HALFSIZE, 0, 0,
- 0, 0, FLOOR_HALFSIZE,
- 0, 0, -FLOOR_HALFSIZE,
- ]);
- private const FLOOR_VERTEX_NUMBER:int = FLOOR_VERTICES.length / 3;
- private var floorProjectedVertices:Vector.<Number> = new Vector.<Number>();
- private var floorIndices:Vector.<int> = Vector.<int>([
- 0, 1, 2, 2, 3, 0
- ]);
- private var floorUvts:Vector.<Number> = Vector.<Number>([
- 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- ]);
- private const TEXTURE_SIZE:int = 150;
- private var floorTexture:BitmapData = new BitmapData(TEXTURE_SIZE, TEXTURE_SIZE, false);
- private const WIREFRAME_COLOR:uint = 0x555566;
- private var sprite:Sprite = new Sprite();
- private function renderFloor():void
- {
- // 照り返しを描画する閾値
- const THRESHOLD_Y:Number = 50;
- var matrix:Matrix = new Matrix();
- var colorTransform:ColorTransform = new ColorTransform();
- floorTexture.fillRect(floorTexture.rect, 0x180C00);
- for (var i:int = 0; i < sparkNumber; i++) {
- var yIndex:int = i * 3 + 1;
- if (position[yIndex] > -THRESHOLD_Y) {
- var xIndex:int = i * 3;
- var zIndex:int = i * 3 + 2;
- matrix.identity();
- var scale:Number = (0.2 - (position[yIndex] / THRESHOLD_Y) * 0.8) * diameters[i];
- matrix.scale(scale, scale);
- matrix.translate(FLOOR_HALFSIZE + position[xIndex] - REFLECTION_RADIUS * scale, FLOOR_HALFSIZE - position[zIndex] - REFLECTION_RADIUS * scale);
- matrix.scale(TEXTURE_SIZE / FLOOR_SIZE, TEXTURE_SIZE / FLOOR_SIZE);
- colorTransform.alphaMultiplier = 1 + position[yIndex] / THRESHOLD_Y;
- floorTexture.draw(reflectionBitmapData, matrix, colorTransform, BlendMode.ADD);
- }
- }
- Utils3D.projectVectors(projectionMatrix, FLOOR_VERTICES, floorProjectedVertices, floorUvts);
- for (i = 0; i < FLOOR_VERTEX_NUMBER; i++) {
- floorProjectedVertices[(i << 1) ] += CENTER_X;
- floorProjectedVertices[(i << 1) + 1] += CENTER_Y;
- }
- Utils3D.projectVectors(projectionMatrix, fireworkVertices, fireworkProjectedVertices, fireworkUvts);
- for (i = 0; i < fireworkProjectedVertices.length / 2; i++) {
- fireworkProjectedVertices[(i << 1) ] += CENTER_X;
- fireworkProjectedVertices[(i << 1) + 1] += CENTER_Y;
- }
- var g:Graphics = sprite.graphics;
- g.clear();
- g.beginBitmapFill(floorTexture);
- g.drawTriangles(floorProjectedVertices, floorIndices, floorUvts);
- g.endFill();
- displayBuffer.draw(sprite);
- g.clear();
- g.lineStyle(1, WIREFRAME_COLOR);
- g.moveTo(floorProjectedVertices[0], floorProjectedVertices[1]);
- g.lineTo(floorProjectedVertices[2], floorProjectedVertices[3]);
- g.lineTo(floorProjectedVertices[4], floorProjectedVertices[5]);
- g.lineTo(floorProjectedVertices[6], floorProjectedVertices[7]);
- g.lineTo(floorProjectedVertices[0], floorProjectedVertices[1]);
- g.moveTo(floorProjectedVertices[8], floorProjectedVertices[9]);
- g.lineTo(floorProjectedVertices[10], floorProjectedVertices[11]);
- g.moveTo(floorProjectedVertices[12], floorProjectedVertices[13]);
- g.lineTo(floorProjectedVertices[14], floorProjectedVertices[15]);
- displayBuffer.draw(sprite, null, null, BlendMode.ADD);
- g.clear();
- g.beginFill(FIREWORK_COLOR);
- g.drawTriangles(fireworkProjectedVertices, fireworkIndices);
- g.endFill();
- displayBuffer.draw(sprite);
- }
- private const FIREWORK_RADIUS:Number = 8;
- private const FIREWORK_HEIGHT:Number = 40;
- private const FIREWORK_COLOR:uint = 0xAACCFF;
- private var fireworkVertices:Vector.<Number> = new Vector.<Number>();
- private var fireworkIndices:Vector.<int> = new Vector.<int>();
- private var fireworkProjectedVertices:Vector.<Number> = new Vector.<Number>();
- private var fireworkUvts:Vector.<Number> = new Vector.<Number>();
- private function createFireworkModel():void
- {
- const SEGMENT:int = 8;
- for (var i:int = 0; i < SEGMENT; i++) {
- var x:Number = Math.cos(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
- var z:Number = Math.sin(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
- fireworkVertices.push(x, -FIREWORK_HEIGHT, z);
- fireworkVertices.push(x, 0, z);
- var i0:int = (i * 2 ) % (SEGMENT * 2);
- var i1:int = (i * 2 + 1) % (SEGMENT * 2);
- var i2:int = (i * 2 + 2) % (SEGMENT * 2);
- var i3:int = (i * 2 + 3) % (SEGMENT * 2);
- fireworkIndices.push(i2, i0, i1);
- fireworkIndices.push(i1, i3, i2);
- }
- }
- }
- }
forked from: forked from: PS2 Firework (Particles and Motion blur) forked from: forked from: forked from: PS2 Firework (Particles and Motion blur)
- // forked from hacker_fhynon_3's forked from: forked from: PS2 Firework (Particles and Motion blur)
- // forked from rintarock's forked from: PS2 Firework (Particles and Motion blur)
- // forked from kohring's PS2 Firework (Particles and Motion blur)
- package {
- import flash.display.*;
- import flash.events.*;
- import flash.filters.*;
- import flash.geom.*;
- import flash.text.*;
- import flash.utils.*;
- [SWF(width="465", height="465", frameRate="60")]
- public class Firework extends Sprite
- {
- // 火花
- private var position:Vector.<Number> = new Vector.<Number>();
- private var velocity:Vector.<Number> = new Vector.<Number>();
- private var diameters:Vector.<Number> = new Vector.<Number>();
- private var sparkNumber:Number = 0;
- private var projectedPosition:Vector.<Number> = new Vector.<Number>();
- private var uvts:Vector.<Number> = new Vector.<Number>();
- private var sparkBitmapDatas:Vector.<BitmapData> = new Vector.<BitmapData>();
- private var sparkBitmapDataRectangles:Vector.<Rectangle> = new Vector.<Rectangle>();
- private const SPARK_COLOR:uint = 0x002299;
- private const GRAVITY:Number = 0.04;
- private const AIR_RESISTANCE:Number = 1.006;
- // 1フレームに放出する火花の数
- private const EMIT_SPARK_NUMBER:int = 8;
- // 照り返し
- private var reflectionBitmapData:BitmapData;
- private const REFLECTION_COLOR:uint = 0x002299;
- private const REFLECTION_RADIUS:Number = 4;
- // フレームバッファ
- private var displayBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
- private var splitBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
- private const NUMBER_OF_SPLIT_FRAME:int = 10;
- private var perspective:PerspectiveProjection = new PerspectiveProjection();
- private var projectionMatrix:Matrix3D = new Matrix3D();
- private var viewRotationY:Number = 0;
- private var viewRotationX:Number = 25;
- private const CENTER_X:Number = stage.stageWidth / 2;
- private const CENTER_Y:Number = stage.stageHeight * 0.65;
- private var stats:TextField = new TextField();
- public function Firework()
- {
- addChild(new Bitmap(displayBuffer));
- stats.x = 5;
- stats.y = 5;
- stats.autoSize = TextFieldAutoSize.LEFT;
- stats.textColor = 0xFFFFFF;
- addChild(stats);
- var shape:Shape = new Shape();
- var g:Graphics = shape.graphics;
- // 火花のプリレンダリング
- var bitmapData:BitmapData = new BitmapData(1, 1, true, SPARK_COLOR);
- sparkBitmapDatas.push(bitmapData);
- sparkBitmapDataRectangles.push(bitmapData.rect);
- for (var diameter:int = 1; diameter <= 32; diameter++) {
- bitmapData = new BitmapData(diameter, diameter, true, 0);
- g.clear();
- g.beginFill(SPARK_COLOR);
- var radius:Number = diameter / 2;
- g.drawCircle(radius, radius, radius);
- g.endFill();
- bitmapData.draw(shape);
- sparkBitmapDatas.push(bitmapData);
- sparkBitmapDataRectangles.push(bitmapData.rect);
- // bitmapData.rectはアクセサで重いのでキャッシュしておく。これにより30%ほど高速化
- }
- // 照り返しのプリレンダリング
- reflectionBitmapData = new BitmapData(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2, true, 0);
- g.clear();
- var matrix:Matrix = new Matrix();
- matrix.createGradientBox(REFLECTION_RADIUS * 2, REFLECTION_RADIUS * 2, 0, 0, 0);
- g.beginGradientFill(GradientType.RADIAL, [ REFLECTION_COLOR, REFLECTION_COLOR ], [ 1, 0 ], [ 0, 255 ], matrix);
- g.drawCircle(REFLECTION_RADIUS, REFLECTION_RADIUS, REFLECTION_RADIUS);
- g.endFill();
- reflectionBitmapData.draw(shape);
- createFireworkModel();
- addEventListener(Event.ENTER_FRAME, enterFrameHandler);
- // stage.addEventListener(MouseEvent.CLICK, function (e:Event):void {
- // emitSpark();
- // });
- }
- private function enterFrameHandler(e:Event):void
- {
- displayBuffer.fillRect(displayBuffer.rect, 0);
- setupProjectionMatrix();
- var startTime:uint = getTimer();
- renderFloor();
- var floorRenderingTime:uint = getTimer() - startTime;
- startTime = getTimer();
- for (var i:int = 0; i < NUMBER_OF_SPLIT_FRAME; i++) {
- const FACTOR:Number = 0.06;
- viewRotationY += (getTimer() * 0.01 + (-(CENTER_X - mouseX) * 0.4) - viewRotationY) * FACTOR;
- viewRotationX += ((27 + (CENTER_Y - mouseY) * 0.15) - viewRotationX) * FACTOR;
- setupProjectionMatrix();
- for (var j:int = 0; j < EMIT_SPARK_NUMBER; j++) {
- emitSpark();
- }
- updateSparks();
- renderSparks();
- }
- var sparksRenderingTime:uint = getTimer() - startTime;
- stats.text =
- "Number of Sparks : " + sparkNumber + "\n" +
- "Floor Rendering Time : " + floorRenderingTime + " ms\n" +
- "Sparks Rendering Time : " + sparksRenderingTime + " ms \n";
- }
- private function setupProjectionMatrix():void
- {
- perspective.fieldOfView = 60;
- projectionMatrix.identity();
- projectionMatrix.appendRotation(viewRotationY, Vector3D.Y_AXIS);
- projectionMatrix.appendRotation(viewRotationX, Vector3D.X_AXIS);
- projectionMatrix.appendTranslation(0, 0, perspective.focalLength);
- projectionMatrix.append(perspective.toMatrix3D());
- correctMatrix3DMultiplyBug(projectionMatrix);
- }
- private function correctMatrix3DMultiplyBug(matrix:Matrix3D):void
- {
- // see http://bugs.adobe.com/jira/browse/FP-670
- var m1:Matrix3D = new Matrix3D(Vector.<Number>([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 ]));
- var m2:Matrix3D = new Matrix3D(Vector.<Number>([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ]));
- m1.append(m2);
- if (m1.rawData[15] == 20) {
- // バグ持ち!
- var rawData:Vector.<Number> = matrix.rawData;
- rawData[15] /= 20;
- matrix.rawData = rawData;
- }
- }
- private function createSpark(x:Number, y:Number, z:Number, vx:Number, vy:Number, vz:Number, diameter:Number):void
- {
- position.push(x, y, z);
- velocity.push(vx, vy, vz);
- diameters.push(diameter);
- sparkNumber++;
- }
- private function emitSpark():void
- {
- var azimuth:Number = Math.random() * 2 * Math.PI;
- var vy:Number = -(Math.random() * 0.06 + 0.94);
- var vx:Number = Math.sqrt(1 - vy * vy) * Math.cos(azimuth);
- var vz:Number = Math.sqrt(1 - vy * vy) * Math.sin(azimuth);
- var speed:Number = Math.random() * 2.3 + 0.7;
- vx *= speed;
- vy *= speed;
- vz *= speed;
- var diameter:Number = 3 + Math.random() * 3;
- createSpark(0, -FIREWORK_HEIGHT, 0, vx, vy, vz, diameter);
- }
- private function updateSparks():void
- {
- for (var i:int = 0; i < sparkNumber; ) {
- var xIndex:int = i * 3;
- var yIndex:int = xIndex + 1;
- var zIndex:int = xIndex + 2;
- velocity[yIndex] += GRAVITY;
- velocity[xIndex] *= AIR_RESISTANCE;
- velocity[yIndex] *= AIR_RESISTANCE;
- velocity[zIndex] *= AIR_RESISTANCE;
- if (position[yIndex] + velocity[yIndex] > 0) {
- velocity[yIndex] = -velocity[yIndex] * 0.2;
- position[xIndex] += velocity[xIndex];
- position[yIndex] += velocity[yIndex];
- position[zIndex] += velocity[zIndex];
- // 小さい火花に分割
- const DIAMETER_MIN:Number = 2;
- if (diameters[i] > DIAMETER_MIN) {
- var diameterLimit:Number = diameters[i];
- while (1) {
- var diameter:Number = Math.random() * (4 - DIAMETER_MIN) + DIAMETER_MIN;
- diameterLimit -= diameter;
- if (diameterLimit < 0) {
- break;
- }
- var azimuth:Number = Math.random() * 2 * Math.PI;
- var r:Number = Math.random() * 2;
- createSpark(position[xIndex], position[yIndex], position[zIndex],
- (velocity[xIndex] + Math.cos(azimuth) * r) * 0.5,
- velocity[yIndex],
- (velocity[zIndex] + Math.sin(azimuth) * r) * 0.5,
- diameter);
- }
- }
- // spliceは重い!
- // position.splice(xIndex, 3);
- // velocity.splice(xIndex, 3);
- // diameters.splice(i, 1);
- position[xIndex] = position[sparkNumber * 3 - 3];
- position[yIndex] = position[sparkNumber * 3 - 2];
- position[zIndex] = position[sparkNumber * 3 - 1];
- velocity[xIndex] = velocity[sparkNumber * 3 - 3];
- velocity[yIndex] = velocity[sparkNumber * 3 - 2];
- velocity[zIndex] = velocity[sparkNumber * 3 - 1];
- diameters[i] = diameters[sparkNumber - 1];
- position.pop();
- position.pop();
- position.pop();
- velocity.pop();
- velocity.pop();
- velocity.pop();
- diameters.pop();
- sparkNumber--;
- continue;
- }
- position[xIndex] += velocity[xIndex];
- position[yIndex] += velocity[yIndex];
- position[zIndex] += velocity[zIndex];
- i++;
- }
- }
- private function renderSparks():void
- {
- splitBuffer.fillRect(splitBuffer.rect, 0x000000);
- Utils3D.projectVectors(projectionMatrix, position, projectedPosition, uvts);
- // ループ外に追い出したら30%以上高速化
- var p:Point = new Point();
- var focalLength:Number = perspective.focalLength;
- for (var i:int = 0; i < sparkNumber; i++) {
- // パーティクルの大きさ = 1/z * focalLength * pixel
- var diameter:int = uvts[i * 3 + 2] * focalLength * diameters[i] + 0.5;
- // (i * 2) => (i << 1)で10%ほど高速化
- p.x = CENTER_X + projectedPosition[(i << 1) ] - diameter / 2;
- p.y = CENTER_Y + projectedPosition[(i << 1) + 1] - diameter / 2;
- splitBuffer.copyPixels(sparkBitmapDatas[diameter], sparkBitmapDataRectangles[diameter], p);
- }
- displayBuffer.draw(splitBuffer, null, null, BlendMode.ADD);
- }
- private const FLOOR_SIZE:Number = 300;
- private const FLOOR_HALFSIZE:Number = FLOOR_SIZE / 2;
- private const FLOOR_VERTICES:Vector.<Number> = Vector.<Number>([
- FLOOR_HALFSIZE, 0, FLOOR_HALFSIZE,
- -FLOOR_HALFSIZE, 0, FLOOR_HALFSIZE,
- -FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE,
- FLOOR_HALFSIZE, 0, -FLOOR_HALFSIZE,
- FLOOR_HALFSIZE, 0, 0,
- -FLOOR_HALFSIZE, 0, 0,
- 0, 0, FLOOR_HALFSIZE,
- 0, 0, -FLOOR_HALFSIZE,
- ]);
- private const FLOOR_VERTEX_NUMBER:int = FLOOR_VERTICES.length / 3;
- private var floorProjectedVertices:Vector.<Number> = new Vector.<Number>();
- private var floorIndices:Vector.<int> = Vector.<int>([
- 0, 1, 2, 2, 3, 0
- ]);
- private var floorUvts:Vector.<Number> = Vector.<Number>([
- 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- ]);
- private const TEXTURE_SIZE:int = 150;
- private var floorTexture:BitmapData = new BitmapData(TEXTURE_SIZE, TEXTURE_SIZE, false);
- private const WIREFRAME_COLOR:uint = 0x555566;
- private var sprite:Sprite = new Sprite();
- private function renderFloor():void
- {
- // 照り返しを描画する閾値
- const THRESHOLD_Y:Number = 50;
- var matrix:Matrix = new Matrix();
- var colorTransform:ColorTransform = new ColorTransform();
- floorTexture.fillRect(floorTexture.rect, 0x180C00);
- for (var i:int = 0; i < sparkNumber; i++) {
- var yIndex:int = i * 3 + 1;
- if (position[yIndex] > -THRESHOLD_Y) {
- var xIndex:int = i * 3;
- var zIndex:int = i * 3 + 2;
- matrix.identity();
- var scale:Number = (0.2 - (position[yIndex] / THRESHOLD_Y) * 0.8) * diameters[i];
- matrix.scale(scale, scale);
- matrix.translate(FLOOR_HALFSIZE + position[xIndex] - REFLECTION_RADIUS * scale, FLOOR_HALFSIZE - position[zIndex] - REFLECTION_RADIUS * scale);
- matrix.scale(TEXTURE_SIZE / FLOOR_SIZE, TEXTURE_SIZE / FLOOR_SIZE);
- colorTransform.alphaMultiplier = 1 + position[yIndex] / THRESHOLD_Y;
- floorTexture.draw(reflectionBitmapData, matrix, colorTransform, BlendMode.ADD);
- }
- }
- Utils3D.projectVectors(projectionMatrix, FLOOR_VERTICES, floorProjectedVertices, floorUvts);
- for (i = 0; i < FLOOR_VERTEX_NUMBER; i++) {
- floorProjectedVertices[(i << 1) ] += CENTER_X;
- floorProjectedVertices[(i << 1) + 1] += CENTER_Y;
- }
- Utils3D.projectVectors(projectionMatrix, fireworkVertices, fireworkProjectedVertices, fireworkUvts);
- for (i = 0; i < fireworkProjectedVertices.length / 2; i++) {
- fireworkProjectedVertices[(i << 1) ] += CENTER_X;
- fireworkProjectedVertices[(i << 1) + 1] += CENTER_Y;
- }
- var g:Graphics = sprite.graphics;
- g.clear();
- g.beginBitmapFill(floorTexture);
- g.drawTriangles(floorProjectedVertices, floorIndices, floorUvts);
- g.endFill();
- displayBuffer.draw(sprite);
- g.clear();
- g.lineStyle(1, WIREFRAME_COLOR);
- g.moveTo(floorProjectedVertices[0], floorProjectedVertices[1]);
- g.lineTo(floorProjectedVertices[2], floorProjectedVertices[3]);
- g.lineTo(floorProjectedVertices[4], floorProjectedVertices[5]);
- g.lineTo(floorProjectedVertices[6], floorProjectedVertices[7]);
- g.lineTo(floorProjectedVertices[0], floorProjectedVertices[1]);
- g.moveTo(floorProjectedVertices[8], floorProjectedVertices[9]);
- g.lineTo(floorProjectedVertices[10], floorProjectedVertices[11]);
- g.moveTo(floorProjectedVertices[12], floorProjectedVertices[13]);
- g.lineTo(floorProjectedVertices[14], floorProjectedVertices[15]);
- displayBuffer.draw(sprite, null, null, BlendMode.ADD);
- g.clear();
- g.beginFill(FIREWORK_COLOR);
- g.drawTriangles(fireworkProjectedVertices, fireworkIndices);
- g.endFill();
- displayBuffer.draw(sprite);
- }
- private const FIREWORK_RADIUS:Number = 8;
- private const FIREWORK_HEIGHT:Number = 40;
- private const FIREWORK_COLOR:uint = 0xAACCFF;
- private var fireworkVertices:Vector.<Number> = new Vector.<Number>();
- private var fireworkIndices:Vector.<int> = new Vector.<int>();
- private var fireworkProjectedVertices:Vector.<Number> = new Vector.<Number>();
- private var fireworkUvts:Vector.<Number> = new Vector.<Number>();
- private function createFireworkModel():void
- {
- const SEGMENT:int = 8;
- for (var i:int = 0; i < SEGMENT; i++) {
- var x:Number = Math.cos(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
- var z:Number = Math.sin(2 * Math.PI * i / SEGMENT) * FIREWORK_RADIUS;
- fireworkVertices.push(x, -FIREWORK_HEIGHT, z);
- fireworkVertices.push(x, 0, z);
- var i0:int = (i * 2 ) % (SEGMENT * 2);
- var i1:int = (i * 2 + 1) % (SEGMENT * 2);
- var i2:int = (i * 2 + 2) % (SEGMENT * 2);
- var i3:int = (i * 2 + 3) % (SEGMENT * 2);
- fireworkIndices.push(i2, i0, i1);
- fireworkIndices.push(i1, i3, i2);
- }
- }
- }
- }
notice: 
