敵を倒しきったらEND画面へ・・・

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
cupa
記事: 117
登録日時: 2年前

敵を倒しきったらEND画面へ・・・

#1

投稿記事 by cupa » 2年前

度々失礼します・・・

STGを頑張って作っている初心者です、、、
今回はタイトルの通り敵を倒しきったらEND画面へ転移の仕方がわかりません。

自分がやった方法は、Tekikazuという変数をもって、敵を描画するごとにTekikazuを1プラスして、もしTekikazuがTEKI_MAXになったらstatusをENDにする、そして転移したかわかりやすいように
今回はhelloと適当なところに表示しています。ランダムで敵を発生のところが悪いのかなぁとも思って、ワールド全体で見えているところでしかTekikazuをプラスしないようにしても結果は変わりませんでした。何が悪いのでしょうか?・・・

コード:

#define WORLD_WIDTH 640
#define WORLD_HEIGHT 480
#define Tama 500
#define TEKI_MAX 5
#define BOMB_MAX TEKI_MAX

#include "DxLib.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	int i;
	int j;
	int b;

	int JikiX, JikiY, JikiGraph;
	int JikiTamaGraph, JikiTamaX[Tama], JikiTamaY[Tama], JikiTamaFlag[Tama];
	int Teki1X[TEKI_MAX], Teki1Y[TEKI_MAX], Teki1Flag[TEKI_MAX], Teki1Graph;
	int Teki1W, Teki1H, TamaW, TamaH;
	int titlebackground, gamebackground, titlefont, titlemojifont;
	int sht_sound, sht_game_sound;
	int BombX[BOMB_MAX], BombY[BOMB_MAX], BombStatus[BOMB_MAX];
	int BombImage[16];
	int Tekikazu;


	ChangeWindowMode(true);
	SetGraphMode(WORLD_WIDTH, WORLD_HEIGHT, 64);
	DxLib_Init();
	SetDrawScreen(DX_SCREEN_BACK);
	SetDrawMode(DX_DRAWMODE_BILINEAR);
	SetWindowText("生姜");

	for (i = 0; i < Tama; i++)
	{
		JikiTamaFlag[i] = 0;
	}

	for (j = 0; j < TEKI_MAX; j++)
	{
		Teki1Flag[j] = 0;
	}

	for (b = 0; b < BOMB_MAX; b++)
	{
		BombStatus[i] = -1;
	}

	titlebackground = LoadGraph("Game.title.jpg");
	gamebackground = LoadGraph("title2.jpg");
	JikiGraph = LoadGraph("sprite.png");
	JikiX = 320; JikiY = 400;
	JikiTamaGraph = LoadGraph("sht.jikishot.png");
	Teki1Graph = LoadGraph("killerT.png");
	titlefont = CreateFontToHandle("けいふぉんと", 50, 9, DX_FONTTYPE_ANTIALIASING_EDGE);
	titlemojifont = CreateFontToHandle("07やさしさゴシック手書き", 20, 5, DX_FONTTYPE_ANTIALIASING_EDGE);
	sht_sound = LoadSoundMem("sht.c.z.mp3");
	sht_game_sound = LoadMusicMem("sht.game.mp3");
	Tekikazu = 0;
	SetVolumeMusicMem(255 * 50 / 100, sht_game_sound);
	LoadDivGraph("sht.bomb.png", 16, 8, 2, 71, 68, BombImage);

	bool TekiDesFlag = false;


	// 弾のグラフィックのサイズをえる
	GetGraphSize(JikiTamaGraph, &TamaW, &TamaH);

	// 四角君のグラフィックのサイズを得る
	GetGraphSize(Teki1Graph, &Teki1W, &Teki1H);

	enum {
		TITLE,

		GAME,

		END,
	}status = TITLE;

	while (ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0)
	{
		ClearDrawScreen();

		switch (status)
		{
		case TITLE:
			DrawGraph(0, 0, titlebackground, 0);
			if (CheckHitKey(KEY_INPUT_Z)) {
				status = GAME;
				PlaySoundMem(sht_sound, DX_PLAYTYPE_BACK);
				PlayMusicMem(sht_game_sound, DX_PLAYTYPE_BACK);
			}
			break;
		case GAME:
			DrawGraph(0, 0, gamebackground, 0);
			break;
		case END:
			break;
		}

		if (status == TITLE)
		{
			DrawStringToHandle(70, 200, "シューティングゲーム", GetColor(255, 255, 255), titlefont);
			DrawStringToHandle(30, 420, "Zでゲーム開始", GetColor(255, 255, 255), titlemojifont);
			DrawStringToHandle(30, 450, "ESCでゲーム終了", GetColor(255, 255, 255), titlemojifont);

		}

		if (status == GAME)
		{
			DrawGraph(JikiX, JikiY, JikiGraph, true);

			if (CheckHitKey(KEY_INPUT_W))JikiY -= 3;
			if (CheckHitKey(KEY_INPUT_A))JikiX -= 3;
			if (CheckHitKey(KEY_INPUT_S))JikiY += 3;
			if (CheckHitKey(KEY_INPUT_D))JikiX += 3;


			if (CheckHitKey(KEY_INPUT_SPACE) == 1)
			{
				i = -1;
				for (int p = 0; p < Tama; p++) // 配列を走査し
				{
					if (JikiTamaFlag[p] != 1) // 空いている場所を見つけたら
					{
						i = p; // その添字をiに設定
						break;
					}
				}
				if (i >= 0)
				{
					int Pw, Ph, Tw, Th;

					GetGraphSize(JikiGraph, &Pw, &Ph);
					GetGraphSize(JikiTamaGraph, &Tw, &Th);

					// 弾iの位置をセット、位置はボール君の中心にする
					JikiTamaX[i] = (Pw - Tw) / 2 + JikiX;
					JikiTamaY[i] = (Ph - Th) / 2 + JikiY;

					JikiTamaFlag[i] = 1;
				}
			}

			for (i = 0; i < Tama; i++)
			{
				// 自機の弾iの移動ルーチン( 存在状態を保持している変数の内容が1(存在する)の場合のみ行う )
				if (JikiTamaFlag[i] == 1)
				{
					// 弾iを16ドット上に移動させる
					JikiTamaY[i] -= 20;

					for (int a = 0; a < TEKI_MAX; a++)
					{
						int p = i;

						if (Teki1Flag[a] != 0 && JikiTamaFlag[p] == 1)
						{
							if (((JikiTamaX[p] > Teki1X[a] && JikiTamaX[p] < Teki1X[a] + Teki1W) ||
								(Teki1X[a] > JikiTamaX[p] && Teki1X[a] < JikiTamaX[p] + TamaW)) &&
								((JikiTamaY[p] > Teki1Y[a] && JikiTamaY[p] < Teki1Y[a] + Teki1H) ||
									(Teki1Y[a] > JikiTamaY[p] && Teki1Y[a] < JikiTamaY[p] + TamaH)))
							{
								// 敵と弾が接触している場合


								if (!TekiDesFlag)
								{
									for (b = 0; b < BOMB_MAX; b++)
									{
										if (BombStatus[b] < 0)
										{

											BombStatus[b] = 0;
											BombX[b] = Teki1X[a];
											BombY[b] = Teki1Y[a];
											break;
										}
									}
								}
								TekiDesFlag = false;

								Teki1Flag[a] = 0;
								JikiTamaFlag[p] = 0;
							}
							else {
								TekiDesFlag = false;
							}
						}
					}

					// 画面外に出てしまった場合は存在状態を保持している変数に0(存在しない)を代入する
					if (JikiTamaY[i] < -80)
					{
						JikiTamaFlag[i] = 0;
					}

					// 画面に弾iを描画する
					DrawGraph(JikiTamaX[i] + 10, JikiTamaY[i] - 30, JikiTamaGraph, true);
					DrawGraph(JikiTamaX[i] - 10, JikiTamaY[i] - 30, JikiTamaGraph, true);
				}
			}

			if (rand() < (RAND_MAX / 100)) // 乱数で敵、発生 ←ここが間違っている?(あたっしゅさんに答えてもらいました)
			{
				//j = -1;
				for (int t = 0; t < TEKI_MAX; t++) // 配列を走査し
				{
					// if (PienTamaFlag[t] != 1) // 空いている場所を見つけたら
					if (Teki1Flag[t] != 1) // 空いている場所を見つけたら
					{
						Teki1X[t] = GetRand(WORLD_WIDTH);

						Teki1Y[t] = -64;

						Teki1Flag[t] = 1;

						break;
					}
				}
			}

			// 敵の描画
			for (j = 0; j < TEKI_MAX; j++)
			{
				if (Teki1Flag[j] != 0) {

					Teki1Y[j] += 3;

					if (Teki1Y[j] < WORLD_HEIGHT && Teki1Y[j] > 0 && Teki1X[j] < WORLD_WIDTH && Teki1X[j] > 0)
					{
						Tekikazu += 1;
					}

					DrawGraph(Teki1X[j], Teki1Y[j], Teki1Graph, true);
					// 四角い枠が表示されるのは、killerT.png の背景が透過になっていないため。
				}
			}

			//爆発アニメーションの描画
			for (b = 0; b < BOMB_MAX; b++)
			{
				if (BombStatus[b] >= 0)
				{
					DrawGraph(BombX[b], BombY[b], BombImage[BombStatus[b]], true);
					BombStatus[b]++;
					if (BombStatus[b] >= 16)
					{
						BombStatus[b] = -1;
					}
				}
			}

			if (Tekikazu == TEKI_MAX)
			{
				status = END;
			}

			if (JikiX > 640 - 64) JikiX = 640 - 64;
			if (JikiX <= 0) JikiX = 0;
			if (JikiY > 480 - 64) JikiY = 480 - 64;
			if (JikiY <= 0) JikiY = 0;


		}

		if (status == END)
		{
			DrawString(200, 200 - 32, "hello", GetColor(255, 255, 255));
		}

		ScreenFlip();

	}


	DxLib_End();

	return 0;
}
よろしくおねがいします、、、

cupa
記事: 117
登録日時: 2年前

Re: 敵を倒しきったらEND画面へ・・・

#2

投稿記事 by cupa » 2年前

補足:試しのhelloはちゃんと描画されています。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 敵を倒しきったらEND画面へ・・・

#3

投稿記事 by みけCAT » 2年前

どうして敵を描画するごとにTekikazuを1プラスするのか、説明できますか?

敵を倒しきったかの判定なら、敵を倒した、
すなわち弾と敵が接触して敵が消えた時にプラスした方がいいような気がします。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

cupa
記事: 117
登録日時: 2年前

Re: 敵を倒しきったらEND画面へ・・・

#4

投稿記事 by cupa » 2年前

やりたいことは、敵はTEKI_MAX分出てきて、敵を倒した分でスコアを決める(スコアはまだやっていない)というものです。何故敵を描画するごとにTekikazuをプラスするかというと、敵の数はTEKI_MAXだけれども、たまに取り逃します。
その取り逃した分も入れたいのでそうしています、

みけCATさんのやり方で行くと、確実にTEKI_MAX分倒すことになります。
ゲームでいうTA?みたいな感じで何秒でーとかだったらそれでも良いと思うのですが、、、(語彙力なくてすみません)

今自分が投稿したものを見てみたら、誤解されてもおかしくないことを言ってました、、、すみません

cupa
記事: 117
登録日時: 2年前

Re: 敵を倒しきったらEND画面へ・・・

#5

投稿記事 by cupa » 2年前

タイトルに敵を倒しきったら、と書いてありましたね……
完全に語彙力の問題でした、、、

littlestream
記事: 48
登録日時: 7年前

Re: 敵を倒しきったらEND画面へ・・・

#6

投稿記事 by littlestream » 2年前

やりたいことは次の通りではなく何故取り逃がしてしまうものを描画毎にtekikazu++;してしまうのか
分かりません。そんな事をしたら、tekikazu>TEKI_MAXまで簡単に推移してしまう気がしますが
もしかして、tekikazu++;したとしても敵を倒した直後に別の変数でも使うつもりなのでしょうか?

コード:

//自分が勘違いした場合の処理
if(敵と弾が当たったら)
{
     tekikazu++;
}

if(tekikazu>TEKI_MAX)
{
     DrawFormatString(X,Y,GetColor(255,rand()%255,0),"CLEAR!!");
     status=END;
}//自分が勘違いした場合の処理終わり

コード:

//cupaさんの通りの処理を想定したもの
for(int i=0;i<TEKI_MAX;i++)
{
     DrawGraph(//敵の描画(^^;
     
}
for(int i=0;i<TEKI_MAX;i++)
{
     if(//当たったら) tamahit++;
}

if(tamahit>TEKI_MAX)
{
     status=END;//????
}//cupaさんの通りの処理を想定したもの

cupa
記事: 117
登録日時: 2年前

Re: 敵を倒しきったらEND画面へ・・・

#7

投稿記事 by cupa » 2年前

littlestreamさんの言っていることがいまいちよくわかりません、、、

>やりたいことは次の通りではなく何故取り逃がしてしまうものを描画毎にtekikazu++;してしまうか
 分かりません。

みけCATさんとlittlestreamさんの勘違いしてらっしゃるところは同じだと思うのですが、
描画毎に敵の数をカウントしていけば、取り逃した敵もカウントに入るためTEKI_MAX分敵が描画された時点で終了、という流れになると思ったのですが、、、
お二人が言っているのは「敵と弾が当たったら・・・カウントする」というものだと思うのですが、
それの通りやると確実にTEKI_MAX分倒すことになると思います。
それはそれでいいと思うのですが、、、やりたいことの趣旨が違うので駄目だと思います。

もう一度いいますが、自分がやりたいことは「敵を倒せた分でScoreを決める」というものです。

cupa
記事: 117
登録日時: 2年前

Re: 敵を倒しきったらEND画面へ・・・

#8

投稿記事 by cupa » 2年前

ですが一点、自分でも間違えていたことがありました。
敵を描画しただけでカウントするのではなく、敵を描画して、「もし画面外に出てしまったら」
という処理を忘れていました。。。

littlestream
記事: 48
登録日時: 7年前

Re: 敵を倒しきったらEND画面へ・・・

#9

投稿記事 by littlestream » 2年前

cupaさんへ

描画された時点のカウント変数がどう変化しているか確かめるのと
ちょっとcupaさんの言っている事が卓上デバッグだと難しいので一番上のソースコードを
使ってデバッグしてみます。

littlestream
記事: 48
登録日時: 7年前

Re: 敵を倒しきったらEND画面へ・・・

#10

投稿記事 by littlestream » 2年前

コード:

if (Teki1Y[j] > WORLD_HEIGHT && Teki1Y[j] < -65 && Teki1X[j] > WORLD_WIDTH && Teki1X[j] < 0)
{
	Tekikazu += 1;
}
上の敵数をカウントしている条件式は上のように<が>に>が<になっているのと、敵を作った時に-64と
していたので瞬時にゲームが終わっているようだと思います。なのでy座標の判定式を-64から-1した-65に修正
したほうが良いと思います。

cupa
記事: 117
登録日時: 2年前

Re: 敵を倒しきったらEND画面へ・・・

#11

投稿記事 by cupa » 2年前

littlestreamさんに言われた通り直したので一瞬でEND画面へ・・・ということはなくなったのですが、逆に五体倒しても画面外に行ってもEND画面に行きません。どうしたらよいでしょうか。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 敵を倒しきったらEND画面へ・・・

#12

投稿記事 by みけCAT » 2年前

cupa さんが書きました:
2年前
逆に五体倒しても画面外に行ってもEND画面に行きません。どうしたらよいでしょうか。
デバッグをすればいいと思います。
敵が弾に当たった時に加え、敵が画面外に出たときにも、
「該当の敵を消して Tekikazu に1を足す」という処理をするようにするといいかもしれません。
littlestream さんが書きました:
2年前

コード:

if (Teki1Y[j] > WORLD_HEIGHT && Teki1Y[j] < -65 && Teki1X[j] > WORLD_WIDTH && Teki1X[j] < 0)
{
	Tekikazu += 1;
}
この条件式だと、「WORLD_HEIGHT (正の数) より大きく、かつ-65未満」な数や、
「WORKD_WIDTH (正の数) より大きく、かつ0未満」な数は存在しないので、
常に偽です。
&& のかわりに || を使ったほうがいいかもしれません。
littlestream さんが書きました:
2年前

コード:

if(tekikazu>TEKI_MAX)
{
     DrawFormatString(X,Y,GetColor(255,rand()%255,0),"CLEAR!!");
     status=END;
}

コード:

if(tamahit>TEKI_MAX)
{
     status=END;//????
}
tekikazuやtamahitの初期値が0であり、かつTEKI_MAX体の敵それぞれについて1回ずつしか1を足さない、
かつ1以外の値を足したり足し算以外の演算(引き算、掛け算など)をしない場合、
tekikazuやtamahitはTEKI_MAXまでにしかならず、これらの条件式は真になりません。
> のかわりに >= を使ったほうがいいかもしれません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

littlestream
記事: 48
登録日時: 7年前

Re: 敵を倒しきったらEND画面へ・・・

#13

投稿記事 by littlestream » 2年前

コード:

if (Teki1Y[j] > WORLD_HEIGHT && Teki1Y[j] < -65 && Teki1X[j] > WORLD_WIDTH && Teki1X[j] < 0)
{
	Tekikazu += 1;
	Teki1Flag[j]=0;
}
上のif文内のANDを全てORにするとENDに行くかもしれません。

返信

“C言語何でも質問掲示板” へ戻る