キノコで大きくなった時の当たり判定に対応する

キノコをとって大きくなった後の当たり判定を実装する(プログラムでマリオを作る第36回)

前回、キノコを取得して、プレイヤーを大きくする処理を書いたので、
今回は、大きくなって変更された当たり判定を修正したいと思います。

今回の実行結果はこちらになります。

キノコで大きくなった時の当たり判定に対応する

プログラム解説

mario.jsを開いてください。

まず、メンバー変数に新しくマリオの中心のマップチップ座標となるcenterMapYを定義します。

// chapter36
this.centerMapY = 0;

このcenterMapYの役割は、マリオの中間位置にマップチップオブジェクトがぶつかった場合にすり抜けないようにするためのものです。

続いて、マップチップ座標を更新するupdateMapPositionY関数を修正します。

キノコを取得して大きくなったことで、マリオの下端の座標がいままでの2倍になるので、そのための修正をします。

また同時に、先ほど定義したcenterMapYにも中央のマップチップ座標を代入します。

// キノコ状態の時と分ける
if(this.state == KINOKO_STATE){
	// キノコ状態の時のマップチップ座標
	this.upMapY = Math.floor(posY / MAP_SIZE);
	// 通常よりもマップチップ一つ分多い
	this.downMapY = Math.floor((posY + this.height - 1) / MAP_SIZE);
	// 中央座標
	this.centerMapY = Math.floor((posY + MAP_SIZE - 1) / MAP_SIZE);
}
else{
	// 小さい状態
	this.upMapY = Math.floor(posY / MAP_SIZE);
	this.downMapY = Math.floor((posY + MAP_SIZE - 1) / MAP_SIZE);
	// 中央座標
	this.centerMapY = Math.floor((posY + (MAP_SIZE / 2) - 1) / MAP_SIZE);
}

キノコを取得した時と、そうでない時とで、マップチップ座標を分けています。

続いて、配列外チェックの箇所にて、
centerMapYにも配列外に出た時、配列外を参照しないような処理を入れてあげます。

// ・・・
if(this.downMapY < 0){
	this.downMapY = 0;
}
// ★新しく追加
// 中央座標の配列外チェック
if(this.centerMapY >= MAX_MAP_Y - 1){
      this.centerMapY = MAX_MAP_Y - 1;
}
if(this.centerMapY < 0){
	this.centerMapY = 0;
}

当たり判定に中心座標も加える

続いて、当たり判定に先ほど定義した中心座標のマップチップも加えます。

collisionX関数にcenterMapYの判定も追加します。

Mario.prototype.collisionX = function(map,posX){
 	this.updateMapPositionX(posX);
 	// マリオの右側 ch36中心座標の判定も追加
	if(isObjectMap(map[this.downMapY][this.rightMapX]) || isObjectMap(map[this.upMapY][this.rightMapX]) || isObjectMap(map[this.centerMapY][this.rightMapX])){
 		// (加算される前の)中心点からの距離を取る
 		var vecX = Math.abs((this.moveNumX + HALF_MAP_SIZE) - ((this.rightMapX * MAP_SIZE) + HALF_MAP_SIZE));
 		this.addPosX = Math.abs(MAP_SIZE - vecX);
 	}
 	// マリオの左側 ch36中心座標の判定も追加
	else if(isObjectMap(map[this.downMapY][this.leftMapX]) || isObjectMap(map[this.upMapY][this.leftMapX]) || isObjectMap(map[this.centerMapY][this.leftMapX])){
 		// (加算される前の)中心点からの距離を取る
 		var vecX = Math.abs((this.moveNumX + HALF_MAP_SIZE) - ((this.leftMapX * MAP_SIZE) + HALF_MAP_SIZE));
 		this.addPosX = -Math.abs(MAP_SIZE - vecX);
 	}
 }

着地する点を変更する

マリオの高さが変わったため、着地点も修正する必要があるので、その対応をします。

collisionY関数のマリオの下側部分の当たり判定処理を修正します。

// マリオの下側
 if(isObjectMap(map[this.downMapY][this.rightMapX]) || isObjectMap(map[this.downMapY][this.leftMapX])){
 	// (加算される前の)中心点からの距離を見る
	var centerY = this.height == 64 ? this.posY + 32 : this.posY;
	var vecY = Math.abs((centerY + HALF_MAP_SIZE) - ((this.downMapY * MAP_SIZE) + HALF_MAP_SIZE));
	// ・・・

マリオの下端部分が32だけずれたため、オブジェクトとの当たり判定が起きる箇所を32だけ下にずらす必要があります。

centerYという一時変数を作成して、キノコを取得した場合との高さを分けるようにしました。

これで、キノコを取得した後の当たり判定に対応できました。

全体のコードはgithubから参照してください。