フロントエンド開発Blog

オレには鈍器がある

JavaScript , enchant.js hitTest

オレには鈍器がある 作成途中のコード。tilemapとアナログパッドの実装です。開発中の汚いソースコードを恥ずかしげも無く晒し挙げます。

実装機能:
・タイルマップを敷き詰める
・plyaerを配置する
・配置したplayerを操作する

http://jsdo.it/oredon/lY9M

かいつまんで説明しますと、

・マップデータを用意し、0,1で構成された配列を用意
・上記と同様に、衝突判定を0,1で構成された配列を用意
・マップの衝突判定に基づいてキャラの挙動を定義
・キャラ、シーンを入力に基づいて動かす

ざっと4つの処理を実施しています。その中で特にややこしいのが三番目の「衝突判定」かなと思います。

何を隠そう、自分も試行錯誤したのがこの衝突判定部分でした。ここを少し詳しく見ていきます。

2Dのゲームですから、キャラの動きは x方向(横) y方向(縦) の二種類あります。まずはこの2種類にざくっと切り分けて制御を組み込みます

if( this.vx < 0 ){
	//左方向
}else if( this.vx > 0 ){
	//右方向
}

if( this.vy > 0 ){
	//下方向
}else if( this.vy < 0 ){
	//上方向
}

x軸とy軸で一端if連鎖が切れてますが、これは斜め方向の入力を有効にするためにx,yそれぞれ別の制御が必要なため分けています

次に個々の衝突判定を見ていきます。全部見るときりが無いので左入力のみにスポットを当ててみます

//左方向
if( !map.hitTest(this.x + this.vx + PC_MARGIN_HORIZONTAL, this.y+PC_MARGIN_TOP) ){
	this.moveTo(this.x + this.vx, this.y);
}

すみません、調整値がたくさん入ってて分かりにくいと思います(汗

要は「移動しようとしている先の座標がmapのcollisionデータ(衝突判定データ)とtrueかfalseか、enchant.jsに用意されているhitTest関数を使って調べ、移動可能なら移動し、移動不可なら移動しない」というだけの処理です。hitTestの結果がtrueなら壁がある、falseならただの床です。

この記述だけでも意図したとおり壁に衝突したらキャラがそれ以上動かなくなります。しかしこの状態で動かすと少しでも壁に引っかかるとキャラが動かなくなります。ちょっと操作しにくいですね、ということでドラクエなんかでも良くありがちな「障害物を半歩避けて動く」ようなロジックを最初のhitTestにつなげて記述します。

//左方向
if( !map.hitTest(this.x + this.vx + PC_MARGIN_HORIZONTAL, this.y+PC_MARGIN_TOP) ){
	this.moveTo(this.x + this.vx, this.y);
}else if( !map.hitTest(this.x + this.vx + PC_MARGIN_HORIZONTAL, this.y + 10 + PC_MARGIN_TOP) ){
	//壁があるが、左下方向に余白がある
	this.vy = this.vy ? this.vy : -this.vx;
	this.moveTo(this.x, this.y + this.vy);
	this.vy=0;
}else if( !map.hitTest(this.x + this.vx + PC_MARGIN_HORIZONTAL, this.y - 10 + PC_MARGIN_TOP) ){
	//壁があるが、左上方向に余白がある
	this.vy = this.vy ? this.vy : this.vx;
	this.moveTo(this.x, this.y + this.vy);
	this.vy=0;
}

左方向に動いて壁に激突したとき、左下・左上に空きがないか調べ、空きがあれば上下に適宜移動するようになりました。

あとは左方向だけでなく上下左右全てに同様の処理を展開すればキャラが動くようになりました。

ページトップへ

関連ページ

ページトップへ