In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

tetris

テトリス練習
* 演出なし
* 
* スペースで回転
* 十字キーで移動
Get Adobe Flash player
by miniapp 27 Aug 2010
    Embed
/**
 * テトリス練習
 * 演出なし
 * 
 * スペースで回転
 * 十字キーで移動
 */
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);
        }
    }
}