プレイ画面を完成させていく

前回までの状態

Fig. 1: 枠だけ表示できている

こんな状態、これをもう少しかっこつけていく。

  1. 枠の内部に色を塗る
  2. 枠の大きさを調整
  3. 枠内にタイル番号を描画

この処理を追加していく

  1. 枠の内部に色を塗る
  2. 枠の大きさを調整
  3. 枠内にタイル番号を描画

これは実は簡単で、すでにRectの配列は作ってあるので、各Rectを好きな色で塗っていけばよい。
PlayDrawを書き換えるよ。

Listing. 1: タイルの塗りつぶし
"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].draw(好きな色で塗ればいいよ);
                        //タイル枠を書く
			_board.tileRec[j][i].drawFrame(2, 0, Palette::Red);
		}
	}
 
}
実行結果
Fig. 2: タイル塗りつぶし実行結果

なんかうまく行ったっぽいけど、枠を消してみる。

Fig. 3: タイル領域塗りつぶし(枠なし)

そりゃそうだよね。タイルが、画面いっぱいに隙間なく敷き詰められるように計算しているし、同じ色で塗ってるもんね。 全部同じ色になる。。。
そこで次。

  1. 枠の内部に色を塗る
  2. 枠の大きさを調整
  3. 枠内にタイル番号を描画

ちょっと見やすくするために、枠の大きさを調整して、タイルとタイルの間に隙間を作る。
これも簡単。枠を上下左右2ピクセルずつ縮小して、その分ずらして枠の真ん中にタイルが表示されるように調整する。
表示の時に毎フレーム調整してもそんなに手間にはならないけど、初めから位置をずらして登録してみよう。
InitBoardをいじっていく。

枠のサイズ調整
Fig. 4: 枠調整後のイメージ
Listing. 2: 枠の大きさを調整する
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;
			_board.tileRec[j][i] = Rect{ ここで、座標をずらして登録する };
		}
	}
}
Fig. 5: 調整結果

あとはDrawFrameとかで内側何ピクセルか塗るとかすると、ちょっと見やすくなる。(ついでにシラーっと”プレイ画面”の描画を前に出した)
そこは好き好きで!

Fig. 6: 枠完成
  1. 枠の内部に色を塗る
  2. 枠の大きさを調整
  3. 枠内にタイル番号を描画

あとは、枠の中にタイル番号を表示する。
タイル番号は

struct Board
{
	//          行    列
	int tile[BOARD_HEIGHT][BOARD_WIDTH];
	Rect tileRec[BOARD_HEIGHT][BOARD_WIDTH];
};

のBorad::tile[行][列]に入っている。
これ取ってきて、その場所の、Rectの真ん中に表示してあげるとそれっぽくなる。
Mainに、ナンバー表示用のFontAssetを追加する。
(別にTITLE_FONTとか使いまわしてもいいよ。
下のSDFフォントってやつを使うと、FONTを拡大縮小しても、表示のクオリティが下がることないらしいよ。
(っていう意味では、TITLE_FONTの大きさ変更して表示してもよかったな。)

詳しくは、公式ページの解説をみてね。

FontAsset::Register(U"TILEFONT", FontMethod::SDF, 75, Typeface::Bold);

矩形の中心座標は

//左上x,y 幅高さがwidthの四角形
Rect rec{x, y, width};
//その四角形の中心座標
rec.center();

で取得できる。これを、FontAsset().drawAt(四角形の中心座標)で描画すると、フォントの真ん中を、四角形の真ん中に合わせて描画してくれる(超便利すぎ機能)

数値と文字列の変換

もう一つ、数値→文字列の変換が必要になる。これもSiv3Dには便利な関数が登録されている。
ただし、Siv3DのString型にのみ変換できる。
(std::stringとかに変換したいときは、別の変換関数を使うけど、似たような関数があるからあとで調べてみて)
(ってのも、Siv3Dだけできても、ゲーム業界じゃ通用しないので、C++の標準関数も勉強しないとダメです)

int a = 100;
//数値→文字列(String型)の変換
String str = ToString(a);
Listing. 3: タイル番号を描画
void PlayDraw(Board& _board)
{

	// 背景の色を設定する | Set the background color
	Scene::SetBackground(Palette::Lemonchiffon);

	for (int j = 0; j < BOARD_HEIGHT; j++)
	{
		for (int i = 0; i < BOARD_WIDTH; i++)
		{
			_board.tileRec[j][i].draw(Palette::Burlywood);
			_board.tileRec[j][i].drawFrame(2, 0, Palette::Saddlebrown);
			FontAsset(U"TILE_FONT")(_board.tile[j][i]をStringに変換した文字列)
                                               .drawAt(_board.tileRec[j][i]の真ん中の座標);
		}
	}

	//StringはSiv3Dだけでつかえる stringの上位互換型
	String PlayStr = U"プレイ画面";
	FontAsset(U"TITLE_FONT")(PlayStr).drawAt(Scene::Center(), Palette::Cadetblue);
}
Fig. 7: タイル番号表示まで

最後に空白タイルを設置する。
設置するって言っても、もともとコンソール版でも以下のように設定して、設定された番号をスルーしていた。

"空白の番号を設定"
const int BLANK_POS = 16;
<code>
つまり描画処理でボードのタイル番号がBLANK_POSの時だけスルーすればよい\\
こう書くとできそうな気がする。\\
<code cpp>
for (int j = 0; j < BOARD_HEIGHT; j++)
{
    for (int i = 0; i < BOARD_WIDTH; i++)
    {
        if(タイル番号 != BLANK_POS)
        {
            タイルの描画処理;           
        }
    }
}

当然これでもよいが、今回は新登場で、ループ制御構文のcontinueを使ってみよう。
continueを使うと条件に合った時だけスルーできる。

Listing. 4: continueによるループ制御
#include <iostream>
using namespace std;
int main() {
    //1~10までの奇数だけ表示
	for(int i=1; i<=10; i++){
		if(i % 2 == 0)
			continue;
		cout << i << " " ;
	}
}

結果:

1 3 5 7 9

こうすることで、ブロックが1個減るのでコードが見やすくなる(はずと信じてる)。

スペースの設置実際のコード

Listing. 5: 空白部分を設置
void PlayDraw(Board& _board)
{

	// 背景の色を設定する | Set the background color
	Scene::SetBackground(Palette::Lemonchiffon);

	for (int j = 0; j < BOARD_HEIGHT; j++)
	{
		for (int i = 0; i < BOARD_WIDTH; i++)
		{
                        _board.tile[j][i]にBLANK_POSを見つけたらcontinueでskipする

			_board.tileRec[j][i].draw(Palette::Burlywood);
			_board.tileRec[j][i].drawFrame(2, 0, Palette::Saddlebrown);
			FontAsset(U"TILE_FONT")(ToString(_board.tile[j][i])).drawAt(_board.tileRec[j][i].center());
		}
	}
Fig. 8: skip処理の描画結果

次は、ついに数字を入れ替えて営く処理を書いていこう

その5 タイルのスライド処理へ

  • game-engineer/classes/2023/something-else/summertime-special-cource/slidepuzle-siv3d-4.txt
  • 最終更新: 3年前
  • by root