tetris テトリス練習 * 演出なし * * スペースで回転 * 十字キーで移動 miniapp forked:0favorite:2lines:240license : see code comments modified : 2010-08-27 19:02:24 Embed Tweet /** * テトリス練習 * 演出なし * * スペースで回転 * 十字キーで移動 */ 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); } } } Code Fullscreen Preview Fullscreen sabotenbroth.. Albert clone map KeyboardEvent.ENTER_FRAME undefined KeyboardEvent.KEY_DOWN parent writeObject readObject ByteArray type Keyboard.SPACE position keyCode KeyboardEvent scaleY scaleX removeEventListener height width Boolean