ぷよ雪
ぷよ雪
でっちあげプロトタイプ@November 8, 2009
今後やりたかったこと:
・ちゃんとテストする
・連鎖だとわかるように一連鎖ずつ消す
・落下・連鎖を滑らかに描画する
・ASの配列の扱い方を調べて書き直す
・ASのイベントと時間の扱い方を調べて書き直す
・ASのコーディング規約を調べて書き直す
/**
* Copyright naraba ( http://wonderfl.net/user/naraba )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/xuej
*/
// ぷよ雪
// でっちあげプロトタイプ@November 8, 2009
// 今後やりたかったこと:
// ・ちゃんとテストする
// ・連鎖だとわかるように一連鎖ずつ消す
// ・落下・連鎖を滑らかに描画する
// ・ASの配列の扱い方を調べて書き直す
// ・ASのイベントと時間の扱い方を調べて書き直す
// ・ASのコーディング規約を調べて書き直す
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;
[SWF(width="400", height="450", frameRate="30", backgroundColor="0x4444FF")]
public class PuyoSnow extends Sprite
{
private const CELL_WIDTH:int = 5;
private const CELL_HEIGHT:int = 5;
private const SCENE_WIDTH:int = 80;
private const SCENE_HEIGHT:int = 90;
private const BLANK:int = -1;
private const FLOOR:int = -2;
private const MARKING:int = -3;
private const COLORS:Array = [0xFFFFFF, 0xDDDDFF, 0xBBBBFF, 0x9999FF];
private var scene:Array = [];
private var fallingPairs:Array = [];
private var topLevelAt:Array = [];
private var groundLevelAt:Array = [];
private var fallTimer:Timer = new Timer(10);
public function PuyoSnow()
{
Wonderfl.capture_delay(30);
scene = new Array(SCENE_HEIGHT+1).map(function():* {
return new Array(SCENE_WIDTH).map(function():* {
return null;
})
});
for (var i:int = 0; i < SCENE_WIDTH; i++) {
for (var j:int = 0; j < SCENE_HEIGHT; j++) {
scene[i][j] = BLANK;
}
scene[i][SCENE_HEIGHT] = FLOOR;
}
topLevelAt = new Array(SCENE_WIDTH).map(function():* {
return SCENE_HEIGHT;
});
groundLevelAt = new Array(SCENE_WIDTH).map(function():* {
return SCENE_HEIGHT;
});
stage.addEventListener(Event.ENTER_FRAME, function(e:Event):void {
draw();
});
fallTimer.addEventListener(TimerEvent.TIMER, fallPairs);
fallTimer.start();
}
private function makePair():void
{
fallingPairs.push(new Pair(SCENE_WIDTH, COLORS.length));
}
private function fallPairs(e:TimerEvent):void
{
if (Math.random() < .4) { makePair(); }
for (var i:int = 0; i < fallingPairs.length; i++) {
var pair:Pair = fallingPairs[i];
var p1x:int = pair.p1.x;
var p1y:int = pair.p1.y;
var p2x:int = pair.p2.x;
var p2y:int = pair.p2.y;
if (scene[p1x][p1y+1] != BLANK || scene[p2x][p2y+1] != BLANK) {
scene[p1x][p1y] = pair.p1.color;
scene[p2x][p2y] = pair.p2.color;
topLevelAt[p2x] = p2y;
topLevelAt[p1x] = p1y;
if (topLevelAt[p2x] <= 0 || topLevelAt[p1x] <= 0) {
// どこかが上まで積もったら何も言わずにただ止まる
fallTimer.stop();
}
fallingPairs.splice(i, 1);
i -= 1; // bug fix @ November 12, 2009
} else {
pair.fall();
}
}
do { // 連鎖があってもノータイムで全部消す
ground();
} while (vanish());
}
private function ground():void
{
for (var i:int = 0; i < SCENE_WIDTH; i++) {
for (var j:int = SCENE_HEIGHT; j >= topLevelAt[i]; j--) {
if (scene[i][j] != BLANK) {
groundLevelAt[i] = j;
continue;
}
var k:int = j - 1;
while (scene[i][k] == BLANK && k >= topLevelAt[i]) { k--; }
if (scene[i][k] != BLANK) {
scene[i][j] = scene[i][k];
scene[i][k] = BLANK;
groundLevelAt[i] = j;
} else {
topLevelAt[i] = groundLevelAt[i];
break;
}
}
}
}
private function vanish():Boolean
{
var didVanish:Boolean = false;
for (var i:int = 0; i < SCENE_WIDTH; i++) {
for (var j:int = SCENE_HEIGHT-1; j >= groundLevelAt[i]; j--) {
var color:int = scene[i][j];
if (color < 0) { continue; }
var mode:Boolean = (markChunk(i, j, color) > 3);
unmarkChunk(i, j, color, mode);
didVanish = didVanish || mode;
}
}
return didVanish;
}
private function markChunk(x:int, y:int, col:int):int
{
if (x < 0 || x >= SCENE_WIDTH) { return 0; }
if (scene[x][y] == col) {
scene[x][y] = MARKING;
return 1 + markChunk(x-1, y, col) + markChunk(x+1, y, col) +
markChunk(x, y-1, col) + markChunk(x, y+1, col);
}
return 0;
}
private function unmarkChunk(x:int, y:int, col:int, isVanishMode:Boolean):void
{
if (x < 0 || x >= SCENE_WIDTH) { return; }
if (scene[x][y] == MARKING) {
scene[x][y] = (isVanishMode ? BLANK : col);
unmarkChunk(x-1, y, col, isVanishMode);
unmarkChunk(x+1, y, col, isVanishMode);
unmarkChunk(x, y-1, col, isVanishMode);
unmarkChunk(x, y+1, col, isVanishMode);
}
}
private function draw():void
{
graphics.clear();
graphics.beginFill(0x2222FF);
graphics.drawRect(0, 0, CELL_WIDTH*SCENE_WIDTH, CELL_HEIGHT*SCENE_HEIGHT);
graphics.endFill();
for each (var pair:Pair in fallingPairs) {
drawPuyo(pair.p1.x, pair.p1.y, pair.p1.color);
drawPuyo(pair.p2.x, pair.p2.y, pair.p2.color);
}
for (var i:int = 0; i < SCENE_WIDTH; i++) {
for (var j:int = SCENE_HEIGHT; j >= groundLevelAt[i]; j--) {
var s:int = scene[i][j];
if (s >= 0) { drawPuyo(i, j, s); }
}
}
}
private function drawPuyo(x:int, y:int, col:int):void
{
graphics.beginFill(COLORS[col]);
graphics.drawEllipse(CELL_WIDTH*x, CELL_HEIGHT*y, CELL_WIDTH, CELL_HEIGHT);
graphics.endFill();
}
}
}
class Pair
{
public var p1:Puyo;
public var p2:Puyo;
public function Pair(maxX:int, numColors:int)
{
var x:int = int(Math.random()*(maxX-1));
p1 = new Puyo(x, 0, int(Math.random()*numColors));
if (Math.random() < .5) {
p2 = new Puyo(x+1, 0, int(Math.random()*numColors));
} else {
p2 = new Puyo(x, 1, int(Math.random()*numColors));
}
}
public function fall():void
{
p1.y += 1;
p2.y += 1;
}
}
class Puyo
{
public var x:int;
public var y:int;
public var color:int;
public function Puyo(x:int, y:int, color:int)
{
this.x = x;
this.y = y;
this.color = color;
}
}