これは実は簡単で、すでにRectの配列は作ってあるので、各Rectを好きな色で塗っていけばよい。
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); } } }
なんかうまく行ったっぽいけど、枠を消してみる。
そりゃそうだよね。タイルが、画面いっぱいに隙間なく敷き詰められるように計算しているし、同じ色で塗ってるもんね。
全部同じ色になる。。。
そこで次。
ちょっと見やすくするために、枠の大きさを調整して、タイルとタイルの間に隙間を作る。
これも簡単。枠を上下左右2ピクセルずつ縮小して、その分ずらして枠の真ん中にタイルが表示されるように調整する。
表示の時に毎フレーム調整してもそんなに手間にはならないけど、初めから位置をずらして登録してみよう。
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; _board.tileRec[j][i] = Rect{ ここで、座標をずらして登録する }; } } }
あとはDrawFrameとかで内側何ピクセルか塗るとかすると、ちょっと見やすくなる。(ついでにシラーっと”プレイ画面”の描画を前に出した)
そこは好き好きで!
あとは、枠の中にタイル番号を表示する。
タイル番号は
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);
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);
}
最後に空白タイルを設置する。
設置するって言っても、もともとコンソール版でも以下のように設定して、設定された番号をスルーしていた。
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を使うと条件に合った時だけスルーできる。
#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個減るのでコードが見やすくなる(はずと信じてる)。
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());
}
}
次は、ついに数字を入れ替えて営く処理を書いていこう