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、操作系変更、落下時の加速に対応、レベルアップ条件変更

1. 移動を矢印キーに変更
2. 回転をZ,Xキーに変更
3. いきなり落下ではなく、加速するように
4. スピードアップは10ライン消すごとに変更
5. 50ライン消すとレベル0に戻ります。enjoy!!
Get Adobe Flash player
by ongaeshi 05 Jan 2010
/**
 * 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());
       }

   }
}