見出し画像

一緒にテトリス作ってみましょう!(6)

こんにちは。
今日も一日ぐずついた天気でした。
しかし、暖かくなってきたのが嬉しくて、窓の外の雨混じりの曇り空を眺めながら、こういう日もいいものだなぁ、と思ってました。

今日はゲーム画面の外枠を表示してみましょう。
実はまだ全体像をどのようにするか決めてないのですが、Game 全体を仕切ってくれる class Game があって、class GameField にはゲーム画面の表示だけを担当してもらおうと考えてます。
(社会生活と同様に、それぞれ担当してくれる係りを作っていくイメージでプログラムを作っていきましょう。)

今回作るテトリスには簡単な機能しか実装しませんので、全体のプログラムは小さくなる予定です。
そのため、プログラムは全部 MainPage.xaml.cs に書いちゃおうと思ってます。

まだ、class Game は、下のことしか決めてませんw。

class GameField の下あたりに追加してください。

上図の const は、「この値は変更しない」という意味です。変更しない値には const を付けておくと良いですよ。
Px_BLOCK は、1つのブロックのピクセル数を表しています。自分の好きな値に変更してもらって構いません。
Px_INNER_BLOCK は、ブロックの色を塗るピクセル数です。色を塗る範囲を少し小さくして、隣のブロックとの境界を見やすくします。

次に、昨日作った class GameField の Draw()(←かっこを付けることで、関数であることを強調してます)を改良します。

プログラムが見やすいように色付けしてるので、画像として貼り付けています。

少し長く見えますが、内容はすごく単純です。
コピペしやすいように、下の方にコードを貼り付けておきますね。

PCS_COLOR_FIELD は、ブロック全部の個数ですが、「左右両端の壁」と「下端の壁」を個数に入れています。
_colorField は、各ブロックの色を記録する配列で、左上から 0, 1, 2, 3, … と右下まで連番で考えています。
(配列と for ループは簡単なので説明を省略しますね。)

L35, 36 でフィールド全体を黒で塗りつぶしているので、L43 でブロックが黒色だったら色を塗るのを省略してます。
(L は行番号を表してます。)

L39-48 のような2重ループが分かりにくい場合は、以下のことをループで表現していると考えてください。
今は単純化のために、ブロックの幅を 10pxブロックの塗る幅を 8px として考えます。

canvas.FillColor = _colorField[0];  // x = 1, y = 1
canvas.FillRectangle(1, 1, 8, 8)

canvas.FillColor = _colorField[1];  // x = 11
canvas.FillRectangle(11, 1, 8, 8)

canvas.FillColor = _colorField[2];  // x = 21
canvas.FillRectangle(21, 1, 8, 8)
...

canvas.FillColor = _colorField[11];  // x = 111
canvas.FillRectangle(111, 1, 8, 8)


canvas.FillColor = _colorField[12];  // x = 1, y = 11
canvas.FillRectangle(1, 11, 8, 8)

canvas.FillColor = _colorField[13];  // x = 11
canvas.FillRectangle(11, 11, 8, 8)

canvas.FillColor = _colorField[14];  // x = 21
canvas.FillRectangle(21, 11, 8, 8)
...

canvas.FillColor = _colorField[23];  // x = 111
canvas.FillRectangle(111, 11, 8, 8)


canvas.FillColor = _colorField[24];  // x = 1, y = 21
canvas.FillRectangle(1, 21, 8, 8)

canvas.FillColor = _colorField[25];  // x = 11
canvas.FillRectangle(11, 21, 8, 8)

canvas.FillColor = _colorField[26];  // x = 21
canvas.FillRectangle(21, 21, 8, 8)
...

canvas.FillColor = _colorField[35];  // x = 111
canvas.FillRectangle(111, 21, 8, 8)


canvas.FillColor = _colorField[36];  // x = 1. y =31
canvas.FillRectangle(1, 31, 8, 8)

以下繰り返し

Draw() を作ったので、ブロック毎に色を塗れるようになったのですが、この状態で F5 キーを押すと、プログラムがクラッシュします。
それは、_colorField の配列をちゃんと初期化してないからです。

class の初期化が必要な場合、「コンストラクタ」を利用するのが一般的です。
コンストラクタとは、class が実際に利用されるときに最初に呼び出されるものです。class と同名の関数がコンストラクタとなるので、下図の関数を作っておけばオッケーです。

class GameField の中に、この関数を付け加えてください。

まず、_colorField を全部黒色にしてから、壁の左右両端と下端を灰色にしています。
このコンストラクタを付け加えてから F5 キーを押すと画面表示がうまくいくと思いますので、是非実行してみてください。

public class GameField : IDrawable
{
	const int PCS_COLUMN = 10;	// 横のブロック数です
	const int PCS_ROW = 20;		// 縦のブロック数です

	const int PCS_COLOR_FIELD = (PCS_COLUMN + 2) * (PCS_ROW + 1);
	Color[] _colorField = new Color[PCS_COLOR_FIELD];

	// GameField の横のピクセル数です
	const int Px_WIDTH_FIELD = Game.Px_BLOCK * (PCS_COLUMN + 2);
	// GameField の縦のピクセル数です
	const int Px_HEIGHT_FIELD = Game.Px_BLOCK * (PCS_ROW + 1);

	public GameField()
	{
		for (int i = 0; i < PCS_COLOR_FIELD; i++)
		{ _colorField[i] = Colors.Black; }

		for (int idx = 0; idx < PCS_COLOR_FIELD; idx += PCS_COLUMN + 2)
		{
			_colorField[idx] = Colors.LightGray;
			_colorField[idx + PCS_COLUMN + 1] = Colors.LightGray;
		}

		for (int idx = PCS_COLOR_FIELD - 2, cnt = PCS_COLUMN; cnt > 0; idx--, cnt--)
		{
			_colorField[idx] = Colors.LightGray;
		}
	}

	public void Draw(ICanvas canvas, RectF dirtyRect)
	{
		canvas.FillColor = Colors.Black;
		canvas.FillRectangle(0, 0, Px_WIDTH_FIELD, Px_HEIGHT_FIELD);

		int idx = 0;
		for (int y = 1; y < Px_HEIGHT_FIELD; y += Game.Px_BLOCK)
		{
			for (int x = 1; x < Px_WIDTH_FIELD; x += Game.Px_BLOCK, idx++)
			{
				if (_colorField[idx] == Colors.Black) { continue; }

				canvas.FillColor = _colorField[idx];
				canvas.FillRectangle(x, y, Game.Px_INNER_BLOCK, Game.Px_INNER_BLOCK);
			}
		}
	}
}

相変わらず画面の調整はできていませんが、下のように表示されると思います。
class Game の Px_BLOCK の値を変更すると、ブロックが大きくなったり小さくなったりするので、よければ試してみてくださいね。


少しゲーム画面らしくなったので嬉しいです。
このままのプログラムで、Android, iOS, macOS でも動くんだ、と思うとなんだか楽しいですよね。
それでは。


この記事が気に入ったらサポートをしてみませんか?