ビット論理演算子によるパターン描画(1)
/**
* Copyright Aquioux ( http://wonderfl.net/user/Aquioux )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/3KxH
*/
package {
//import aquioux.display.colorUtil.CycleRGB;
import com.bit101.components.PushButton;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
[SWF(width = "465", height = "465", frameRate = "30", backgroundColor = "#000000")]
/**
* ビット論理演算子によるパターン描画(1)
* @see http://aquioux.net/blog/?p=1943
* @author Aquioux(Yoshida, Akio)
*/
public class Main1 extends Sprite {
// ステージサイズ
private const SW:int = stage.stageWidth;
private const SH:int = stage.stageHeight;
// 表示 BitmapData
private var bmd_:BitmapData;
// BitmapData.setVector 用
private var colorData_:Vector.<uint>;
// colorData_ の基
private var degreeData_:Vector.<uint>;
// 演算関数
private var func_:Function;
// カラーマップ
private var colors_:Vector.<uint>
private var colors1_:Vector.<uint>;
private var colors2_:Vector.<uint>;
// カラー階調数
private const DEGREE:int = 0xFF;
// ボタン
private var calcButton1_:PushButton;
private var calcButton2_:PushButton;
private var calcButton3_:PushButton;
private var colorButton1_:PushButton;
private var colorButton2_:PushButton;
private var prevCalcButton_:PushButton;
private var prevColorButton_:PushButton;
public function Main1():void {
// カラーマップ
colors_ = new Vector.<uint>(DEGREE, true);
// カラーパターン1
colors1_ = new Vector.<uint>(DEGREE, true);
for (var i:int = 0; i < DEGREE; i++) colors1_[i] = i << 16 | i << 8 | i;
// カラーパターン2
colors2_ = new Vector.<uint>(DEGREE, true);
var step:Number = 315 / DEGREE;
for (i = 0; i < DEGREE; i++) colors2_[i] = CycleRGB.getColor(i * step);
// data_ 生成
degreeData_ = new Vector.<uint>(SW * SH, true);
colorData_ = new Vector.<uint>(SW * SH, true);
// 表示 BitmapData 生成
bmd_ = new BitmapData(SW, SH, false);
addChild(new Bitmap(bmd_));
// ボタン
var buttonWidth:int = 50;
var buttonHeight:int = 20;
calcButton1_ = new PushButton(this, buttonWidth * 0, buttonHeight * 0, "x | y", calcButtonHandler1);
calcButton2_ = new PushButton(this, buttonWidth * 1, buttonHeight * 0, "x & y", calcButtonHandler2);
calcButton3_ = new PushButton(this, buttonWidth * 2, buttonHeight * 0, "x ^ y", calcButtonHandler3);
colorButton1_ = new PushButton(this, buttonWidth * 0, buttonHeight * 1, "gray", colorButtonHandler1);
colorButton2_ = new PushButton(this, buttonWidth * 1, buttonHeight * 1, "color", colorButtonHandler2);
calcButton1_.width = buttonWidth;
calcButton2_.width = buttonWidth;
calcButton3_.width = buttonWidth;
colorButton1_.width = buttonWidth;
colorButton2_.width = buttonWidth;
calcButton1_.height = buttonHeight;
calcButton2_.height = buttonHeight;
calcButton3_.height = buttonHeight;
colorButton1_.height = buttonHeight;
colorButton2_.height = buttonHeight;
// 初期表示(演算)
func_ = calculateOR;
calcButton1_.enabled = false;
prevCalcButton_ = calcButton1_;
calcurate();
// 初期表示(色)
colors_ = colors1_;
colorButton1_.enabled = false;
prevColorButton_ = colorButton1_;
draw();
}
// ボタンハンドラ
private function calcButtonHandler1(e:Event):void {
changeCalcButton(calcButton1_);
func_ = calculateOR;
calcurate();
draw();
}
private function calcButtonHandler2(e:Event):void {
changeCalcButton(calcButton2_);
func_ = calculateAND;
calcurate();
draw();
}
private function calcButtonHandler3(e:Event):void {
changeCalcButton(calcButton3_);
func_ = calculateXOR;
calcurate();
draw();
}
private function colorButtonHandler1(e:Event):void {
changeColorButton(colorButton1_);
colors_ = colors1_;
draw();
}
private function colorButtonHandler2(e:Event):void {
changeColorButton(colorButton2_);
colors_ = colors2_;
draw();
}
// ボタン切り替え
private function changeCalcButton(button:PushButton):void {
button.enabled = false;
prevCalcButton_.enabled = true;
prevCalcButton_ = button;
}
private function changeColorButton(button:PushButton):void {
button.enabled = false;
prevColorButton_.enabled = true;
prevColorButton_ = button;
}
// ビット論理演算実行
private function calcurate():void {
var idx:int = 0;
// ステージ走査
for (var y:int = 0; y < SH; y++) {
for (var x:int = 0; x < SW; x++) {
// ビット論理演算
var r:int = func_(x, y);
// DEGREE による剰余値をカラーインデックスに割り当て
r %= DEGREE;
// 結果格納
degreeData_[idx++] = r;
}
}
}
// ビット論理演算
private function calculateOR(x:int, y:int):int {
return x | y;
}
private function calculateAND(x:int, y:int):int {
return x & y;
}
private function calculateXOR(x:int, y:int):int {
return x ^ y;
}
// 表示
private function draw():void {
var len:int = degreeData_.length;
for (var i:int = 0; i < len; i++) {
var r:int = degreeData_[i];
colorData_[i] = colors_[r];
}
// 描画
bmd_.setVector(bmd_.rect, colorData_);
}
}
}
//package aquioux.display.colorUtil {
/**
* コサインカーブで色相環的な RGB を計算
* @author Aquioux(YOSHIDA, Akio)
*/
/*public*/ class CycleRGB {
/**
* 32bit カラーのためのアルファ値(0~255)
*/
static public function get alpha():uint { return _alpha; }
static public function set alpha(value:uint):void {
_alpha = (value > 0xFF) ? 0xFF : value;
}
private static var _alpha:uint = 0xFF;
private static const PI:Number = Math.PI; // 円周率
private static const DEGREE120:Number = PI * 2 / 3; // 120度(弧度法形式)
/**
* 角度に応じた RGB を得る
* @param angle HSV のように角度(度数法)を指定
* @return 色(0xNNNNNN)
*/
public static function getColor(angle:Number):uint {
var radian:Number = angle * PI / 180;
var r:uint = (Math.cos(radian) + 1) * 0xFF >> 1;
var g:uint = (Math.cos(radian + DEGREE120) + 1) * 0xFF >> 1;
var b:uint = (Math.cos(radian - DEGREE120) + 1) * 0xFF >> 1;
return r << 16 | g << 8 | b;
}
/**
* 角度に応じた RGB を得る(32bit カラー)
* @param angle HSV のように角度(度数法)を指定
* @return 色(0xNNNNNNNN)
*/
public static function getColor32(angle:Number):uint {
return _alpha << 24 | getColor(angle);
}
}
//}