タイトル真っ暗なんだよねぇ。。。
みんなphotshopとか使えるし、デザインの授業を受けているので、タイトル画面のロゴくらい作れるよね?
作ってはっつけてみよう。
僕は、デザインとかできないのでPowerPointのワードアートと図形を使って画像を作りました。
ロゴっぽいもの作って、グループ化して右クリック⇒図として保存で、画像化できるよ(授業で教えたよね?)
図形の塗りつぶしを、塗りつぶしなしにしておいてpngで保存すれば透明部分が勝手にできるので便利
出来たら、貼り付けていこう。
まず、Mainでアセット化、ついでにゲームスタートをクリックからスペースキープッシュに変えよう。
スタートメッセージ用のフォントもアセットで準備
FontAsset::Register(U"STARTFONT", 30, Typeface::Bold); TextureAsset::Register(U"TITLELOGO", U"images/costcomanlogo.png");
TileUpdateで、スペースが押されたらスタートに変更、TitleDrawでロゴを描く!
void UpdateTitle(GAME_STATE& _state) { if (スペースキー押されたら) { _state = GAME_STATE::PLAY; } } void DrawTitle() { Scene::SetBackground(Palette::White); //Scene::Center()はPoint型返すから、位置調整したいときはPoint{}でどのくらいずらすか決めて、足し算してやるといいよ(便利) TextureAsset(U"TITLELOGO").resized(700).drawAt(Scene::Center() + Point{0, -80}); FontAsset(U"STARTFONT")(U"Push SpaceKey to Start Cleaning up") .drawAt(Scene::Center() + Point{0, 50},Palette::Midnightblue); FontAsset(U"font")(U"TITLE_SCENE").drawAt(Scene::Center()+Point{0,250}, Palette::Black); }
さてここまで来て問題(質問)です。
コンソール版で'+'と'*'は何を表したでしょうか?
正解は(越後製菓)。。。
enum OBJNAME { FLOOR, WALL, LUGG, GOAL, HUMAN, HUMAN_ON_GOAL, LUGG_ON_GOAL }; const string OBJS[] = { " ", "#", "$", ".", "@", "+", "*" };
これを見るとわかるけど、HUMAN_ON_GOAL, LUGG_ON_GOALだね。
2キャラが重なっている場面を表している文字である。
Siv3D版では、これを記号じゃなくTextureの配列にしているので、何番のテクスチャが何か見ると([5]と[6]みればいいね)
Texture ObjImg[7]{ TextureAsset(U"FLOOR"), TextureAsset(U"WALL"), TextureAsset(U"LUGG"), TextureAsset(U"GOAL"), TextureAsset(U"PLAYER"), TextureAsset(U"PLAYER"), TextureAsset(U"LUGG"), };
PLAYERとLUGG、多分一番上にいそうなキャラを描画しているのが、現状である。
しかしながら、初めからプレイヤーとゴールが重なってスタートしている状態や、初めから荷物がゴールに重なっていて、そこから移動しなければならない場合も、ステージによっては存在する。
そういう時には、キャラが重なっていないかどうか判別する機能が欲しくなるよね。そこでこんな機能を追加しよう!
Shiftキーを押すと、HUMAN_ON_GOAL, LUGG_ON_GOALの時は、ゴールが透けて見える。
半透明はSiv3D様にとっては簡単で、
以下のように描画処理を書くと、実現できる
画像を2枚重ねて、上の画像を半透明(透明度0.5)で描画するには
Texure ue; //上に乗ってる半透明にする画像 Texure sita; //下にある画像 sita.draw(座標); ue.draw(座標, ColorF{ 1.0, 0.5 }); //1.0は色なので変えないで。0.4は不透明度 1.0が不透明 0に近づくと透明になっていく
これを使って、HUMAN_ON_GOAL, LUGG_ON_GOALのオブジェクトを発見した時だけ透明度を0.5にして描画すればよい
Texture ObjImg[7]{
TextureAsset(U"FLOOR"),
TextureAsset(U"WALL"),
TextureAsset(U"LUGG"),
TextureAsset(U"GOAL"),
TextureAsset(U"PLAYER"),
TextureAsset(U"PLAYER"),
TextureAsset(U"LUGG"),
};
for (int j = 0; j < _map.stage_height; j++) {
for (int i = 0; i < _map.stage_width; i++) {
OBJNAME objNum = GetObjectNum({ i,j }, _map);
if (objNum != 7)
{
ObjImg[FLOOR].draw(i * CHR_SIZE, j * CHR_SIZE);
ObjImg[GetObjectNum({ i,j }, _map)].draw(i * CHR_SIZE, j * CHR_SIZE);
}
}
}
現在は、描画部分でその位置のオブジェクトを取得して、オブジェクト番号に応じた画像を、スクリーンの対応位置に描画する。という処理になっているはず
オブジェクト番号7番の時は、ステージ外なので無視する。(もっといい書き方あるよね笑)
これを、オブジェクト番号が5,6の時に半透明で描画する処理を書いていく
正直すっきり書く方法があまり思いつかなかったので、わかりやすくこう書いていく
Texture ObjImg[7]{
TextureAsset(U"FLOOR"),
TextureAsset(U"WALL"),
TextureAsset(U"LUGG"),
TextureAsset(U"GOAL"),
TextureAsset(U"PLAYER"),
TextureAsset(U"PLAYER"),
TextureAsset(U"LUGG"),
};
for (int j = 0; j < _map.stage_height; j++) {
for (int i = 0; i < _map.stage_width; i++) {
OBJNAME objNum = GetObjectNum({ i,j }, _map);
switch (オブジェクト番号でスイッチ)
{
case FLOOR:
床だけ書いてブレイク;
break;
case WALL:
case LUGG:
case GOAL:
case HUMAN:
壁、荷物、ゴール、プレイヤーの時は、床を描いてから、オブジェクトを重ねて書く(地面にオブジェクト置くイメージ)
んで、ブレイク
break;
case HUMAN_ON_GOAL:
case LUGG_ON_GOAL:
問題はこの2つ、床描いて、ゴール描いて、プレイヤーまたは荷物を半透明で書く)
break;
default:
7番とか来たときはdefaultでbreakしてやる(何も書かない)
break;
}
}
}
こんな感じに書いてやればいいと思う。
あとは、シフトキーを押しているかどうか判別して(フラグとか作るといいね)シフトキーが押されているフラグがたっているときだけ半透明にするといいと思う
もっとスマートな書き方もあるけど、とりあえずこれでいいことにする
case LUGG_ON_GOAL: if(シフトキーフラグがtrue) 床描いて、ゴール描いて、プレイヤーまたは荷物を半透明で書く) else 通常通り、床描いて、プレイヤーまたは荷物を描く break; default: 7番とか来たときはdefaultでbreakしてやる(何も書かない) break;
シフトキーフラグを付けたバージョン