テトリスもどきゲーム

  1. 作成履歴

    このゲームはゼミの神谷君、吉田君の作品に伊藤が少し手を加えたモノです。

  2. ゲームの紹介

    1. ルール

      正方形4個から構成されるピースを、回転や左右に移動しながら、適当な場所に誘導して落とします。落ちたピースを構成する4角(ダイス)が、 左壁から右まで連続するとその行は削除されます。削除出来ないピースが上まで積み上がると、ゲームオーバーになります。 下のアプレットで体験して下さい。


    2. 操作

       アプレット上でクリックし、sキーを押すとゲームが開始します。左右の矢印キーで左右に、下キーで下に早く落ちます。 スペースキーでピースを回転します。横の線上をピースで埋めるとそのラインが消去(クリア)されます。一定以上をクリアすると、自然落下の速度が速くなります。

  3. ゲームの手法

    1. ゲームのフィールドの表現

       ゲームのフィールド(落下する空間)は 14*24 の格子で構成します。これを配列 area[][] で記録します。落ちるモノをここではピースと呼びます。フィールドの左右と下の壁を -1、ピースのないフィールドを 0,ピースのあるフィールドにピースの番号(1..7)を記録します。

    2. ピースのデータ構造

       このゲームで工夫がいるのはピースの回転法です。この回転を容易にするピースの表現方法が重要です。回転で広い領域を使うのは下図の直線型のピースで、赤の位置を中心として右回転させます。



       そこで、ピースの形状を5*5の配列 piece[i][j] で記憶し、ピースを構成する小さな四角(ダイスと呼びます)のない要素を0、ダイスのある位置をn(ピースの番号)で表現します。piece[0][0]は左上隅の点とします。

    3. ピースの作成

       bpをピースの種類を表す番号とします。中心と、その下にはかならずダイス(4角)があるものとします。
       piece[2][2] = bp;
       piece[2][3] = bp;

      他の二つを、ピースの種別で次のように設定します。
            case 2:
              piece[3][1] = bp;
              piece[3][2] = bp;
              break;
            case 3:
              piece[1][2] = bp;
              piece[1][3] = bp;
              break;

    4. ピースの回転

       一般に原点(0,0)を中心とする右回転は(x,y)座標を(y,x)座標に入れ替え、適当に符号を変更すれば、回転が表現できます。ただし、ここでは原点は配列の左上隅ですから、j の符号の入れ替えは -j でなく、4-j とします。たとえば、(2,4)のダイスは右回転で(0,2)に移動します。したがって、
            copy_piece[4-j][i] = piece[i][j]; 
      で右回転が表現できます。他のピースは5*5のマスの中で回転しますから、各ピースは中心を(2,2)とする5*5の配列で表現できます。

    5. ピースの移動、可能性

      5*5 のピースを配置する中心位置を (bx,by) とします。各、i ,j について
           (piece[i][j] >= 1 && area[bx + i - 2][by + j - 1] == 0)
      であれば、つまり、ピースのダイスがある位置のフィールドが空白であれば、その位置にピースを移動することができます。bx + i - 2 の -2 はピースの中心から左端までの距離です。by + j - 1 の -1 は、ピースを一つ下に落としたときの、中心から上端までの距離になります。
       ピースを落とす(byを増加する)ことが出来なくなったら、ピースの番号を対応するフィールドの位置にコピーします。

    6. 行の消去判断と詰め込み

      消去可能かどうかの判定は簡単です。area[][]のi行にすべてに 0 のマスがなければ、i番目の行を消去可能ですから
            ld=1;
       for(j=2; j<12; j++) ld = ld * area[j][i];
      で、ld が 0 でなければ、横方向にすべてダイスがありますから、削除可能です。行を削除するには、上の行を1行下げれば良いので、
          for(k=i-1;k>0;k--)
        for(s=2;s<12;s++)area[s][k+1]=area[s][k];
      となります。

    7. ゲームの得点と制御

       消した行数で、得点が決まりますが、一度に複数の行を消すとボーナスを出すことにします。一行削除のボーナスを100点とし、同時に消した場合は、倍の得点にします。
       また、10行消すごとにレベルを増やし、ピースの落下速度を速くします。

    8. キーイベント処理

       ウインドウにGUI 部品を配置すると、イベント処理が部品のイベント処理に回ってしまいます。ここでは、部品を利用しないで、キーイベントを利用可能にします。キーイベントを利用するには、アプレットに KeyListener をインプリメントします。キーが押されると
            public void keyPressed(KeyEvent e)
      が、実行されます。 押されたキーの種類は e.getKeyCode() で知ることができます。方向キーは KeyEvent.VK_DOWN などで特定できます。スペースキーは KeyEvent.VK_SPACE、Sキーは KeyEvent.VK_S です。他の
       public void keyTyped(KeyEvent e){}
       public void keyReleased(KeyEvent e){}
      は利用しませんが、定義だけは作成しておく必要があります。

  4. プロジェクト

    1. レイアウト設計

      キーイベントを利用するため、文字入力を伴う部品は利用できません。ここでは、スコア表示などは位置を直接プログラムで指定しています。

    2. データ構造

      int area[][] = new int [14][24]; //ピース記憶領域
      int piece[][] = new int [5][5]; //ブィールド生成領域
      int bx,by;   //ピースの座標軸
      int bp;     //生成ピースのパターン

      int nline;    //消したラインの総数
      int nscore;   //現在のスコア
      int nlevel;    //現在のレヴェル
      int nfast=500;  //ピースの落下速度

      Image image1;  //ダブルバッファ用
      Graphics offgraphics;

    3. メソッド

      1. キーイベント処理: public void this_keyPressed(KeyEvent e){}
        このゲームでは、主要な操作を文字キーで実行します。まず、init()で addKeyListener(); を行います。これで、キーを押すと、このメソッドが呼ばれます。Sキーが押されると Game_Start() を実行し、ゲームを開始または再開し、実行中(satrt_check)なら、左、右、下キーでピースの移動、空白キーで回転をします。

      2. スレッド:w_clock
        スレッドを利用し、ピースの落下時間間隔を制御します。Game_Start()で、このスレッドの実行を開始します。

      3. ダブルバッファ
        グラフィックスのちらつきを抑えるため、ダブルバッファを利用します。start'() でimage1領域を作成し、offgraphicsにグラフィックスを表示します。ダブルバッファは、画面を仮想ウインドウで作成し、作成終了後まとめて仮想ウインドウの画像を本来の画面にコピーします。これで、画面を表示中に画面を書き換えることが少なくなり、ちらつきを抑えることができます。

      4. Set_Init()
        start'() で呼び出します。フィールドの初期化を行い、最初のピースを作成します。ピースが左右方向に外に出ないようフィールドの両側に壁を生成します。

      5. Create_piece()
        Set_Init()で呼び出します。乱数で次に生成するピースの種別を定め、種別に対応するピースを生成します。

      6. public void Move_Down()
        this_keyPressed()で呼び出します。落下中のピースがピースが下に移動か調べ、可能ならbyを増加し、再表示します。

      7. Move_Right()、Move_Right()
        落下中のピースがピースが左右に移動可能か調べ、可能なら、bxを増減し、再表示します。

      8. Roll_piece()
        落下中のピースの回転した配列を作成し、ピースが回転可能か調べます。回転可能なら、回転させます。

      9. public void paint (Graphics g)
        フィールドを表示します。area[i][j]の値に従い、4角のコマがある場合、ピースの種別による色で、背景の場合は黒で、-5の場合(ゲームオーバー)のとき灰色で塗ります。
      10. run()
        スレッドの実行部で、このゲームを進行します。ピースが落下出来ない場合、ピースをフィールドにおき、行を削除出来るか調べます。フィールドの(7,2)の位置が0でない場合、ゲームオーバーになります。それ以外の場合、ピースを生成し、位置を初期化します。

  5. ダウンロード・アンケート

    1. ソース

      ソースファイルは こちらからご覧下さい

    2. アンケート

      この種のゲームは得意ですか?  1:はい 2:少し 3:ぜんぜん
      プログラムは理解できましたか?  1:はい 2:少し 3:ぜんぜん
      プログラムは参考になりましたか?  1:はい 2:少し 3:ぜんぜん