-
ゲームのフィールドの表現
ゲームのフィールド(落下する空間)は 14*24 の格子で構成します。これを配列 area[][] で記録します。落ちるモノをここではピースと呼びます。フィールドの左右と下の壁を
-1、ピースのないフィールドを 0,ピースのあるフィールドにピースの番号(1..7)を記録します。
-
ピースのデータ構造
このゲームで工夫がいるのはピースの回転法です。この回転を容易にするピースの表現方法が重要です。回転で広い領域を使うのは下図の直線型のピースで、赤の位置を中心として右回転させます。
そこで、ピースの形状を5*5の配列 piece[i][j] で記憶し、ピースを構成する小さな四角(ダイスと呼びます)のない要素を0、ダイスのある位置をn(ピースの番号)で表現します。piece[0][0]は左上隅の点とします。
-
ピースの作成
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;
-
ピースの回転
一般に原点(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 のピースを配置する中心位置を (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を増加する)ことが出来なくなったら、ピースの番号を対応するフィールドの位置にコピーします。
-
行の消去判断と詰め込み
消去可能かどうかの判定は簡単です。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];
となります。
-
ゲームの得点と制御
消した行数で、得点が決まりますが、一度に複数の行を消すとボーナスを出すことにします。一行削除のボーナスを100点とし、同時に消した場合は、倍の得点にします。
また、10行消すごとにレベルを増やし、ピースの落下速度を速くします。
-
キーイベント処理
ウインドウに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){}
は利用しませんが、定義だけは作成しておく必要があります。