背景レイヤーを使ってボスを作ろう

ここでは背景マップチップを使ってオリジナルのボスを作る方法を記述しています。
必要最低限なものは用意しておいてください。


スペシャルサンクス

Ten Years Ago様


マップチップに当たり判定をつける方法

まさおコンストラクション3.0以降ではマップチップのコードを取得するメソッドが用意されています。
背景用マップチップのコードを取得するにはgetMapChip2()メソッドを使います。
今回は当たり判定をつけたいので、主人公の位置のマップチップコードが知りたいので

mapchip_code = Applet1.getMapChip2(Applet1.getMyX(),Applet1.getMyY());
と記述しましょう。
mapchip_codeは別の名前にしてもらっても構いません。
ただし今回は分かりやすいようにこの名前を使っていきます。

マップチップコードを取得しただけでは何も起きないので、
このマップチップコードの値を利用して起こしたい動作を記述します。
今回は取得したマップチップコードが一定数値以上であれば、主人公が死ぬという動作を記述します。
以下の通りです。
if( mapchip_code >= 1 ) {
	Applet1.setMyMiss(2);
}
このように記述すると、主人公が背景マップチップのコードが1以上の場所に来ると死亡します。
マップチップのコードはまさおコンストラクションのフォルダ内に入っている「mapchip.bmp」に記述されている番号です。
マップチップコード0は左上の何も書かれていない空白の場所で、ここには画像を描かないようにしましょう。

では先ほどはマップチップコードを取得した場合死ぬ処理を施したので、今度はマップチップコードを取得して
主人公に敵を踏んだ時のアクションを実行させてみましょう。
if( mapchip_code >= 30 && Applet1.getMyVY() >= 10 ) {
	Applet1.setMyPress(3);
	boss_hp = boss_hp - 1;
}
まずこのプログラムを実行するための条件をご覧ください。
この記述を日本語で書きますと
取得したマップチップコードが30以上。そして主人公の落下速度が10以上である場合
主人公にボスを踏んだ時の動作をさせ、ボスの現在のHPを1減らし、その値を次のボスのHPとする。
このように記述することで敵を踏んだという処理を施すことができます。

これで死ぬ当たり判定と踏み判定を作ることができました。


背景マップチップの配置

次にプログラムを記述してマップチップを配置する方法を説明します。
マップチップを配置するにはsetMapChip2()メソッドを使います。
以下のように記述することで指定した座標にマップチップを配置することができます。

Applet1.setMapChip2(0,0,1);
まさおコンストラクションで使われている座標は全部で3種類あり、

1つはマップチップ単位による座標。
1つは1ドット単位による座標。
1つはアプレット画面の1ドット単位による座標。

今回はマップチップ単位で動作させるものしか使用しませんので、下2つは今回は無視してください。

話がそれましたが、上のプログラムの意味は横方向の座標(x座標)の位置0、縦方向の座標(y座標)の位置0に
マップチップコード1を配置するというものです。
要するに、一番左上端の位置に、マップチップのパターン画像の左上端から1つ右にずれた画像を貼りつけます。
マップチップを配置するメソッドをうまく使いこなしましょう。


ボスのパラメータを決める

それでは実際にボスを作っていくことにしましょう。
そのためには必要なパラメータを初期化します。
最低限必要なパラメータはボスのx座標とy座標、そしてボスのHPです。
それではパラメータを初期化するプログラムを見ていくことにしましょう。
ですがその前にこちらを参照してプログラムの動かし方の違いを理解してください。

非同期式の場合

function init() {
	boss_x = 20;	//ボスのx座標
	boss_y = 27;	//ボスのy座標
	boss_hp = 3;	//ボスのHP

	その他初期化したい変数など
}

timerID = setInterval("mainLoop()",100);	//mainLoop()を0.1秒毎に実行する

function mainLoop() {

	if(Applet1.getMode() < 2) {
		return;
	}

	if(Applet1.getJSMes() == 1) {		//ゲーム開始のメッセージを受けた
		Applet1.setJSMes(0);		//メッセージを受けたことを報告	
		init();				//init()を実行する
	}

	以下プログラムが続く

}
このプログラムの動作順は以下の通りです。
timerID = setInterval("mainLoop()",100);により0.1秒毎に関数mainLoop()が実行される
mainLoop()が実行され、ゲームが始まっていなければreturn;が読まれプログラムが終了する
そうでなければそれ以降のプログラムが実行される。
ゲームを開始するとgetJSMes()の働きにより1が出力される。
このときに関数init()が呼ばれ、値が設定される。
ゲーム開始時の状態を維持しないため、別の値をアプレット側に返す。
以降動作させたいプログラムが呼び出される。
これが非同期式のプログラムの流れです。次に同期式を見ていきます。
同期式の場合

//グローバル変数
var init_f = false;	//  JavaApplet 起動時の初期化をしたかのフラグ

//  JavaApplet から全てのモードで  描画直前に呼び出される
function userJS(Offscreen_g,mode,view_x,view_y) {


	//  JavaApplet 起動時の初期化
	if(init_f == false) {
		init_f = true;

		//  JavaApplet 起動時の初期化
		userInitJS();
	}


	if(mode >= 100  &&  mode < 200) {
		//  ゲーム中
		if(Applet1.getJSMes() == 1) {
			//  ゲーム開始

			//  JavaApplet からのメッセージをクリアー
			Applet1.setJSMes(0);

			//  JavaScript ゲーム開始を呼び出す
			userGameStartJS();
		}

		//  JavaScript ゲーム中を呼び出す
		userGameJS(Offscreen_g,view_x,view_y);
	}

}


//  JavaApplet 起動時に JavaScript から1回だけ呼び出される
function userInitJS() {
}

function userGameStartJS() {
	boss_x = 20;
	boss_y = 27;
	boss_hp = 3;

	その他初期化したい変数など
}

funciton userGameJS(Offscreen_g,view_x,view_y) {
	メインプログラムを記述する
}
同期式の場合はJavaアプレット(ここではゲームと置き換えます)がJavascriptの関数userJS()を0.1秒毎に実行しています。
非同期式はゲーム以外の場所でプログラムを実行していると考えてください。
ゲームモードが100から199の間の処理は非同期式で記述しているものと全く同じです。
大きな違いはゲーム側でプログラムを制御しているか否かということです。


ボスの制御を行う

ここまではボスを作るための準備段階でした。いよいよボスの動きを扱うということに触れていきます。

サンプルとしてボスを左に1マス移動させるプログラムを考えることにします。
ボスの大きさはまさおのボスと同じ64*64とします。
まず、ボスのx座標,y座標を指定する変数boss_xとboss_yを用意し、64*64のボスを配置します。

function userGameJS(Offscreen_g,view_x,view_y) {

	if(boss_jyoutai == 100) {					//ゲーム開始時のボスの状態(値を100とする)
		Applet1.setMapChip2(boss_x,boss_y,1);		//左上
		Applet1.setMapChip2(boss_x+1,boss_y,2);		//右上
		Applet1.setMapChip2(boss_x,boss_y+1,3);		//左下
		Applet1.setMapChip2(boss_x+1,boss_y+1,4);		//右下
	}

}
変数boss_x,boss_yをボスの左上とし、マップチップ1を配置。その右隣にマップチップ2を配置。
その下の座標にそれぞれマップチップ3と4を配置しています。
なぜ下の座標なのに+1なのかと疑問に持つ方がおられるかと思います。
y座標は一番上が0で下に行くほど値が大きくなります。よって+1というわけです。
この4つを基準としてマップチップを貼りつけました。

次にボスを左に1マスずらします。
以下の記述をご覧ください。
function userGameJS(Offscreen_g,view_x,view_y) {
	…
	else if(boss_jyoutai == 200) {
		boss_x = boss_x - 1;				//ボスが1マス左に移動する
		Applet1.setMapChip2(boss_x,boss_y,1);		//左上
		Applet1.setMapChip2(boss_x+1,boss_y,2);		//右上
		Applet1.setMapChip2(boss_x,boss_y+1,3);		//左下
		Applet1.setMapChip2(boss_x+1,boss_y+1,4);		//右下

		Applet1.setMapChip2(boss_x+2,boss_y,0);		//過去のボスの右上の画像を消す
		Applet1.setMapChip2(boss_x+2,boss_y+1,0);		//過去のボスの右下の画像を消す
	}
}
まず何かの影響でボスの状態が変わり、ボスが左に1マス移動する状態に変化しました。(ここではboss_jyoutaiの値が200)
するとboss_xの値が1マス左にずれました。
その後、その座標を基準としてマップチップを配置します。
ところが、配置したマップチップは1度配置されたら消えずに残ってしまいます。
すると、前のボスの右の画像が残った状態になってしまいます。
そこで、ボスが移動することにより残ってしまったゴミをきれいにしてやる必要があります。
そのために空白のマップチップを配置します。 下の図をご覧ください。
○:空白
□:マップチップ
■:ゴミマップチップ

移動前

○○○○○□□○○○
○○○○○□□○○○


移動後
○○○○□□■○○○
○○○○□□■○○○

ボスが左に1マスずれるとこのようにマップチップが配置されます。
すると基準となるマップチップから右に2マスずれた場所にゴミが残りますよね。
ここに空白のマップチップを配置すると下の図のようになります。
○:空白
□:マップチップ
■:ゴミマップチップ

移動前

○○○○○□□○○○
○○○○○□□○○○


移動後
○○○○□□○○○○
○○○○□□○○○○

こうすることによりマップチップでできたボスが移動したように見えるというわけです。
縦方向の移動も同じようにゴミの後始末を行う必要があります。
これをボスの攻撃に応用することももちろん可能です。
後は自分でプログラムを記述し試行錯誤してマップチップを配置していくだけです。


最後に

ここで説明していることは基本的な部分です。
またここで書いたサンプルでは動きが速すぎるので、自分で考えて動きを制御してください。
様々なサイトを巡って「技」を盗んでいきましょう。