forked from: 質問:探索順を波紋のようにしたい
色が変更される順番を、クリック箇所を中心に波紋が広がるようにしたいのですが、
どのようにしたらよいでしょう?
色変更中のクリック制御などはしていません。テストなので。
/**
* Copyright keno42 ( http://wonderfl.net/user/keno42 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/saM7
*/
// forked from dada_sygnas's 質問:探索順を波紋のようにしたい
/*
色が変更される順番を、クリック箇所を中心に波紋が広がるようにしたいのですが、
どのようにしたらよいでしょう?
色変更中のクリック制御などはしていません。テストなので。
*/
package{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.*;
import caurina.transitions.Tweener;
import caurina.transitions.properties.ColorShortcuts;
[SWF(backgroundColor="#FFFFFF", frameRate=25)]
public class Hirogari extends MovieClip{
public static const W:int = 20;
public static const H:int = 20;
public static const SIZE:int = 15;
protected var $delay:Number;
protected var $blockList:Array; // ブロック管理
protected var $endList:Array; // チェック済みブロック
protected var $hitList:Array; // 同じ色だったブロックのリスト
/**************************
* コンストラクタ
*/
public function Hirogari(){
super();
ColorShortcuts.init();
$blockList = [];
// ブロックの作成
for( var y:int=0; y<H; y++ ){
$blockList[y] = [];
for( var x:int=0; x<W; x++ ){
var block:Block = new Block();
block.init( x, y );
block.addEventListener( MouseEvent.CLICK, ___onClick );
$blockList[y][x] = block;
addChild( block );
}
}
}
/**************************
* クリックされた
*/
protected function ___onClick( e:MouseEvent ):void{
var clickX:int = e.target._posX;
var clickY:int = e.target._posY;
var color:Number = e.target._color; // クリックしたブロックの色
$endList = []; // チェック完了したものを入れる
$hitList = []; // 同じ色のブロックを入れる
$delay = 0;
// 周囲をチェック
___checkAround( [{x:clickX, y:clickY}], color, 0 );
// 2つ以上連続している場合のみ処理
if( $hitList.length >= 2 ){
___changeColor();
}
}
/**************************
* 周囲をチェック
*/
protected function ___checkAround( xyObjs:Array, color:Number, d:int ):void{
var nextObjs:Array = []; // 次の距離のブロックのリスト
var count:int = xyObjs.length; // 等距離ブロックのリスト
d++; // 距離
for( var i:int = 0; i < count; i++){
var x:int = xyObjs[i].x;
var y:int = xyObjs[i].y;
// ダブリチェックの内容に一度処理したものは格納しておく
// 位置を数値に変換して保存
var posId:int = (y*W) + x;
$endList[posId] = true;
$hitList.push( {x:x, y:y, d:d} );
// 未チェックブロックで、同じ色だけチェック対象にする
// 左
if( x>0 && $endList[posId-1] != true ){
if( color == $blockList[y][x-1]._color ){
$endList[posId-1] = true;
nextObjs.push({x:x-1, y:y});
}
}
// 右
if( x<W-1 && $endList[posId+1] != true ){
if( color == $blockList[y][x+1]._color ){
$endList[posId+1] = true;
nextObjs.push({x:x+1, y:y});
}
}
// 上
if( y>0 && $endList[posId-W] != true ){
if( color == $blockList[y-1][x]._color ){
$endList[posId-W] = true;
nextObjs.push({x:x, y:y-1});
}
}
// 下
if( y<H-1 && $endList[posId+W] != true ){
if( color == $blockList[y+1][x]._color ){
$endList[posId+W] = true;
nextObjs.push({x:x, y:y+1});
}
}
}
if( nextObjs.length ) ___checkAround( nextObjs, color, d );
}
/**************************
* 連続したブロックの色を変更
*/
protected function ___changeColor():void{
var x:int, y:int;
var block:Block;
// 該当ブロックを対象に色を変更
for( var i:int=0; i<$hitList.length; i++ ){
x = $hitList[i].x;
y = $hitList[i].y;
block = $blockList[y][x];
// 距離dに応じてdelay
Tweener.addTween( block, {_brightness:block.brightness, time:0.5, delay:$hitList[i].d*0.1} );
}
}
}
}
import flash.display.Sprite;
/**************************
* ブロックのクラス
*/
class Block extends Sprite{
public static const COLOR:Array = [ 0x33ccff, 0xffcc33 ];
public var _posX:int; // 配列上の位置
public var _posY:int;
public var _color:Number;
protected var $brightness:Number; // 明るさ
/********************
* 明るさの取得と変更
*/
public function get brightness():Number{
$brightness += 0.5;
return $brightness;
}
/********************
* 初期化
*/
public function init( myX:int, myY:int ):void{
$brightness = 0;
_color = COLOR[ Math.floor(Math.random()*COLOR.length)];
this.graphics.lineStyle( 1, 0x999999 );
this.graphics.beginFill( _color );
this.graphics.drawRect( 0, 0, Hirogari.SIZE, Hirogari.SIZE );
this.graphics.endFill();
this.x = myX * Hirogari.SIZE;
this.y = myY * Hirogari.SIZE;
this._posX = myX;
this._posY = myY;
this.useHandCursor = true;
this.buttonMode = true;
}
}