9 - 周りのブロックを削除
forked from 8 - ブロックに色情報を持たせる (diff: 31)
(問題点:周りの同じ色が消えない。) * 解決 * deleteBlockという削除用メソッドを用意し、再帰的にブロックを消せるようにした。 * なので、onMouseDown()に書いていた自分自身のブロックを消す処理を削除。 * クリックされたブロックと周りのブロックを消す処理はdeleteBlockに任せることにした。 * * 問題点:消したときに隙間が空かないようにブロックを落とさなければならない。
ActionScript3 source code
/**
* Copyright samegame ( http://wonderfl.net/user/samegame )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/r9u5
*/
/**
* (問題点:周りの同じ色が消えない。)
* 解決
* deleteBlockという削除用メソッドを用意し、再帰的にブロックを消せるようにした。
* なので、onMouseDown()に書いていた自分自身のブロックを消す処理を削除。
* クリックされたブロックと周りのブロックを消す処理はdeleteBlockに任せることにした。
*
* 問題点:消したときに隙間が空かないようにブロックを落とさなければならない。
*/
package
{
import flash.display.Sprite;
[SWF(backgroundColor = "0x0")]
public class Main extends Sprite
{
public function Main()
{
var panel:Panel = new Panel();
addChild(panel);
}
}
}
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.filters.BevelFilter;
import flash.geom.Point;
class Panel extends Sprite // ブロックはパネルに貼る
{
public static const WIDTH:int = 10; // ブロックの数 - 横
public static const HEIGHT:int = 10; // ブロックの数 - 縦
private var blocks:Array; // ブロックが入っている配列(二次元配列)
public function Panel()
{
createBlocks();
}
// 二次元配列を作る。その配列にブロックを代入。
private function createBlocks():void
{
blocks = new Array(WIDTH);
for (var y:int = 0; y < HEIGHT; y++)
{
blocks[y] = new Array(HEIGHT);
for (var x:int = 0; x < WIDTH; x++)
{
var block:Block = new Block();
block.x = x * Block.WIDTH;
block.y = y * Block.HEIGHT;
addChild(block);
blocks[y][x] = block;
}
}
}
// 二次元配列から引数のブロック位置を検索。
// 見つかったらPoint(x, y)で返却。
// 見つからなかったらnullを返す
public function searchBlock(block:Block):Point
{
for (var y:int = 0; y < HEIGHT; y++)
{
for (var x:int = 0; x < WIDTH; x++)
{
if (blocks[y][x] == block)
{
return new Point(x, y); // ブロックが見つかったので、Pointで返却。
}
}
}
return null; // 見つからなかったのでnullを返す。
}
// ブロックを消す処理
// block[ty][tx].colorが引数で渡されたcolorと同じなら削除
// 上下左右のブロックを調べる
public function deleteBlock(tx:int, ty:int, color:int):void
{
if (tx < 0 || WIDTH <= tx ||
ty < 0 || HEIGHT <= ty) return; // 配列外ならリターン
if (blocks[ty][tx] == null) return; // nullだったらリターン
if (blocks[ty][tx].color != color) return; // クリックしたブロックの色と違っていたらリターン
// 条件は満たしたのでブロックを消す
removeChild(blocks[ty][tx]);
blocks[ty][tx] = null;
// 周りの色を調べる
deleteBlock(tx - 1, ty, color); // 左へ
deleteBlock(tx + 1, ty, color); // 右へ
deleteBlock(tx, ty - 1, color); // 上へ
deleteBlock(tx, ty + 1, color); // 下へ
}
}
class Block extends Sprite
{
public static const WIDTH:int = 30; // ブロックの横幅
public static const HEIGHT:int = 30; // ブロックの縦幅
public static const CW:int = 2; // 補正幅 - ブロック同士がくっつかないように
public static const CH:int = 2; // 補正縦
public static const RW:int = 15; // drawRoundRect()のellipseWidth
public static const RH:int = 15; // drawRoundRect()のellipseHeight
public var color:int; // 自分自身の色。といってもColorクラスのCOLORS配列indexをいれる。ブロック識別用。
public function Block()
{
this.color = Math.random() * Color.COLORS.length; // colorは色番号を保持しておく。
graphics.beginFill(Color.COLORS[this.color]); // ランダムで色を選ぶ
graphics.drawRoundRect(CW, CH, WIDTH - CW, HEIGHT - CH, RW, RH);
graphics.endFill();
this.filters = [new BevelFilter(4, 45, 0xFFFFFF, 1, 0x0, 1, 20, 20, 1, 3, "inner")]; // ベベルフィルターでブロックに質感を持たせる
addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); // ブロックをクリックしたらonMouseDown()を呼ぶ
}
private function onMouseDown(event:MouseEvent):void
{
var panel:Panel = this.parent as Panel; // ブロックはパネルに貼り付けるので、ブロックの親がパネルになる。this.parentで取得できる。
var point:Point = panel.searchBlock(this); // ブロックの位置を検索
if (point)
{
// 自分自身と周りのブロックを消す処理。
// removeChild()と二次元配列から削除。
// 上のparent.removeChild()を消して、panelに消す処理をまかせることにした。
panel.deleteBlock(point.x, point.y, this.color) // 自分自身の位置から削除スタート。
}
}
}
// ブロックの色を保持している
class Color
{
public static const COLORS:Array = [0xED1A3D, 0x00B16B, 0x007DC5];
}
