>> シューティングゲーム作成入門トップに戻る

ボスを作ろう1(出現)

今回からはボスの作成にとりかかっていきます。
今回はボスを出現させるところまで説明します。

画像はコチラを使います。

最終的にはコレを少し明るめにした画像の合計2枚を使います。

どのように出現させるかというと、画面上から「すーっ」と滑らかに出現して、
ふわふわと浮かせる状態にさせます。
ふわふわと浮かせる為には、前回の追跡弾の光の弾で説明したsin波を使うので、
それに伴う角度の増加量や角度の合計用の変数を用意する必要があります。

まずはBOSSクラスのヘッダーファイルとコンストラクタを見てください。

#include "define.h"

class BOSS{
	//座標
	double x,y,prev_x,prev_y;

	//グラフィックハンドル
	int gh_face[2];
	int gh_shot[3];

	//現在の移動パターン
	int move_pattern;
	//現在のショットパターン
	int shot_pattern;

	//弾構造体
	E_SHOT shot[BOSS_SHOTNUM];

	//合計角度と増加量
	int angle,raise;

	//横移動時の増加量
	int raise2;
	int waitcount;
	bool wait;

	//次の移動場所までの距離
	double movex,movey;
	int p3_state;

	//ダメージを負ったかどうかのフラグ
	bool damageflag;

	//生きてるかどうかのフラグ
	bool flag;

private:
	void Move();
	void Appear();
	void MovePattern1();
	void MovePattern2();
	void MovePattern3();
	void MoveInit(double bx,double by,int state);
	void Draw();
public:
	BOSS();
	void SetDamageFlag();
	void SetFlag(bool f);
	bool GetFlag();
	void All();
};

//コンストラクタ
BOSS::BOSS()
{
	//座標初期値
	x=200;
	y=-100;
	prev_x=200;
	prev_y=-100;

	//画像読み込み
	gh_face[0]=LoadGraph("boss.png");
	gh_face[1]=LoadGraph("boss_damage.png");

	gh_shot[0]=LoadGraph("enemyshot1.png");
	gh_shot[1]=LoadGraph("enemyshot2.png");
	gh_shot[2]=LoadGraph("enemyshot3.png");

	//弾初期化
	for(int i=0;i<BOSS_SHOTNUM;++i){
		shot[i].flag=false;
		shot[i].gflag=false;
		shot[i].gh=0;
		shot[i].pattern=0;
		shot[i].rad=0;
		shot[i].speed=0;
		shot[i].x=0;
		shot[i].y=0;
	}

	raise=2;
	raise2=2;
	angle=0;
	move_pattern=0;
	shot_pattern=0;

	movex=0;
	movey=180;

	waitcount=0;
	wait = false;
	p3_state=0;

	damageflag=false;
	flag = true;

}

prev_x,prev_yはある地点からある地点に移動する際の、
前の位置の座標を表しています。
グラフィックハンドルは、ボスのキャラ画像と弾画像用の配列を用意します。
キャラが画像は通常時の画像と弾がヒットした時の画像の2枚分の配列を用意してます。
弾は3種類使うので要素数が三つの配列を用意してます。
ボスの移動に関しては、move_patternの値に従って動作させることにします。
他の変数は、とりあえず以下のものだけ気にして下さい。
他の変数は次回以降に説明します。

//合計角度と増加量
int angle,raise;
//次の移動場所までの距離
double movex,movey;

変数の意味は書いてある通りです。

次にコンストラクタを見てください。
まず初期座標を代入しています。
移動前の座標も一緒にしておきます。
sin値に使う際の角度の増加量を示すraiseは2にしておきます。
move_patternは0にしておきます。これは登場時に移動パターンを示します。
次の移動場所までの距離を示す、movexとmoveyですが、
真ん中の上から登場して、真ん中より若干上で止まるようにするので、
横の移動距離は変わりません。
ですのでmovexは0。
moveyについては敵の画像の大きさが120×120の大きさの物を使っているので、
一番上から80ピクセルぐらいの距離にいれば敵全体が見えます。
初期位置のy座標が-100で、そこから80まで移動するので、
移動距離としては180になります。
ですのでmoveyには180を代入しています。

次にmove_patternの値によって、ボスの移動動作を分岐させます。
そのためにMove関数を作ります。

void BOSS::Move()
{

	switch(move_pattern){
		case 0:
			Appear();
			break;
		case 1:
			MovePattern1();
			break;
		case 2:	
			MovePattern2();
			break;
		case 3:
			MovePattern3();
			break;
	}
}

上記のswitch文を見てもらえればわかりますが、
move_patternの値によって処理を分岐させています。
今回の講座で説明するのは、Appear関数とMovePattern1関数です。
Appear関数がボスが上から登場して定位置に移動するまでの関数で、
MovePattern1関数がふわふわと上下に移動させるための関数です。

まずはAppear関数の説明から行います。

void BOSS::Appear()
{
	double temp;

	angle+=2;

	temp=sin(angle*PI/180);

	x = 200;
	y = prev_y+temp*movey;

	//提位置まで移動したら移動パターンを1に変更
	if(angle==90){
		move_pattern=1;
		angle=0;
	}
}

まず、合計角度であるangleを2ずつ増加させてます。
その次に、追跡弾の章でも説明したとおり、
angleをラジアンに変換して、sin値を得ています。
x座標についてはそのまま上から登場して横に移動しないので200のままで座標は変化ありません。
y座標については、前回の座標prev_yにsin値tempと目的地までの距離moveyをかけています。
こうすることで、angleが90に達したときに、sin値は1を返すので、
丁度目的の位置の座標に移動できるようになります。
sin値の増加量は滑らかに増加するので、動きも滑らかに移動させることが出来るわけです。
その下のif文で、angleが90に達すると、
move_patternを1に設定し、angleを0に戻してます。
move_patternを1にすると上記のmove関数で説明したとおり、
MovePattern1関数が実行されることになります。

MovePattern1関数は以下のとおりになっています。

void BOSS::MovePattern1()
{
	angle+=raise;

	y=80+sin(angle*PI/180)*BOSS_SHAKE;

	if(angle==90){
		raise=-2;
	}else if(angle==-90){
		raise=2;
	}

	x=200;
}

基本的には先ほどのAppear関数とあまり変わりません。
BOSS_SHAKEという定数はdefine.hで、
#define BOSS_SHAKE 20;
というように定義してます。
これは振れ幅を表しています。追跡弾のところで説明したのでわかりますよね?
最終的には+80足して座標を計算しています。
80というのはボスがふわふわ移動せずに停止していた場合の定位置です。
つまり定位置を基準にして振れ幅の分だけふわふわと移動することになります。
その下のif文では90か-90に達したときに、角度の増加量raiseの値を反転させてます。
こうすることでふわふわと移動させることができます。

最後にDraw関数とAll関数です。

void BOSS::Draw()
{
	//弾があたったときはダメージ用の画像を描画、
	if(damageflag){
		DrawRotaGraph(x,y,1.0,0,gh_face[1],TRUE);
	}else{
	//何も無いときは通常描画
		DrawRotaGraph(x,y,1.0,0,gh_face[0],TRUE);
	}


	damageflag=false;
}

void BOSS::All()
{
	Move();
	Draw();
}

特に難しくありません。
今はまだ使いませんが、ボスに弾が当たったときはdamageflagを立てるようにするつもりです。
その時だけ少し明るめのダメージ専用の画像を描画するようにしたいので、
フラグが立っているときだけダメージ用の画像を描画するようにしています。
フラグは毎回戻すようにしています。
All関数はただMove関数と、Draw関数を実行しているだけです。
省略しますが、このボスクラスをCONTROLクラスで宣言し、All関数を呼び出すことで、
以下の動画のようにボスを出現させることができます。

とりあえず今回はここまでです。
次回は移動パターンを増やしてみましょう。

>> 【ボスを作ろう2(移動パターン追加)】に進む
>> シューティングゲーム作成入門トップに戻る