今回は、いよいよタイトル画面を作ります。
タイトル画面を作ったので、gameoverからタイトル画面への移行実装も行います。
実行結果は以下のようになります

タイトル画面にて、キー押下と、後のスマホ対応も念頭において、画面をクリックしたら、ステージに進むようにします。
今回実装する内容
1.最初にタイトル画面を表示させる(タイトル画面の分岐を作る)
2.タイトル画面から入力を受け取り、ステージ表示画面に遷移する
3.ゲームオーバー時にタイトル画面に戻る処理を行う
4.タイトル用の初期化関数を用意する
では、実装していきます。
実装
まず、タイトル画面用の画像を新しく作成します。
以下のように作りました。

こいつを切りとってつかいます。
では、main.jsを修正して、タイトル画面を入れるようにしましょう。
main.js
まず、タイトル用のテクスチャを読み込みます。
// chapter52
let gTitleTex;
gTitleTex = new Image();
gTitleTex.src = "resource/title.png"; 
読み込んだ画像を使って、タイトル画面を描画します。
背景はタイトル用のマップチップを作って、drawMap関数で描画しています。
/**
 * タイトル画面の描画
 */
function drawTitle(){
  // title用のマップ
  drawMap(gTitleMapChip);
  // オプション
  drawOption();
  // タイトルロゴ
  g_Ctx.drawImage(gTitleTex,0,0,420,169,(DISPLAY_WIDTH / 2) - (420 / 2) ,40,420,169);
  // push space 170 width:275,height:35
  g_Ctx.drawImage(gTitleTex,0,170,275,35,(DISPLAY_WIDTH / 2) - (275 / 2) ,286,275,35);
  // mario
  gMario.draw(g_Ctx,gMarioTex);
}
コインの数などの描画はステージ中と変わらないので、drawOption関数を作って、まとめて描画するようにしました。
/**
 * 上に表示されるコインやスコアなどの描画
 */
function drawOption(){
  // chapter46 timer
  g_Ctx.drawImage(gMapTex,352,480,64,32, 550,0, 64, 32);
  drawNumber(615,32,Math.floor(timer.cnt / 60),0.8,0.8);
  // chapter47 score
  drawScore(32,10,gScore);
  
  // コイン
  g_Ctx.drawImage(gMapTex,32,64,32,32,280,8,22,22);
  // ×
  g_Ctx.drawImage(gMapTex,320,480,32,32,311,8,22,22);
  // コイン数
  drawNumber(343,10,gMario.coinNum,1,1,false);
}
タイトル画面用の更新関数を作る
タイトル画面分岐用の更新関数を作ります。
ゲーム画面に突入するフラグとなるスペースキーが押されたら、
ステージ表示画面に移動するようにします。
/**
 * タイトル画面のメインループ処理
 */
function titleUpdate(){
  // スペースボタンが押されたら、ステージ遷移画面に移る
  if(gSpacePush){
    moveTitleToPreStage();
  }
}
function moveTitleToPreStage(){
  gState = PRE_STAGE;
}
描画と更新の関数内で、TITLE分岐を追加します。
function move(){
  switch(gState){
    case TITLE:
      titleUpdate();
      break;
    case PRE_STAGE:
      movePreStage();
      break;
    case GAME_OVER:
      moveGameOver();
      break;
    case IN_STAGE:
      moveInStage();
      break;
  }
}
/*
	Draw
	描画
*/
function Draw(){
  switch(gState){
    case TITLE:
      drawTitle();
      break;
    case IN_STAGE:
      drawInStage();
      break;
    case PRE_STAGE:
      drawPreStage();
      break;
    case GAME_OVER:
      drawGameOver();
      break;
  }
}
ゲームオーバー処理時にタイトル画面に戻る処理
ゲームオーバー時にもタイトル画面に戻る必要があるので、
その処理を書きます。
ゲームオーバー → 一定時間経過 → タイトルという流れになります。
/**
 * ゲームオーバーからタイトル画面へ移るときの処理
 */
function moveGameOver(){
  if(moveStageCnt++ >= GAME_OVER_CNT){
    resetForTitle();
    moveStageCnt = 0;
    gState = TITLE;
  }
}
タイトル画面用に変数を初期化する必要があるので、resetForTitleという関数を作って、初期化処理をするようにしています。
/**
 * 残機やコインなど一番初期の状態にリセットする
 */
function resetForTitle(){
    gTotalStageNumber = 1;
    gWorldNumber = 1;
    gSubWorldNumber = 1;
    gScore = 0;
    gMario.init(32,384);
    gMario.titleReset();
    initStageTimes(gTotalStageNumber);
}
const.js
定数として、ゲームオーバーになってからタイトル画面に移動するフレームと
マリオの初期残機を示す変数を用意します。
// chapter52
let GAME_OVER_CNT = 150;
let PLAYER_NUM = 3;
mario.js
マリオ用のタイトル画面初期化関数を用意します。
コインと残機をリセットします。
/**
 * 残機やコインなど一番初期の状態にリセットする
 */
function resetForTitle(){
    gTotalStageNumber = 1;
    gWorldNumber = 1;
    gSubWorldNumber = 1;
    gScore = 0;
    gMario.init(32,384);
    gMario.titleReset();
    initStageTimes(gTotalStageNumber);
}
canvasをクリックした時の判定を取る
タイトル画面をクリックした時もステージ表示画面に遷移するようにしたいので、クリック判定を取れるようにします。
まず、canvasとして使っているtagにonclickを埋め込みます。
index.html
<div id="canvas_wrapper">
	<canvas id="id_canvas" width="640" height="480" onclick="onClickCanvas()"></canvas>
</div>
onclickの中に呼ばれる関数名を打ち込みます。
onClickCanvas関数をmain.jsの中で実装します。
/**
 * canvas click callback
 */
function onClickCanvas(){
  if(gState == TITLE){
    moveTitleToPreStage();
  }
}
これで、onClickCanvasが呼ばれ、タイトル画面に遷移するようになります。
まとめ
タイトル画面の画像さえ作ってしまえば、簡単な実装でした。
初代のタイトル画面を参考にしてsketchで作りました。
全体のcodeはgithubで確認してください。
感想
タイトル画面を作って、だいぶゲームぽくなった。
後は、来週ステージを作って、暫定完成予定。
しかしここまでくると、はじめはそんなことする予定がなかったけど、音を入れたくなってきた。
音を作らないといけない。