シャボン玉
http://wonderfl.net/code/aaaf48abc914b94ed6cb53bd35256b873a603ae3
に触発されて
/**
* Copyright uwi ( http://wonderfl.net/user/uwi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/jgZP
*/
// http://wonderfl.net/code/aaaf48abc914b94ed6cb53bd35256b873a603ae3
// に触発されて
package {
import flash.display.*;
import flash.text.TextField;
import flash.utils.getTimer;
import flash.filters.DisplacementMapFilter;
import flash.geom.*;
import flash.events.*;
public class RollingBubbles extends Sprite {
private var _tf : TextField;
private var _bubbles : Array;
private const K : uint = 100;
private var _bmdBubbles : Array; // <BitmapData>
public function RollingBubbles() {
_tf = new TextField();
_tf.width = 465;
_tf.height = 465;
// addChild(_tf);
_bmdBubbles = makeBubbleData(100, K);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
_bubbles = [];
}
private var _time : Number = 0;
private function onEnterFrame(e : Event) : void
{
appendBubbles();
moveBubbles();
renderBubbles();
_time++;
}
// シャボン玉を発生
private function appendBubbles() : void
{
if(_time % 10 == 0){
var b : Bubble = new Bubble(
Math.random() * 465,
465,
Math.random() * 0.7 + 0.3,
Math.random() * 200,
Math.random() * 10,
Math.random() * 300 + 100,
-Math.random() * 3 - 2
);
addChild(b);
b.smoothing = true;
// b.pixelSnapping = "never";
_bubbles.push(b);
}
}
// シャボン玉を動かす
private function moveBubbles() : void
{
for(var i : int = _bubbles.length - 1;i >= 0;i--){
var b : Bubble = _bubbles[i];
b.step();
if(b.y < -b.height){
removeChild(b);
removeElement(_bubbles, i);
}
}
}
private static function removeElement(a : Array, ind : uint) : Array
{
if(ind == a.length - 1){
a.pop();
}else{
a[ind] = a.pop();
}
return a;
}
// シャボン玉を描画
private function renderBubbles() : void
{
for each(var b : Bubble in _bubbles){
if(_time % 3 == 0){
b.state = (b.state + 1) % K;
b.bitmapData = _bmdBubbles[b.state];
}
}
}
// シャボン玉データをつくる
private static function makeBubbleData(R : Number, cyc : int) : Array
{
var W : Number = 2 * R;
// red:alpha, green:+x, blue:+y
var base : BitmapData = new BitmapData(W, W, false, 0x008080);
base.lock();
for(var i : uint = 0;i < W;i++){
for(var j : uint = 0;j < W;j++){
var d2 : Number = (i - R) * (i - R) + (j - R) * (j - R);
if(d2 < R * R){
var d : Number = Math.sqrt(d2);
var rr : Number = Math.asin(d/R) / (Math.PI / 2)*R;
var cx : uint = 128 + (i - R) / d * (rr - d) * 4;
var cy : uint = 128 + (j - R) / d * (rr - d) * 4;
var thickness : uint = Math.min(0xff, Math.abs(rr)*1.2 + 0x10);
base.setPixel(i, j, thickness << 16 | cx << 8 | cy);
}
}
}
base.unlock();
var dmf : DisplacementMapFilter = new DisplacementMapFilter(base, new Point(), BitmapDataChannel.GREEN, BitmapDataChannel.BLUE, R, R, "ignore");
var bmds : Array = [];
var src : BitmapData = new BitmapData(W, W, false, 0x000000);
var seed : int = new Date().getTime();
var offsets : Array = [];
var dxs : Array = [];
for(i = 0;i < 3;i++){
offsets.push(new Point());
dxs.push(int(Math.random() * 10 - 5) * int(W / cyc));
}
src.lock();
for(i = 0;i < cyc;i++){
src.perlinNoise(W, W, 3, seed, true, false, 7, false, offsets);
src.colorTransform(src.rect, new ColorTransform(1.8, 1.8, 1.8, 1));
for(j = 0;j < 3;j++){
offsets[j].x += dxs[j];
offsets[j].y += dxs[2 - j];
}
var dst : BitmapData = new BitmapData(W, W, true, 0x000000);
dst.lock();
dst.applyFilter(src, src.rect, new Point(), dmf);
dst.copyChannel(base, base.rect, new Point(), BitmapDataChannel.RED, BitmapDataChannel.ALPHA);
dst.unlock();
bmds.push(dst);
}
src.unlock();
base.dispose();
src.dispose();
return bmds;
}
private function tr(...o : Array) : void
{
_tf.appendText(o + "\n");
}
}
}
import flash.display.Bitmap;
class Bubble extends Bitmap
{
public var xx : Number;
public var xy : Number;
public var w : Number; // 振幅
public var cyc : Number; // 周期
public var t : Number; // 位相
public var vy : Number;
public var state : uint; // 使っているBitmapDataの番号
public function Bubble(xx : Number, xy : Number, scale : Number, state : uint, w : Number, cyc : Number, vy : Number)
{
super();
this.xx = xx;
this.xy = xy;
this.x = xx;
this.y = xy;
this.w = w;
this.cyc = cyc;
this.vy = vy;
this.t = Math.random() * cyc * 2 * Math.PI;
scaleX = scale;
scaleY = scale;
}
public function step() : void
{
t++;
xx += w * Math.cos(t/cyc);
xy += vy;
x = xx;
y = xy;
}
}