前回まででついに、前準備とゲームとしてのひな型ができたと思う。(基本的なゲームの状態移行)
現在はプレイ画面に移行したときに、文字で“プレイ画面”って出てるだけなので、とりあえずボード(タイルの並び)が表示されるところまで作ろう
ボードとタイルは、コンソール版で作ったやつを使っていく。
まったく一緒のものを使ってつくっていく。
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のループに入る前の初期設定するときに大きさを、タイルに合わせて変えてあげよう!
//タイル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
ついでにデバッグするたびに、スタートボタンを押すのはめんどくさいので、初期設定のstateをPLAYにしておこう!
当然だけど、PLAY画面から始まるようになるよ
Siv3DのRect型は、矩形の左上の座標と幅と高さ(正方形の場合はどっちか一方)を指定して.draw()してやると、矩形を描画してくれる。
2重ループを使って、うまいことRect型を作ってみよう
ちょっと、プログラム的には無駄が多いけどstruct Boardに、Rectをタイル数分作ってあげよう(本当にタイルを収める枠を作る感じ)
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に渡してゆくぅ
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(枠内側の太さピクセル数, 枠外側の太さピクセル数, 色);
実際に書き換えてゆくぅ、これはこのまま書けばよい
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); } } }
描画処理がうまくいくとこんな感じに表示される。