プレイ画面を作っていくぅ

前回まででついに、前準備とゲームとしてのひな型ができたと思う。(基本的なゲームの状態移行)
現在はプレイ画面に移行したときに、文字で“プレイ画面”って出てるだけなので、とりあえずボード(タイルの並び)が表示されるところまで作ろう

ボードとタイルの導入

ボードとタイルは、コンソール版で作ったやつを使っていく。
まったく一緒のものを使ってつくっていく。

"Boardとtileの導入"
const int BOARD_WIDTH = 4;
const int BOARD_HEIGHT = 4;
const int BLANK_POS = 16;
 
struct Board
{
	//          行    列
	int tile[BOARD_HEIGHT][BOARD_WIDTH];
};

後はコンソールで、文字で表示していたものを、どうグラフィックで表示するかって話になる。
とりあえず、BOARD_WIDTH xBOARD_HEIGHT = 4×4で、タイルっぽい矩形(四角)を表示する処理を書いてみようか。
ちなみに、キャラクターのサイズはファミコンのキャラが8×8, 16×16などの8の倍数規定だったこともあり、8の倍数で指定することが多い(画面のサイズも2の倍数とか8の倍数のことが多いよね)
タイルのサイズを128ぐらいで指定してみよう(128 x 4 = 512)。そうすると縦横に512×512の画面サイズが必要となる。

で、ウィンドウの大きさを、指定した大きさに変更できるので、Mainのループに入る前の初期設定するときに大きさを、タイルに合わせて変えてあげよう!

"Window Sizeの指定"
//タイル1枚のサイズ 幅、高さ
const Size TILE_SIZE = { 128, 128 };
//windowの大きさ 4x {128, 128} 縦横同じなのでどっちかかけてやる
const Size WSIZE = BOARD_WIDTH * TILE_SIZE;
 
void Main()
{
  //省略 背景書いたり、フォントアセット登録したりの次くらい
    Window::Resize(WSIZE);

実行例

実行したときにウィンドウサイズが512x512になっていればOK

Fig. 1: 大きさのアジャストされたタイトル画面

ついでにデバッグするたびに、スタートボタンを押すのはめんどくさいので、初期設定のstateをPLAYにしておこう
当然だけど、PLAY画面から始まるようになるよ

タイルの描画

次はタイルを書いてみよう!

Siv3DのRect型は、矩形の左上の座標と幅と高さ(正方形の場合はどっちか一方)を指定して.draw()してやると、矩形を描画してくれる。
2重ループを使って、うまいことRect型を作ってみよう
ちょっと、プログラム的には無駄が多いけどstruct Boardに、Rectをタイル数分作ってあげよう(本当にタイルを収める枠を作る感じ)

"Boardとtileの導入"
struct Board
{
	//          行    列
	int tile[BOARD_HEIGHT][BOARD_WIDTH];
        Rect tileRec[BOARD_HEIGHT][BOARD_WIDTH];
};

この枠に、実際の描画座標を割り当ててやる
ボードを初期化数関数InitBoardで、ついでにやってしまおう!

"ボードの初期化"
void InitBoard(Board& _board)
{
	for (int j = 0; j < BOARD_HEIGHT; j++)
	{
		for (int i = 0; i < BOARD_WIDTH; i++)
		{
			_board.tile[j][i] = j * BOARD_WIDTH + i + 1; //[j][i] = [列][行]の位置のタイル番号
			_board.tileRec[j][i] = Rect{ { X座標の計算, Y座標の計算}, 幅(高さ) };
		}
	}
}

PlayDrawとPlayUpdateの処理には、Boardのデータが必要となる。
それらの関数を、Board型の引数をとるように書き換える。

"ゲームループの関数を修正"
省略
void TitleUpdate();
void TitleDraw();
 
void PlayUpdate(Board& _board);
void PlayDraw(Board& _board);
 
void ClearUpdate();
void ClearDraw();
 
省略
 
void PlayUpdate(Board& _board)
{
 
 
}
 
void PlayDraw(Board& _board)
{
	// 背景の色を設定する | Set the background color
	Scene::SetBackground(Palette::Lemonchiffon);
	//StringはSiv3Dだけでつかえる stringの上位互換型
	String PlayStr = U"プレイ画面";
	FontAsset(U"TITLE_FONT")(PlayStr).drawAt(Scene::Center(), Palette::Cadetblue);
}
省略

んで、MainでBoard型の変数を作ってやって、初期化して、実際にPlayUpdateとPlayDrawに渡してゆくぅ

"Mainの修正"
void Main()
{
	//タイトル画面とスタートボタンのフォント(ンでそのままほかのシーンに使いまわし)
	FontAsset::Register(U"TITLE_FONT", FontMethod::SDF, 40, Typeface::Bold);
	FontAsset::Register(U"BUTTON_FONT", FontMethod::SDF, 20, Typeface::Mplus_Heavy);
	Window::Resize(WSIZE);
 
 
	Board myboard;
	InitBoard(myboard);
 
	while (System::Update())
	{
		switch (state)
		{
		case TITLE:
			TitleUpdate();
			TitleDraw();
			break;
		case PLAY:
			PlayUpdate(myboard);
			PlayDraw(myboard);
			break;
		case CLEAR:
			ClearUpdate();
			ClearDraw();
			break;
		case GAMEOVER:
			break;
		default:
			break;
		}
	}
}

次に、PlayDrawをInitBoardで作った枠を描画できるようにdrawFrameで輪郭を描画するよう変更する

drawFrame(枠内側の太さピクセル数, 枠外側の太さピクセル数, 色);

実際に書き換えてゆくぅ、これはこのまま書けばよい

"PlayDrawの修正"
void PlayDraw(Board& _board)
{
	// 背景の色を設定する | Set the background color
	Scene::SetBackground(Palette::Lemonchiffon);
	//StringはSiv3Dだけでつかえる stringの上位互換型
	String PlayStr = U"プレイ画面";
	FontAsset(U"TITLE_FONT")(PlayStr).drawAt(Scene::Center(), Palette::Cadetblue);
 
	for (int j = 0; j < BOARD_HEIGHT; j++)
	{
		for (int i = 0; i < BOARD_WIDTH; i++)
		{
			_board.tileRec[j][i].drawFrame(2, 0, Palette::Red);
		}
	}
 
}

描画処理がうまくいくとこんな感じに表示される。

Fig. 2: タイル枠の表示

その4 プレイ画面の作成2