今回は、ステージクリア後のステージ間移動処理の実装をしたいと思います。
実行結果は以下のようになります。

ステージ名表示画面は、コンティニュー画面と同じなので、ステージを移動した時に、次のステージ用のマップチップや敵の設定をするのみになります。
今回実装する内容
1.ゴール後の得点処理から、ステージ移行画面へと移動する
2.敵やマップオブジェクトを次のステージのものに変更する
ステージ移行処理をどうやって実装するかがポイントですね。
では、実装していきます。
実装
const.js
constに必要な定数を書き込みます。
// chapter51
let GOAL_WAIT_CNT = 180;
let STAGE_TIMES = [(60 * 60 * 4),(60 * 60 * 4)];
ゴール後のスコア換算から次のステージ移動を行うまでに、時間があるので、
その定数を定義するのと、ステージ2を新しく実装するので、ステージ2の時間を新しく追加します。
mario.js
ステージ遷移を行うためにマリオクラスを修正します。
まず、ゴールスコア加算処理から、ステージ表示画面に移るまでの時間を管理するメンバー変数を定義します。
// chapter51
// ゴールアニメーションのためのタイマー
this.goalCnt = 0
おわび
chapter50のinit関数の中を間違えていたので、修正してください。
変数名と値が間違っていました。
// chapter50
// ゴールアニメーション状態を管理する	
this.goalAnimationState = INACTIVE;
// 重力など行動を止めるフラグ
this.isMarioStop = false;
this.goalPosX = 32 * 36;
// chapter51
this.goalCnt = 0
ゴール処理が終了した時の分岐の中身を追加します。
3秒待ったらステージ表示処理に入るようにします。
case GOAL_ANIMATION_END:
	if(this.goalCnt++ >= GOAL_WAIT_CNT){
		this.moveNextStage();
	}
	break;
分岐の中のmoveNextStage関数を書きます
/**
 * ステージクリア時に次のステージに遷移させる
 */
Mario.prototype.moveNextStage = function(){
	// とりあえず、これでいい
	gTotalStageNumber++;
	gSubWorldNumber++;
	// ステージ切り替え画面に遷移させる
	gState = PRE_STAGE;
}
gState変数を変更することで、mainの描画が切り替わるように処理を書いているので、そのままPRE_STAGEを代入します。
ステージ数は原作のマリオでは、ステージ1-4からはステージ2-1に切り替わりますが、とりあえず今は気にしないということで。
最後に、ステージによってゴールの位置(ゴールにマリオが吸い込まれる位置)が変更されるので、ゴール位置をセットする関数を作ります。
/**
 * マリオがゴールで消える位置を代入する
 * @param {*} goalPosX 
 */
Mario.prototype.setGoalPosition = function(goalPosX){
	this.goalPosX = goalPosX + (MAP_SIZE * 6);
}
マップチップを記録するファイルを用意する
ステージ2や3用のマップチップを変数として定義する必要がありますが、const定義ファイルであるconst.jsに定義すると中身が乱雑になるので、
新しくmap.jsを定義して、その中にマップチップを記録することにします。
map.js
let gMap12 = [
    [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],
    [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],
    [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],
    [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],
    [255,255,255,255,255,255,255,255,255,255,255,255,255,-1,-1,255,255,255,255,-1,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],
    [255,255,255,255,255,255,255,255,255,255,255,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,48,48,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],
    [255,255,255,255,255,-1,-1,-1,255,255,255,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,48,48,48,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],
    [255,255,255,255,255,255,255,255,255,255,255,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,48,48,48,48,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],
    [255,255,255,255,255,255,255,255,-1,-1,255,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,80,82,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,48,48,48,48,48,255,255,255,255,255,255,255,255,255,255,255,255,140,141,142,143],
    [255,255,255,255,-1,-1,-1,-1,80,80,255,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,33,33,-1,-1,-1,255,255,255,255,255,255,255,255,255,255,33,33,33,255,255,255,255,255,255,255,255,255,80,80,80,255,255,255,255,255,255,255,255,255,255,255,255,255,255,48,48,48,48,48,48,255,255,255,255,255,255,255,255,255,255,255,255,156,157,158,159],
    [255,255,255,255,255,255,255,255,255,255,255,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,48,48,48,48,48,48,48,255,255,255,255,255,255,255,255,255,255,255,171,172,173,174,175],
    [255,255,255,255,255,255,255,255,255,255,255,-1,-1,-1,-1,-1,-1,62,63,-1,-1,-1,-1,-1,-1,-1,-1,62,63,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,255,255,62,63,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,62,63,255,48,48,48,48,48,48,48,48,255,255,255,255,255,255,255,255,255,255,255,187,188,189,190,191],
    [255,255,255,255,255,255,255,255,255,255,255,-1,-1,-1,-1,-1,-1,78,79,-1,-1,-1,-1,-1,-1,-1,-1,78,79,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,255,255,78,79,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,78,79,48,48,48,48,48,48,48,48,48,255,255,255,255,255,255,255,48,255,255,255,203,204,205,206,207],
    [112,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,-1,-1,113,113,113,113,113,113,113,113,113,113,113,113,113,-1,-1,-1,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,114],
    [128,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,-1,-1,129,129,129,129,129,129,129,129,129,129,129,129,129,-1,-1,-1,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,130],
];
// 背景用のマップチップ
var gBackGroundMapChip12 = [
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
  ];
ステージ切り替え処理
ステージ切り替え処理をmain.jsに書いていきますが、
まず、敵の切り替え処理を考えます。
ステージごとの敵の切り替え処理
はじめに敵のオブジェクトを作る時に多めに定義しておき、
多めに設定した、敵クラスを使わない場合は、処理フラグをオフにしておき、
処理させないようにします。
もちろん、ステージごとに敵のオブジェクトを生成してもokですが、
メモリを考えてこちらの実装にしました。
まず、敵の初期化関数で、stateを引数に持たせるようにします。
stateの引数にDeadを入れることで非活性にすることができます。
kuribo.js
/**
 * 初期化関数
 * @param {*} posX 
 * @param {*} posY 
 * @param {*} dir 
 * @param {*} state 
 */
Kuribo.prototype.init = function(posX,posY,dir,state = NORMAL_STATE){
	this.posX = posX;
	this.posY = posY;
	// chapter25敵の移動
	this.addPosX = 0;
	// chapter37
	this.addPosY = 0;
	// どのタイミングでアニメーションを切り替えるか
	this.animCnt = 0;
	// 切り出す始点のX座標
	this.animX = 0;
	this.animY = 0;
	this.direction = dir;
	// マップチップ座標
	this.rightMapX = 0;
	this.leftMapX = 0;
	this.upMapY = 0;
	this.downMapY = 0;
	// chapter27
	this.state = state;
	this.height = 16;
	this.deadCnt = 0;
	// chapter47
	this.score = 100;
}
stateをdefault引数にして、NORMAL_STATEを代入します。
こうすることで、他の部分を変更しなくて済みます。
nokonoko.jsも同様に変更してください。
main.js
stage2用の初期化分岐にて、ステージ2固有の初期化処理を行うことで、
ステージごとで敵の配置を変えることができます。
/**
 * ステージ2の敵の初期化
 */
function initStage2Enemy(){
  // kuribo
  gKuribos[0][0].init(1024,384,LEFT_DIR);
  gKuribos[0][1].init(1088,384,LEFT_DIR);
  // nokonoko
  gNokos[0][0].init(384,396,RIGHT_DIR);
  gNokos[0][1].init(192,396,LEFT_DIR);
}
マップチップの変更
マップチップの変更は、ステージ1から土管に入って別のステージに遷移した時と同様の処理でいけます。
/**
 * stage2用の初期化
 */
function initStage2(){
  // 敵の初期化
  initStage2Enemy();
  // 隠しブロックの出現を保存する
  if(gMario.hideBlockX != -1){
    replaceEmptyBoxMap(gMapChipCopy,gMario.hideBlockX,gMario.hideBlockY);
  }
  // マップ初期化
  gMapChip = JSON.parse(JSON.stringify(gMap12));
  gBackGroundMapChip = JSON.parse(JSON.stringify(gBackGroundMapChip12));
  gMario.init(0,384);
  
  // ゴール
  gGoal.init(91 * MAP_SIZE);
  gMario.setGoalPosition(91 * MAP_SIZE);
}
ゴール処理対応
ゴールの位置もステージによって異なるので、ゴールの位置も変更する必要があります。
goal.jsに初期関数を定義します。
goal.js
/**
 * 初期化
 * @param {*} posX 
 */
Goal.prototype.init = function(posX){
    this.posX = posX;
    this.flagY = 64;
    this.score = 0;
    this.castleFlagY = 273;
}
間違いとおわび
前回の書いた、flagAnimation関数が間違っていたので、修正してください。
変数名が間違っており、入れなければいけない値も違いました。
Goal.prototype.fragAnimation = function(mario){
    if(mario.goalAnimationState != INACTIVE){        
        // 地面まで達した場合
        if(this.flagY + 26 < 384){
            this.flagY += 3;    
        }
        else{
            this.flagY = 358;
        }
    }
}
これで、ゴール初期化処理は終わりです。
最後にステージ初期化処理の分岐の部分にstage2用の初期化関数を埋め込むことで、完成です。
/**
 * ステージ毎の初期化を行う
 */
function initStage(){
  switch(gTotalStageNumber){
    case 1:
      initStage1();
      break;
    case 2:
      initStage2();
      break;
  }
  initStageTimes(gTotalStageNumber);
}
まとめ
ステージの切り替えをどうするのかが、悩みどころです。
まぁ今回は一例ということで。
全体のcodeはgithubで確認してください。
感想
マップを作らないといけないので、少し時間がかかること以外をのぞいて、
ステージ遷移画面既に作ってあるので、実装自体は楽でした。
ステージの切り替え処理の実装は、ちゃんと考えないと後々困るところです。
次はタイトル画面を作って、マリオのステージ1をコピーすれば、目標としていたものが完成するはず!