トップページ >
電子工作インデックス >
テトリス >
3. ゲーム画面の作り方
3. ゲーム画面の作り方
分かりやすさ重視ということで…多少効率わるいかもしれませんが、LEDマトリクスのドット数
分の配列をそのまま用意することにします。
用意する配列は全部で3種類です。
- ブロックの配列
- 壁&固定済みブロックの配列
- ゲーム画面表示用配列(前に出てきたdisplay[38][24]です。)
ブロック用の配列
{0,0,1,1,1,1,0,0},
{0,0,1,1,1,1,0,0},
{0,0,1,1,0,0,0,0},
{0,0,1,1,0,0,0,0},
{0,0,1,1,0,0,0,0},
{0,0,1,1,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
1マスあたりLED1個だと見栄えがしません。また、画面内に膨大な数のブロックが
入ってきてカオスになるため、ブロック1マスあたりLEDを2個×2個としました。他のブロック
と同様のサイズとして扱えるように、余白も含め、ブロック用配列のサイズは全て
8×8の2次元配列とします。正方行列にしないと回転等の処理が面倒になります。
さらに、ブロックの種類を番号で指定できると後々ラクなので、この2次元配列を要素と持つ
3次元配列として定義しておきます。
const char blocks[7][8][8]=
{
{
{0,0,1,1,0,0,0,0},
{0,0,1,1,0,0,0,0},
{0,0,1,1,0,0,0,0},
{0,0,1,1,0,0,0,0},
{0,0,1,1,0,0,0,0},
{0,0,1,1,0,0,0,0},
{0,0,1,1,0,0,0,0},
{0,0,1,1,0,0,0,0},
{,
{
{0,0,1,1,1,1,0,0},
{0,0,1,1,1,1,0,0},
{0,0,1,1,0,0,0,0},
{0,0,1,1,0,0,0,0},
{0,0,1,1,0,0,0,0},
{0,0,1,1,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
},
…こんな感じで、7種類分ブロックを作ります。
固定済みブロック用の配列
ゲーム中に動かす必要があるのはブロックのデータだけなので、
壁や落下済みの固定ブロックはレイヤーごと分離してしまいます。
そのほうが処理のイメージが分かりやすいです(たぶん)。
int back[38][24]=
{
{1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
{1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
……
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
こんな感じでつくります。初期化した時点であるのは壁のデータだけです。
ここに落下後のブロックのデータをどんどん足し合わせることでゲーム画面の
背景(?)を作っていきます。ブロックが落下済みかどうかは別の関数でチェックします。
上の配列初期化方法だとソースコードがかさばりますし、
ゲームオーバー後に新しく空ステージデータを作ることができないので、数式っぽく
記述しておきます。最終的につくられるデータは↑と同じですが…
int i,j
for( i = 0 ; i < 38 ; i ++ )
{
for( j = 0 ; j < 24 ; j ++)
{
//画面の上の方(底じゃない部分)
if( i < 36)
{
//壁の内側。
if( ( j > 1 ) && ( j < 22 ) )
{
back[i][j] = 0;
}
//壁。
else
{
back[i][j] = 1;
}
}
//画面の底の部分。
else
{
back[i][j] = 1;
}
}
}
}
こんなかんじで。
ゲーム画面表示用の配列
ブロックの座標を(x,y)として、ブロック+背景…ゲーム画面を作ります。配列を作るときに
ゲーム画面の見た目から入ってしまったので配列の要素を指定するのに
[x座標][y座標]の順になってしまいました。
block_typeはブロックの種類を指定する配列です。
int i,j;
for( i = 0 ; i < 8 ; i ++)
{
for( j = 0 ; j < 8 ; j ++)
{
display[ y + i ][ x + j] = blocks[block_type][i][j] + back[ y + i][ x + j];
}
}
こんな感じで足し合わせ…。