forked from: QuickBox2Dで万華鏡
kaleidoscope
* 万華鏡(2)
*
* 綺麗にしてみたつもり。
* 具は毎回ランダム。
/**
* Copyright takishiki ( http://wonderfl.net/user/takishiki )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/oa2G
*/
// forked from takishiki's QuickBox2Dで万華鏡
/*
* kaleidoscope
* 万華鏡(2)
*
* 綺麗にしてみたつもり。
* 具は毎回ランダム。
*/
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.MovieClip;
import com.actionsnippet.qbox.*;
import com.actionsnippet.qbox.QuickBox2D;
import Box2D.Common.Math.b2Vec2;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.display.BlendMode;
import flash.display.Graphics;
import flash.filters.GlowFilter;
[SWF(width=465, height=465, frameRate=30, backgroundColor=0xFFFFFF)]
public class Main extends MovieClip
{
// 定数
private const QB2D_SCALE :Number = 1 / 30; // QuickBox2Dのスケール
private const POLY_R :int = 50;
private const NUM :int = 20; // 具の数
private const DEBUG :Boolean = false; // デバッグオフ
private const GRAVITY :int = 20; // 重力
// 変数
private var _sp:Sprite;
private var _bmp:Bitmap;
private var _bmpd:BitmapData;
private var _sim:QuickBox2D;
private var _deg:Number = 0;
private var _bgSp:Sprite;
// constructor
public function Main():void {
stage.frameRate = 60;
// 黒背景
_bgSp = new Sprite();
var g:Graphics = _bgSp.graphics;
g.lineStyle();
g.beginFill(0x000000, 1.0);
g.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
g.endFill();
this.addChild(_bgSp);
_sim = new QuickBox2D(this, { debug:DEBUG } );
_sim.setDefault( { fillColor:0x000000, lineAlpha:0, radius:1.5 } );
//_sim.createStageWalls();
_sim.gravity = new b2Vec2(0, 0); // 重力なし
// 壁を配置
var a:Number = stage.stageWidth / 4 * QB2D_SCALE;
_sim.addBox( { x:a, y:a * 2, width:0.5, height:a * 2, angle:0, density:0, fillColor:0x000000 } );
_sim.addBox( { x:a * 3, y:a * 2, width:0.5, height:a * 2, angle:0, density:0, fillColor:0x000000 } );
_sim.addBox( { x:a * 2, y:a, width:a * 2, height:0.5, angle:0, density:0, fillColor:0x000000 } );
_sim.addBox( { x:a * 2, y:a * 3, width:a * 2, height:0.5, angle:0, density:0, fillColor:0x000000 } );
// 具を配置
var type:int;
var color:uint;
var i:int;
var obj:QuickObject;
for (i = 0; i < NUM; i++) {
type = randRange(0, 1);
color = hsv2rgb(randRange(0, 359), 1, 1);
if (type == 0) {
// 長方形
obj = _sim.addBox( {
x:stage.stageWidth / 2 * QB2D_SCALE, y:stage.stageHeight / 2 * QB2D_SCALE,
width:randRange(1, 15) / 10, height:randRange(1, 15) / 10,
fillColor:randRange(0, 1) * color, fillAlpha:1.0,
lineColor:0, lineAlpha:0
} );
}else {
// 円
obj = _sim.addCircle( {
x:stage.stageWidth / 2 * QB2D_SCALE, y:stage.stageHeight / 2 * QB2D_SCALE,
radius:randRange(1, 6) / 10,
fillColor:randRange(0, 1) * color, fillAlpha:1.0,
lineColor:0, lineAlpha:0
} );
}
// グローフィルター
obj.userData.filters = [new GlowFilter(color, 0.8, 10, 10, 2, 2, true, false), new GlowFilter(color, 0.6, 20, 20, 4, 2, false, false),];
}
_sim.start();
_sim.mouseDrag();
var sp:Sprite = new Sprite();
g = sp.graphics;
g.beginFill(0x000000, 1.0);
g.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
drawPoly(sp, 3, stage.stageWidth / 2, stage.stageHeight / 2, POLY_R, 30);
g.endFill();
this.addChild(sp);
_bmpd = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0x000000);
_bmp = new Bitmap(_bmpd);
_sp = new Sprite();
_sp.addChild(_bmp);
this.addChild(_sp);
this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
// 多角形描画
private function drawPoly(sp:Sprite, num:int, x:int, y:int, r:int, deg:Number):void {
/*
* sp:対象Sprite
* num:頂点の数
* x:中心のx座標
* y:中心のy座標
* r:半径
* deg:回転角度(度)
*/
var g:Graphics = sp.graphics;
var rad:Number;
var i:int;
var step:Number = 360 / num;
// 描画スタート位置に移動
rad = deg2rad(0 + deg);
g.moveTo(x + r * Math.cos(rad), y + r * Math.sin(rad));
for (i = 0; i < num; i++) {
rad = deg2rad((i + 1) * step + deg);
g.lineTo(x + r * Math.cos(rad), y + r * Math.sin(rad));
}
}
// フレーム処理
private function onEnterFrame(event:Event):void {
_deg += 1;
if (_deg >= 360) {
_deg -= 360;
}
var rad:Number = deg2rad(_deg);
_sim.gravity = new b2Vec2(GRAVITY * Math.cos(rad), GRAVITY * Math.sin(rad));
makeImage(_bmpd);
}
// 万華鏡画像作成
private function makeImage(target:BitmapData):void {
_sp.visible = false;
var h:int = POLY_R * 3 / 2;
var r3:Number = Math.sqrt(3);
// ステージ用
var bmpd:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight);
// 元の三角形用
var bmpdTri:BitmapData = new BitmapData(POLY_R * 2, POLY_R * 2, false, 0x000000);
// 一行描画用
var bmpdRow:BitmapData = new BitmapData(target.width, Math.ceil(h), false, 0x000000);
// ステージ描画
bmpd.lock();
bmpd.draw(this);
bmpd.unlock();
var rect:Rectangle = new Rectangle();
rect.x = Math.floor(stage.stageWidth / 2 - POLY_R);
rect.y = Math.floor(stage.stageHeight / 2 - POLY_R);
rect.width = POLY_R * 2;
rect.height = POLY_R * 2;
// 三角形部分を切り取り
bmpdTri.copyPixels(bmpd, rect, new Point());
var matrix:Matrix = new Matrix();
var matrix2:Matrix = new Matrix();
var rad:Number = Math.PI * 2 / 3; // 120°
var num:int;
var i:int;
// 行作成
bmpdRow.lock();
num = Math.ceil(target.width / POLY_R) + 2;
for (i = 0; i < num; i++) {
matrix = new Matrix();
// 中央に平行移動
matrix2 = new Matrix();
matrix2.translate( -POLY_R, -POLY_R);
matrix.concat(matrix2);
if (i % 2 == 0) {
// 偶数
// 回転
matrix2 = new Matrix();
matrix2.rotate(-rad * i);
matrix.concat(matrix2);
}else {
// 奇数
// 反転
matrix2 = new Matrix();
matrix2.scale(1, -1);
matrix.concat(matrix2);
// 回転
matrix2 = new Matrix();
matrix2.rotate(-rad * int(i / 2) + rad);
matrix.concat(matrix2);
// y軸平行移動
matrix2 = new Matrix();
matrix2.translate(0, -POLY_R / 2);
matrix.concat(matrix2);
}
// x軸平行移動
matrix2 = new Matrix();
matrix2.translate(Math.floor(i * POLY_R / 2 * r3), 0);
matrix.concat(matrix2);
// 基準位置まで平行移動
matrix2 = new Matrix();
matrix2.translate(0, POLY_R);
matrix.concat(matrix2);
// 描画
bmpdRow.draw(bmpdTri, matrix, new ColorTransform(), BlendMode.LIGHTEN);
}
bmpdRow.unlock();
// 行のbmpdを反転しながら列方向に描画
target.lock();
// 背景色で塗りつぶし
target.fillRect(target.rect, 0x000000);
num = Math.ceil(target.height / POLY_R);
for (i = 0; i < num; i++) {
matrix = new Matrix();
// 中央に平行移動
matrix2 = new Matrix();
matrix2.translate(0, -Math.round(h / 2));
matrix.concat(matrix2);
if (i % 2 == 1) {
// 奇数
// 反転
matrix2 = new Matrix();
matrix2.scale(1, -1);
matrix.concat(matrix2);
}
// 平行移動
matrix2 = new Matrix();
matrix2.translate(0, Math.floor(h * i));
matrix.concat(matrix2);
// 基準位置まで平行移動
matrix2 = new Matrix();
matrix2.translate(0, Math.round(h / 2));
matrix.concat(matrix2);
// 描画
target.draw(bmpdRow, matrix, new ColorTransform(), BlendMode.LIGHTEN);
}
target.unlock();
bmpdTri.dispose();
bmpdRow.dispose();
_sp.visible = true;
}
// HSV -> RGB(uint)
private function hsv2rgb(h:Number, s:Number, v:Number):uint {
var r:Number = 0;
var g:Number = 0;
var b:Number = 0;
if (s == 0) {
r = g = b = v;
}else {
var hTemp:Number = (h + 360) % 360;
hTemp /= 60;
var i:Number = Math.floor(hTemp); // 整数部
var f:Number = hTemp - i; // 小数部
var p:Number = v * (1.0 - s);
var q:Number = v * (1.0 - (s * f));
var t:Number = v * (1.0 - (s * (1.0 - f)));
switch(i) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
}
}
return rgb2hex(r * 255, g * 255, b * 255);
}
// R, G, B -> hex color value
private function rgb2hex(r:Number = 0, g:Number = 0, b:Number = 0):uint {
r = Math.round(r);
g = Math.round(g);
b = Math.round(b);
return 0xff000000 + r * 0x10000 + g * 0x100 + b;
}
// degree -> radian
private function deg2rad(deg:Number):Number {
deg %= 360;
return deg / 180 * Math.PI;
}
// a-bの乱数生成
private function randRange(min:Number = 0, max:Number = 1):Number {
var randomNum:Number = Math.floor(Math.random() * (max - min + 1)) + min;
return randomNum;
}
}
}