/**
* Copyright kihon ( http://wonderfl.net/user/kihon )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/oTo0
*/
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public class Main extends Sprite
{
private var keys:Array = [];
private var status:Status = new Status();
private var map/*Array*/:Array; // テトリス盤面
private var landingCount:int = 10; // 地面(ブロック)に付いてから固定されるまでのフレーム
private var leftKeyPressCount:int = 0;
private var rightKeyPressCount:int = 0;
private const WIDTH:int = 12; // 横幅
private const HEIGHT:int = 21; // 縦幅
private const FALL_SPEED:Number = 0.05; // 落ちるスピード
public function Main()
{
map = [];
for (var y:int = 0; y < HEIGHT; y++)
{
map[y] = new Array();
for (var x:int = 0; x < WIDTH; x++)
{
// 左端/右端/下端は壁なので1を入れ、それ以外のところは0を入れる
if (x == 0 || x == WIDTH - 1 || y == HEIGHT - 1) map[y][x] = 1;
else map[y][x] = 0;
}
}
initalize();
addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
}
// 初期化処理
private function initalize():void
{
status.x = 4;
status.y = 0;
status.block = Block.SHAPE[0];
}
// 毎フレーム行う処理
private function onEnterFrame(event:Event):void
{
status.y += FALL_SPEED;
// 一つ下に移動して衝突する場合は、今のマスから動かさないようにする
if (check(status.x, status.y + 1)) status.y = int(status.y);
if (keys[Keyboard.LEFT] && !check(status.x - 1, Math.ceil(status.y)) && !check(status.x - 1, Math.floor(status.y)))
{
if (leftKeyPressCount == 0 || leftKeyPressCount >= 3)
{
status.x--;
}
leftKeyPressCount++;
}
else leftKeyPressCount = 0; // キーが離されたら、値を0に戻す
if (keys[Keyboard.RIGHT] && !check(status.x + 1, Math.ceil(status.y)) && !check(status.x + 1, Math.floor(status.y)))
{
if (rightKeyPressCount == 0 || rightKeyPressCount >= 3)
{
status.x++;
}
rightKeyPressCount++;
}
else rightKeyPressCount = 0;
if (check(status.x, status.y + 1))
{
if (--landingCount <= 0) endProcess();
}
else landingCount = 10;
draw();
}
// 仮に引数の(x, y)に今落ちているブロックを置いた場合、
// 他のブロックや壁と衝突してしまう場合はtrue, しない場合はfalseが返却される
private function check(tx:int, ty:int):Boolean
{
var block:Array = status.block;
for (var y:int = 0; y < Block.SIZE; y++)
{
for (var x:int = 0; x < Block.SIZE; x++)
{
if (block[y][x] && map[ty + y][tx + x]) return true;
}
}
return false;
}
// ブロックが地面に落ちて、位置が確定した後の処理
private function endProcess():void
{
// ENTER_FRAMEを一度止める
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
lock(); // ブロックを固定
draw(); // 描画
initalize(); // 初期化
landingCount = 10; // 初期化
// 最初の位置にブロックが置けなかったらゲームオーバー。
if (check(status.x, status.y)) gameOver();
else addEventListener(Event.ENTER_FRAME, onEnterFrame); // 再開
}
// 着地したブロックを固定させる
private function lock():void
{
var block:Array = status.block;
for (var y:int = 0; y < Block.SIZE; y++)
{
for (var x:int = 0; x < Block.SIZE; x++)
{
if (block[y][x]) map[status.y + y][status.x + x] = block[y][x];
}
}
}
private function gameOver():void
{
trace("GAME OVER");
}
// ブロックの描画
private function draw():void
{
graphics.clear(); // 初期化
graphics.beginFill(0x0);
graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
graphics.endFill();
for (var y:int = 0; y < HEIGHT; y++)
{
for (var x:int = 0; x < WIDTH; x++)
{
// 注目しているマスに0が入っていない、つまり壁かブロックが入っている場合
if (map[y][x])
{
// 壁だったら
if (x == 0 || x == WIDTH - 1 || y == HEIGHT - 1)
{
graphics.lineStyle(1.0);
graphics.beginFill(0x555555);
}
// ブロックだったら
else
{
graphics.lineStyle(2.0);
graphics.beginFill(Block.COLOR[map[y][x]]);
}
graphics.drawRect(x * Block.WIDTH, y * Block.HEIGHT, Block.WIDTH, Block.HEIGHT);
graphics.endFill();
}
}
}
var block:Array = status.block;
for (y = 0; y < Block.SIZE; y++)
{
for (x = 0; x < Block.SIZE; x++)
{
// 4*4配列の中でブロックの描画があるところだけを表示する
if (block[y][x])
{
graphics.lineStyle(1.5);
graphics.beginFill(Block.COLOR[block[y][x]]);
graphics.drawRect((status.x + x) * Block.WIDTH, (status.y + y) * Block.HEIGHT, Block.WIDTH, Block.HEIGHT);
graphics.endFill();
}
}
}
}
// キーが押されたとき
private function onKeyDown(event:KeyboardEvent):void
{
keys[event.keyCode] = true;
}
// キーが離されたとき
private function onKeyUp(event:KeyboardEvent):void
{
keys[event.keyCode] = false;
}
}
}
class Status
{
public var x:Number; // このx, yの位置からブロックを表示する
public var y:Number;
public var block/*Array*/:Array; // 今持っているブロック
}
class Block
{
public static const SIZE:int = 4; // ブロックの形状を4*4の配列で保持しているので、その4を定数にしている
public static const WIDTH:int = 20; // ブロックの横サイズ
public static const HEIGHT:int = 20; // ブロックの縦サイズ
// 色
public static const COLOR/*int*/:Array = [0x0, 0xFEFBB3, 0x69DEEE, 0x3DC642, 0xF33433, 0x797CFB, 0xF88C2D, 0xFFAAFF];
// 形状
public static const SHAPE/*Array*/:Array =
[
[
[0, 0, 0, 0],
[0, 1, 1, 0],
[0, 1, 1, 0],
[0, 0, 0, 0]
],
[
[0, 2, 0, 0],
[0, 2, 0, 0],
[0, 2, 0, 0],
[0, 2, 0, 0]
],
[
[0, 0, 0, 0],
[0, 3, 3, 0],
[3, 3, 0, 0],
[0, 0, 0, 0]
],
[
[0, 0, 0, 0],
[4, 4, 0, 0],
[0, 4, 4, 0],
[0, 0, 0, 0]
],
[
[0, 0, 0, 0],
[5, 0, 0, 0],
[5, 5, 5, 0],
[0, 0, 0, 0]
],
[
[0, 0, 0, 0],
[0, 0, 6, 0],
[6, 6, 6, 0],
[0, 0, 0, 0]
],
[
[0, 0, 0, 0],
[0, 7, 0, 0],
[7, 7, 7, 0],
[0, 0, 0, 0]
]
];
}