tetris
テトリス練習
* 演出なし
*
* スペースで回転
* 十字キーで移動
/**
* テトリス練習
* 演出なし
*
* スペースで回転
* 十字キーで移動
*/
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.ui.Keyboard;
[SWF(width="465", height="465", frameRate="60", backgroundColor="0xCCCCCC")]
public class Tetris3 extends Sprite {
public static const STAGE_WIDTH:uint = 12;
public static const STAGE_HEIGHT:uint = 21;
public static const BLOCK_NULL:int = 0;
public static const BLOCK_WALL:int = 9;
private var _field:Array = [];
private var _view:View;
private var _block:Block;
private var _frameCount:uint = 0;
public function Tetris3() {
_view = new View(this);
for (var yy:uint = 0; yy < STAGE_HEIGHT; ++yy) {
_field[yy] = [];
}
for (yy = 0; yy < STAGE_HEIGHT; ++yy) {
for (var xx:uint = 0; xx < STAGE_WIDTH; ++xx) {
if(xx == 0 || xx == STAGE_WIDTH - 1 || yy == STAGE_HEIGHT - 1)
_field[xx][yy] = BLOCK_WALL;
else
_field[xx][yy] = BLOCK_NULL;
}
}
createBlock();
_view.render(_field, _block);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
private function onKeyDown(e:KeyboardEvent):void {
switch(e.keyCode) {
case 37://左
moveBlock( -1, 0);
break;
case 39://右
moveBlock(1, 0);
break;
case 40://下
moveBlock(0, 1);
break;
case Keyboard.SPACE:
rotateRight();
break;
}
}
private function onEnterFrame(e:Event):void {
if (_frameCount++ % 30) return;
moveBlock(0, 1)//下に落とす
if (checkCollision(0, 1)) {//下に落ちないなら
fixMovingBlock();
checkLine();
createBlock();//新しいブロックを出した時に重なっていたらgame over
if (checkCollision(0, 0)) {
gameOver();
return;
}
}
_view.render(_field, _block);
}
private function gameOver():void {
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
_view.render(_field, _block);
var tf:TextField = createTextField(this, 'game over', undefined, undefined, 70);
tf.x = (465 - tf.width) / 2;
tf.y = 465 - tf.height - 10;
}
private function rotateRight():void {
if (_block.type == 2) return;//四角は回転させない。
_block.rotateRight();
if (checkCollision(0, 0)) {
_block.rotateLeft();//当たっていたら元に戻す
}
_view.render(_field, _block);
}
private function checkCollision(diffX:int, diffY:int):Boolean {
if (_field[_block.x + diffX][_block.y + diffY]) return true;
for (var i:int = 0; i < 3; ++i) {
var pos:Array = _block.map[i];
if (_field[_block.x + pos[0] + diffX][_block.y + pos[1] + diffY]) {
return true;
break;
}
}
return false;
}
private function moveBlock(diffX:int, diffY:int):void {
if (checkCollision(diffX, diffY)) return;
_block.x += diffX;
_block.y += diffY;
_view.render(_field, _block);
}
private function createBlock():void {
var type:int = Math.random() * (Block.blocks.length - 1) + 1;//1から7をランダムに
_block = new Block(type);
const startX:uint = 5;
const startY:uint = 0;
_block.x = startX;
_block.y = startY;
}
private function fixMovingBlock():void {
_field[_block.x][_block.y] = _block.type;
for (var i:uint = 0; i < 3; ++i) {
var pos:Array = _block.map[i];
_field[_block.x + pos[0]][_block.y + pos[1]] = _block.type;
}
}
private function checkLine():void {
for (var yy:int = STAGE_HEIGHT - 2; yy >= 0; --yy) {
var filled:Boolean = true;//y行目が詰まっているか調べる。一個でも壁でなかったらfalseにする。
for (var xx:uint = 1; xx < STAGE_WIDTH - 1; ++xx) {
if (_field[xx][yy] == BLOCK_NULL) {
filled = false;
break;
}
}
if (filled) {
for (var h:int = yy; h > 0; --h) {
for (xx = 1; xx < STAGE_WIDTH - 1; ++xx) {
_field[xx][h] = _field[xx][h - 1];
}
}
for (xx = 1; xx < STAGE_WIDTH - 1; ++xx) {
_field[xx][0] = BLOCK_NULL;//一番上の段を空で埋める
}
++yy;//もう一度同じラインを調べる
}
}
_view.render(_field, _block);
}
private function createTextField(parent:Sprite = null, text:String = "", x:int = 0, y:int = 0, fontSize:int = 13):TextField {
var tf:TextField = new TextField();
tf.x = x, tf.y = y;
tf.defaultTextFormat = new TextFormat("_typeWriter", fontSize, 0x0);
tf.text = text;
tf.selectable = false;
tf.autoSize = TextFieldAutoSize.CENTER;
if (parent) parent.addChild(tf);
else this.addChild(tf);
return tf;
}
}
}
import flash.utils.ByteArray;
class ArrayUtil {
public static function clone(arg:*):* {
var b:ByteArray = new ByteArray();
b.writeObject(arg);
b.position = 0;
return b.readObject();
}
}
class Block {
/*
ブロックは以下の種類がある。oが代表。
1 2 3 4 5 6 7
xoxx ox xox xox xox xo ox
xx x x x xx xx
*/
//代表からの相対座標でブロックを表す
public static const blocks:Array = [
[],//0は空を表したいので使わない
[ [-1, 0], [ 1, 0 ], [ 2, 0] ], //1
[ [ 1, 0], [ 0, 1 ], [ 1, 1] ], //2
[ [-1, 0], [1, 0], [0, 1] ], //3
[ [-1, 0], [1, 0], [-1, 1] ], //4
[ [ 1, 0], [ -1, 0], [ 1, 1] ], //5
[ [ -1, 0 ], [ 0, 1], [ 1, 1] ], //6
[ [ 1, 0] , [0, 1], [-1, 1 ] ] //7
];
public var x:int;
public var y:int;
public var type:int;
public var map:Array;
public function Block(_type:int) {
type = _type;
map = ArrayUtil.clone(blocks[type]);
}
/**
* 90度づつ回転させる
*/
public function rotateRight():void {
var temp:Array = ArrayUtil.clone(map);
for (var i:uint = 0; i < 3; ++i) {
var p:Array = map[i];
var tempP:Array = temp[i];
p[0] = tempP[1];
p[1] = -tempP[0];
}
}
public function rotateLeft():void {
var temp:Array = ArrayUtil.clone(map);
for (var i:uint = 0; i < 3; ++i) {
var p:Array = map[i];
var tempP:Array = temp[i];
p[0] = -tempP[1];
p[1] = tempP[0];
}
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
//配列を渡すと描画するクラス
class View {
private static const _STAGE_BG_COLOR:uint = 0xffffff;
private static const _STAGE_WALL_COLOR:uint = 0x80;
private static const _BLOCK_COLOR:Array = [0, 0xFF0099, 0x00FFFF, 0x0000FF, 0xFF0000, 0x00FF00, 0xAA00FF, 0xFFA500];
private var _layer:Sprite;
private var _bm:Bitmap;
private var _bmd:BitmapData;
public function View(layer:Sprite) {
_layer = layer;
_bmd = new BitmapData(Tetris3.STAGE_WIDTH, Tetris3.STAGE_HEIGHT, false, _STAGE_BG_COLOR);
_bm = new Bitmap(_bmd);
_layer.addChild(_bm);
_bm.scaleX = _bm.scaleY = 15;
_bm.x = (465 - _bm.width) / 2;
_bm.y = (465 - _bm.height) / 2;
}
public function render(field:Array, block:Block):void {
_bmd.floodFill(0, 0, _STAGE_BG_COLOR);
//積まれたブロック、外壁を塗る
for (var yy:uint = 0; yy < Tetris3.STAGE_HEIGHT; ++yy) {
for (var xx:uint = 0; xx < Tetris3.STAGE_WIDTH; ++xx) {
switch (field[xx][yy]) {
case Tetris3.BLOCK_WALL:
_bmd.setPixel(xx, yy, _STAGE_WALL_COLOR);
break;
case Tetris3.BLOCK_NULL:
_bmd.setPixel(xx, yy, _STAGE_BG_COLOR);
break;
default:
_bmd.setPixel(xx, yy, _BLOCK_COLOR[field[xx][yy]]);
}
}
}
//動いているブロックの場所を塗る
var movingBlockColor:uint = _BLOCK_COLOR[block.type];
_bmd.setPixel(block.x, block.y, movingBlockColor);
for (var i:uint = 0; i < 3; ++i) {
var pos:Array = block.map[i];
_bmd.setPixel(block.x + pos[0], block.y + pos[1], movingBlockColor);
}
}
}