パーティクル時計
2次ベジェの式に沿ってパーティクルが移動しながら文字を描いていきます。
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.ColorTransform;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextLineMetrics;
import flash.utils.getTimer;
[SWF(width=465, height=465, backgroundColor=0x000000, frameRate=60)]
public class ParticleClock extends Sprite
{
private var _bitmap:Bitmap;
private var _bitmapData:BitmapData;
private var _colorTransform:ColorTransform;
private var _lastTime:int;
private var _pointsX:Object;
private var _pointsY:Object;
private var _setupTime:uint;
private var _sizes:Object;
private var _tail:Particle;
public function ParticleClock()
{
_pointsX = {};
_pointsY = {};
_sizes = {};
for each (var ch:String in "0123456789:".split(""))
{
var tf:TextField = new TextField();
tf.defaultTextFormat = new TextFormat(null, 100, 0);
tf.text = ch;
var line:TextLineMetrics = tf.getLineMetrics(0);
var w:int = Math.ceil(line.width);
var h:int = Math.ceil(line.height);
var bitmap:BitmapData = new BitmapData(w, h, true, 0);
bitmap.draw(tf);
var index:int = 0;
var v:Vector.<uint> = bitmap.getVector(bitmap.rect);
var pointsX:Vector.<uint> = new Vector.<uint>();
var pointsY:Vector.<uint> = new Vector.<uint>();
_pointsX[ch] = pointsX;
_pointsY[ch] = pointsY;
_sizes[ch] = bitmap.rect;
for (var i:int = 0, len:int = v.length; i < len; i++)
{
if (v[i] === 0xff000000)
{
pointsX[index] = i % w;
pointsY[index] = int(i / w);
++index;
}
}
}
for (var j:int = 0; j < 10000; j++)
{
_tail = new Particle(_tail);
}
_colorTransform = new ColorTransform(0.5, 0.8, 0.8, 0.9);
_bitmapData = new BitmapData(465, 465, false, 0);
_bitmap = new Bitmap(_bitmapData);
addChild(_bitmap);
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
private function enterFrameHandler(e:Event):void
{
var time:uint = getTimer();
if (int(time / 2000) !== _lastTime)
{
_lastTime = int(time / 2000);
setupParticle();
}
var diff:int = getTimer() - _setupTime;
var particle:Particle = _tail;
_bitmapData.lock();
_bitmapData.colorTransform(_bitmapData.rect, _colorTransform);
while (particle !== null)
{
if (particle.stopped)
{
particle = particle.prev;
continue;
}
var t:Number = particle.duration == 0 ? 1 : diff / particle.duration;
if (t >= 1.0)
{
t = 1.0;
particle.stopped;
}
t *= t;
particle.x = particle.sx * (1 - t) * (1 - t) + particle.cx * t * (1 - t) + particle.ex * t * t;
particle.y = particle.sy * (1 - t) * (1 - t) + particle.cy * t * (1 - t) + particle.ey * t * t;
_bitmapData.setPixel(particle.x, particle.y, 0xffffff);
particle = particle.prev;
}
_bitmapData.unlock();
}
private function setupParticle():void
{
var date:String = new Date().toTimeString().substring(0, 8);
var w:int = 0;
var h:int = 0;
var offsets:Array = [];
for (var i:int = 0; i < 8; i++)
{
offsets[i] = w;
var rect:Rectangle = _sizes[date.charAt(i)];
w += rect.width;
h = h < rect.height ? rect.height : h;
}
var particle:Particle = _tail;
var offsetX:int = Math.random() * (465 - w);
var offsetY:int = Math.random() * (465 - h);
while (particle !== null)
{
var chIndex:int = Math.random() * 8;
var ch:String = date.charAt(chIndex);
var pointsX:Vector.<uint> = _pointsX[ch];
var pointsY:Vector.<uint> = _pointsY[ch];
var index:int = Math.random() * pointsX.length;
particle.sx = particle.ex;
particle.sy = particle.ey;
particle.ex = pointsX[index] + offsets[chIndex] + offsetX;
particle.ey = pointsY[index] + offsetY;
particle.cx = Math.random() * 465 * 4 - 465;
particle.cy = Math.random() * 465 * 4 - 465;
var dx:Number = particle.sx - particle.ex;
var dy:Number = particle.sy - particle.ey;
particle.duration = Math.random() * 1000 + 1000;
particle.stopped = false;
particle = particle.prev;
}
_setupTime = getTimer();
}
}
}
class Particle
{
public var cx:Number;
public var cy:Number;
public var duration:int;
public var ex:Number;
public var ey:Number;
public var prev:Particle;
public var stopped:Boolean;
public var sx:Number;
public var sy:Number;
public var x:Number;
public var y:Number;
public function Particle(prev:Particle)
{
this.prev = prev;
duration = 0;
stopped = true;
sx = 0;
sy = 0;
ex = 0;
ey = 0;
cx = 0;
cy = 0;
}
}