Tetris、操作系変更、落下時の加速に対応、レベルアップ条件変更
1. 移動を矢印キーに変更
2. 回転をZ,Xキーに変更
3. いきなり落下ではなく、加速するように
4. スピードアップは10ライン消すごとに変更
5. 50ライン消すとレベル0に戻ります。enjoy!!
/**
* Copyright ongaeshi ( http://wonderfl.net/user/ongaeshi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/zFxf
*/
// forked from flashrod's Tetris
//
// 1. 移動を矢印キーに変更
// 2. 回転をZ,Xキーに変更
// 3. いきなり落下ではなく、加速するように
// 4. スピードアップは10ライン消すごとに変更
// 5. 50ライン消すとレベル0に戻ります。enjoy!!
package {
import flash.display.Sprite;
import flash.text.TextField;
import flash.events.Event;
import flash.events.KeyboardEvent;
[SWF(width = "240", height = "352", backgroundColor = "0xf0f0f0", frameRate = "60")]
public class Main extends Sprite {
private const W:int = 10;
private const H:int = 20;
private const UNIT:int = 16; // 一つのブロックサイズ
// カラーテーブル
private const COLOR:Array =[0x000000, 0x00FFFF, 0xFFFF00,
0x22FF22, 0xFF2222, 0x4444FF, 0xFF8844, 0xFF22FF];
// ブロックパターン、インデックスは色を表す、0は抜き
private const PAT:Array =[[[1, 1, 1, 1]], //棒
[[0, 2, 0], [2, 2, 2]], //凸
[[3, 3, 0], [0, 3, 3]], //逆S
[[0, 4, 4], [4, 4, 0]], //S
[[5, 5], [5, 0], [5, 0]], //逆L
[[6, 6], [0, 6], [0, 6]], //L
[[7, 7], [7, 7]]];//四角
// 落下速度
//
private const SPEED:Array = [60, 30, 20, 10, 5];
private const DROP_SPEED:int = 2;
private const LEVEL_UP_LINES:int = 10;
// キーコード
private const VK_LEFT:int = 37; // 懼
private const VK_ROTLEFT:int = 90; // z
private const VK_ROTRIGHT:int = 88; // x
private const VK_RIGHT:int = 39; // 懼
private const VK_DROP:int = 40; // 懼
// 変数一覧
private var field:Array = [];
private var piece:Array;
private var next:Array;
private var text:TextField = new TextField();
private var score_:TextField = new TextField();
private var keytable:Array = [];
private var step:int = 0;
private var px:int;
private var py:int;
private var isDrop_:Boolean = false;
private var speedLevel_:int = 0; //落下速度のレベル
private var deleteLine_:int = 0; //消去したライン数
public function Main() {
// 次のブロック
text.x = W * UNIT;
text.y = 0 * UNIT;
text.text="Next:";
addChild(text);
// スコア
score_.x = W * UNIT;
score_.y = 6 * UNIT;
addChild(score_);
updateScore();
// 操作説明
var t:TextField = new TextField();
t.x = W * UNIT;
t.y = 11 * UNIT;
t.text = "usage: ←,→,↓,Z,X";
addChild(t);
// フィールド(H * W のサイズで0埋め)
field = new Array(H).map(function():*{
return new Array(W).map(function():*{
return 0;
})
});
// 最初に二つ落として、最初のブロックとNEXTブロックを設定する
pick();
pick();
// イベント登録
addEventListener(Event.ENTER_FRAME, onEnterFrame);
setupKeyDownEvent();
}
private function onEnterFrame(e:Event):void {
if (--step < 0) {
if (!isDrop_)
step=SPEED[speedLevel_];
else
step = DROP_SPEED;
if (space(px, py+1, piece)) {
++py;
repaint();
} else {
drop();
pick();
}
}
}
private function setupKeyDownEvent():void {
keytable[VK_LEFT] = function():void {px -= space(px-1, py, piece)};
keytable[VK_ROTLEFT] = function():void {rotate(true)};
keytable[VK_ROTRIGHT] = function():void {rotate(false)};
keytable[VK_RIGHT] = function():void {px += space(px+1, py, piece)};
keytable[VK_DROP] = function():void { if (!isDrop_) {
isDrop_ = true; step = DROP_SPEED; } };
stage.addEventListener(KeyboardEvent.KEY_DOWN, function
(e:KeyboardEvent):void {
if (keytable[e.keyCode]) {
keytable[e.keyCode]();
repaint();
}
});
stage.addEventListener(KeyboardEvent.KEY_UP, function
(e:KeyboardEvent):void {
if (e.keyCode == VK_DROP) {
isDrop_ = false;
}
});
}
// 回転
private function rotate(clock:Boolean):void {
var r:Array = new
Array(piece[0].length).map(function():*{return [];});
for (var j:int = 0; j<piece.length; ++j)
for (var i:int = 0; i < r.length; ++i)
if (clock)
r[i][piece.length-1-j] = piece[j][i];
else
r[r.length-1-i][j] = piece[j][i];
if (space(px, py, r))
piece = r;
}
// 再描画
private function repaint():void {
// 一度画面をクリア
graphics.clear();
// フィールドブロック
for (var j:int = 0; j < H; ++j)
for (var i:int = 0; i < W; ++i) {
var g:int = 0;
// 落下中ピース
if (py <= j && j < (py+piece.length) && px <= i &&
i < (px+piece[0].length))
g = piece[j-py][i-px];
// フィールド配置済みピース
if (g == 0)
g = field[j][i];
// 描画
graphics.beginFill(COLOR[g]);
graphics.drawRect(i*UNIT, j*UNIT, UNIT, UNIT);
}
// ネクストブロック
for (j = 0; j < next.length; ++j)
for (i = 0; i < next[j].length; ++i) {
graphics.beginFill(COLOR[next[j][i]]);
graphics.drawRect((i+W+1)*UNIT, (j+2)*UNIT, UNIT, UNIT);
}
}
// 指定位置にピースが置けるか判定
//
// @param x 検査位置x
// @param y 検査位置y
// @param p 検査するブロック
private function space(x:int, y:int, p:Array):int {
for (var j:int = 0; j < p.length; ++j) {
if (0 > (y+j) || (y+j) >= H)
return 0;
for (var i:int = 0; i < p[j].length; ++i) {
if (0 > (x+i) || (x+i) >= W)
return 0;
if (p[j][i] && field[y+j][x+i])
return 0;
}
}
return 1;
}
// ブロックを下まで落とし、フィールドに吸着、ブロック消去判定
private function drop():void {
// ブロック位置を下まで落とす
for (; space(px, py+1, piece); py++)
;
// フィールドに配置
for (var j:int = 0; j < piece.length; ++j)
for (var i:int = 0; i < piece[j].length; ++i)
if (piece[j][i])
field[py+j][px+i] = piece[j][i];
// ブロック消去
for (j=0; j<H; ++j)
if (field[j].indexOf(0) < 0) {
// 1行消去して
field.splice(j, 1);
// 先頭に一つ挿入
field.unshift([]);
for (i=0; i<W; ++i)
field[0][i] = 0;
// 消去したライン数
deleteLine_++;
}
// スピードアップ検査、一定回数積んだら速度を元に戻す
speedLevel_ = deleteLine_ / LEVEL_UP_LINES;
if (speedLevel_ >= SPEED.length)
speedLevel_ = 0;
// スコア更新
updateScore();
}
// 次のブロックを取得
private function pick():void {
piece = next;
if (piece != null) {
px = (W-piece[0].length)/2;
py = 0;
if (!space(px, py, piece))
text.text="GAME OVER";
}
next = PAT[int(Math.random()*PAT.length)];
}
// スコア更新
private function updateScore():void {
score_.text = "";
score_.appendText("Lines : " + deleteLine_.toString() + "\n");
score_.appendText("\n");
score_.appendText("Level : " + speedLevel_.toString());
}
}
}