暑いから雪を降らしてみる(4) PerlinNoiseで風吹いてるVer
アニメーション用の設定をしておくよ
/**
* Copyright 7kamura ( http://wonderfl.net/user/7kamura )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/zh2j
*/
// forked from 7kamura's 暑いから雪を降らしてみる(3) 文字ありVer
// forked from 7kamura's 暑いから雪を降らしてみる(2) キラキラVer
// forked from 7kamura's 暑いから雪を降らしてみる(1) 普通に落ちるだけVer
package {
import flash.display.Sprite;
import flash.display.*;
import flash.geom.Rectangle;
import flash.events.Event;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;
import flash.filters.BlurFilter;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
// アニメーション用の設定をしておくよ
[SWF(width=465, height=465, backgroundColor=0x0, frameRate=60)]
import flash.geom.Matrix;
import flash.geom.Point;
public class Main extends Sprite {
public static const WIDTH:Number = 465;
public static const HEIGHT:Number = 465;
public static const GRAVITY:Number = 0.02;
private var rect:Rectangle;
private var canvas:BitmapData;
private var textBmd:BitmapData;
private var glowBmd:BitmapData;
private var noiseBmd:BitmapData;
private var particleList:Array;
private var glowMatrix:Matrix;
private var timer:Timer;
public function Main() {
if(stage) init();
}
private function init():void {
// ここにParticleを描画していくよ
canvas = new BitmapData(WIDTH, HEIGHT, false, 0x0);
addChild(new Bitmap(canvas));
// これを上から被せてキラキラ表示するよ
// 1/4の大きさでcanvasをコピーしてから4倍に拡大して被せることでキラキラを演出するよ
// BlendMode.ADDのおかげで、透明のシートを被せたような感じになってるよ
// Bitmapの生成時に、smoothingをtrueにして滑らかに表示しているよ
// 拡大率をglowMatrixに保存しておいて、後でコピーしたcanvasを縮小するときに使うよ
glowBmd = new BitmapData(WIDTH/4, HEIGHT/4, false, 0x0);
var glowBmp:Bitmap = addChild(new Bitmap(glowBmd, PixelSnapping.NEVER, true)) as Bitmap;
glowBmp.blendMode = BlendMode.ADD;
glowBmp.scaleX = glowBmp.scaleY = 4;
glowMatrix = new Matrix(1/4, 0, 0, 1/4);
// Particle達はここに入れておくよ
particleList = new Array;
// Particleで彩られる予定の文字データを用意するよ
createText();
// 風を演出するためのParlinNoiseを作成するよ
createPerlinNoise();
// 毎フレームごとに描画を更新してもらうよ
addEventListener(Event.ENTER_FRAME, update);
// 10秒ごとに風向きを変えるよ
timer = new Timer(10000);
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.start();
// クリックで最初からやり直してもらうよ
stage.addEventListener(MouseEvent.CLICK, reset);
}
private function reset(e:Event):void {
init();
}
private function onTimer(e:Event):void {
createPerlinNoise();
}
private function update(e:Event):void {
// Canvasを一旦クリアするよ
canvas.fillRect(canvas.rect, 0x0);
// Particleを10個つくるよ
var p_num:Number = 10;
while(p_num--) {
createParticle(Math.random()*WIDTH, 0);
}
canvas.lock();
var n:Number = particleList.length;
var d:Number;
while(n--) {
var p:Particle = particleList[n];
p.vy += GRAVITY; // 重力加速度
p.vx *= 0.99; // 空気抵抗
p.vy *= 0.99;
// 文字の上(白い部分)に来ると速度を落とすよ
d = 1 - (textBmd.getPixel(p.x, p.y) / 0xFFFFFF) * 0.3;
p.vx *= d;
p.vy *= d;
// noiseBmdによってランダムに移動するよ
// 赤色成分の値によってx方向の速度を変えているよ
var color:uint = noiseBmd.getPixel(p.x, p.y);
var r:uint = color >> 16 & 0xFF;
p.vx += ((r - 128) / 0xFF) * 0.05;
p.x += p.vx; // 移動
p.y += p.vy;
canvas.setPixel(p.x, p.y, p.c);
// 画面外に出たParticleを抹消するよ
if (p.x > WIDTH || p.x < 0 || p.y > HEIGHT || p.y < 0) {
particleList.splice(n, 1);
}
}
// キラキラを上から被せるよ
glowBmd.draw(canvas, glowMatrix);
canvas.unlock();
}
private function createText():void {
var tfld:TextField = new TextField();
tfld.autoSize = TextFieldAutoSize.LEFT;
tfld.defaultTextFormat = new TextFormat("Verdana", 50, 0xFFFFFF, true);
tfld.text = "Gakuweb";
tfld.x = (canvas.width - tfld.width) / 2;
tfld.y = (canvas.height- tfld.height)/ 2;
// tfldをBitmapDataに変換するよ
textBmd = new BitmapData(WIDTH, HEIGHT, false, 0x0);
textBmd.applyFilter(textBmd, textBmd.rect, new Point(0, 0), new BlurFilter(4,4));
textBmd.draw(tfld, tfld.transform.matrix);
/* For Debug
addChild(tfld);
*/
}
private function createPerlinNoise():void {
noiseBmd = new BitmapData(WIDTH, HEIGHT, false, 0x0);
var randomSeed:uint = Math.floor(Math.random() * 0xFFFF);
noiseBmd.perlinNoise(WIDTH, HEIGHT, 1, randomSeed, false, true, 1);
/* For Debug
addChild(new Bitmap(noiseBmd));
*/
}
private function createParticle(x:Number, y:Number, vx:Number = 0, vy:Number = 0, c:uint = 0xFFFFFF):void {
var p:Particle = new Particle();
p.x = x;
p.y = y;
p.vx = vx;
p.vy = vy;
p.c = c;
particleList.push(p);
}
}
}
class Particle {
public var x:Number;
public var y:Number;
public var vx:Number;
public var vy:Number;
public var c:uint;
public function init():void {
x = 0;
y = 0;
vx = 0;
vy = 0;
c = 0xFFFFFF;
}
}