公式のDXライブラリを見ながら当たり判定を実装しようとしているのですが。。。。。。

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

公式のDXライブラリを見ながら当たり判定を実装しようとしているのですが。。。。。。

#1

投稿記事 by cupa » 2年前

タイトルの通り、当たり判定をつけようとしているのですが何も起こりません。
公式のDxLibをみて、自分のコードに合わせたのですが、できません。

コード:

#define WORLD_WIDTH 640
#define WORLD_HEIGHT 480
#define Tama 500
#define TEKI_MAX 50

#include "DxLib.h"

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

	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;
	int TekiCount;


	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;
	}

	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");
	TekiCount = 0;

	// 弾のグラフィックのサイズをえる
	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);
			}
			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;
					
					if (((JikiTamaX[i] > Teki1X[j] && JikiTamaX[i] < Teki1X[j] + Teki1W) ||
						(Teki1X[j] > JikiTamaX[i] && Teki1X[j] < JikiTamaX[i] + TamaW)) &&
						((JikiTamaY[i] > Teki1Y[j] && JikiTamaY[i] < Teki1Y[j] + Teki1H) ||
							(Teki1Y[j] > JikiTamaY[i] && Teki1Y[j] < JikiTamaY[i] + TamaH)))
					{
						// 接触している
						Teki1Flag[j] = 0;
						JikiTamaFlag[i] = 0;
					}

					// 画面外に出てしまった場合は存在状態を保持している変数に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) // 空いている場所を見つけたら
					{
						// j = t; // その添字をiに設定

						//int TekiPattern = GetRand(WORLD_WIDTH); // パターンではなく、発生する敵の X 座標

						//Teki1X[i] = TekiPattern;
						Teki1X[t] = GetRand(WORLD_WIDTH);

						//Teki1Y[j] += 3;

						Teki1Y[t] = -64;

						Teki1Flag[t] = 1;
						// DrawGraph(Teki1X[j], Teki1Y[j], Teki1Graph, true);

						break;
					}
				}
				//int TekiPattern = GetRand(640);

				//Teki1X[j] = TekiPattern;

				//Teki1Y[j] += 3;

				//DrawGraph(Teki1X[j], Teki1Y[j], Teki1Graph, true);
			}

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

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

			if (Teki1Y[j] > WORLD_HEIGHT + 64)
			{
				Teki1Flag[j] = 0;
			}

			

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


		}
		ScreenFlip();

	}


	DxLib_End();

	return 0;
}
何回も質問させてしまってすみません、初心者です。

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

Re: 公式のDXライブラリを見ながら当たり判定を実装しようとしているのですが。。。。。。

#2

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

cupa さんが書きました:
2年前

コード:

if (((JikiTamaX[i] > Teki1X[j] && JikiTamaX[i] < Teki1X[j] + Teki1W) ||
	(Teki1X[j] > JikiTamaX[i] && Teki1X[j] < JikiTamaX[i] + TamaW)) &&
	((JikiTamaY[i] > Teki1Y[j] && JikiTamaY[i] < Teki1Y[j] + Teki1H) ||
		(Teki1Y[j] > JikiTamaY[i] && Teki1Y[j] < JikiTamaY[i] + TamaH)))
{
	// 接触している
	Teki1Flag[j] = 0;
	JikiTamaFlag[i] = 0;
}
cupa さんが書きました:
2年前

コード:

if (Teki1Y[j] > WORLD_HEIGHT + 64)
{
	Teki1Flag[j] = 0;
}
これらの部分では、変数 j を適切に値を設定すること無く使っています。
この時、 j は他の部分で使われている for 文により TEKI_MAX になっており、
範囲外へのアクセスが発生してしまいます。
ループを追加するなどして、 j の値を適切に設定してから判定しないといけません。

弾の発射がどうもうまくいきません、、、 - プログラマ専用SNS ミクプラ
でも同様の間違いをしていますね。
何も考えずコピペするのではなく、処理の意味を考えてコードを書いたほうがいいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: 公式のDXライブラリを見ながら当たり判定を実装しようとしているのですが。。。。。。

#3

投稿記事 by cupa » 2年前

確かにそうですね、前言われた配列を走査する、というのがまだ理解できていなくて…どういう意味なのでしょうか、特に「i=p」や「j=t」などがわかりません。当たり判定も自分でやってみようかと思いましたが、ややこしすぎて公式のを見てやったものの理解ができないままコピペして…というのを繰り返していました、、、みけCATさんに言われたとおりに「配列を走破し・・・」ていうのを前と同じやり方でやってみたのですが、弾を撃つとフリーズしてしまいます(多分二重のループが原因です、ですが二つ(i,j)を使っているので一つにしようとしてもif文みたいにはできず、手ず待っています。何かやろうとすると何かが足りなかったりしてしまいます・・・)

取り敢えず現在のコードです、、、

コード:

#define WORLD_WIDTH 640
#define WORLD_HEIGHT 480
#define Tama 500
#define TEKI_MAX 50

#include "DxLib.h"

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

	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;
	int TekiCount;


	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;
	}

	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");
	TekiCount = 0;

	// 弾のグラフィックのサイズをえる
	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);
			}
			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;

					j = -1;
					i = -1;

					
					for (int a = 0; a < TEKI_MAX; a++)
					{
						for (int p = 0; p < Tama; p++)
						{
							if (Teki1Flag[a] != 1 || JikiTamaFlag[p] != 1)
							{
								if (((JikiTamaX[i] > Teki1X[j] && JikiTamaX[i] < Teki1X[j] + Teki1W) ||
									(Teki1X[j] > JikiTamaX[i] && Teki1X[j] < JikiTamaX[i] + TamaW)) &&
									((JikiTamaY[i] > Teki1Y[j] && JikiTamaY[i] < Teki1Y[j] + Teki1H) ||
										(Teki1Y[j] > JikiTamaY[i] && Teki1Y[j] < JikiTamaY[i] + TamaH)))
								{
									// 接触している
									Teki1Flag[j] = 0;
								}

								j = a;
								i = p;

								break;
							}
						}
					}
					// 画面外に出てしまった場合は存在状態を保持している変数に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) // 空いている場所を見つけたら
					{
						// j = t; // その添字をiに設定

						//int TekiPattern = GetRand(WORLD_WIDTH); // パターンではなく、発生する敵の X 座標

						//Teki1X[i] = TekiPattern;
						Teki1X[t] = GetRand(WORLD_WIDTH);

						//Teki1Y[j] += 3;

						Teki1Y[t] = -64;

						Teki1Flag[t] = 1;
						// DrawGraph(Teki1X[j], Teki1Y[j], Teki1Graph, true);

						break;
					}
				}
				//int TekiPattern = GetRand(640);

				//Teki1X[j] = TekiPattern;

				//Teki1Y[j] += 3;

				//DrawGraph(Teki1X[j], Teki1Y[j], Teki1Graph, true);
			}

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

					Teki1Y[j] += 3;

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

			

			

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


		}
		ScreenFlip();

	}


	DxLib_End();

	return 0;
}
同じ間違いをするとは、、、、、、、( ;∀;)

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

Re: 公式のDXライブラリを見ながら当たり判定を実装しようとしているのですが。。。。。。

#4

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

cupa さんが書きました:
2年前
前言われた配列を走査する、というのがまだ理解できていなくて…どういう意味なのでしょうか
配列の要素を前から1個ずつ処理していく、という意味です。
配列 走査 - Google 検索
cupa さんが書きました:
2年前
みけCATさんに言われたとおりに「配列を走破し・・・」ていうのを前と同じやり方でやってみたのですが
ループ後に条件を満たす要素が見つかったかをチェックし、
見つかっていたらそこに対して処理を行う、という処理が無いため、同じやり方ではないですね。
cupa さんが書きました:
2年前
弾を撃つとフリーズしてしまいます
for (i = 0; i < Tama; i++) のループの内側で、変数 i の値を不適切に書き換えているため、
特殊な場合以外は無限ループになってしまいますね。
cupa さんが書きました:
2年前
取り敢えず現在のコードです、、、

コード:

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

		j = -1;
		i = -1;

		
		for (int a = 0; a < TEKI_MAX; a++)
		{
			for (int p = 0; p < Tama; p++)
			{
				if (Teki1Flag[a] != 1 || JikiTamaFlag[p] != 1)
				{
					if (((JikiTamaX[i] > Teki1X[j] && JikiTamaX[i] < Teki1X[j] + Teki1W) ||
						(Teki1X[j] > JikiTamaX[i] && Teki1X[j] < JikiTamaX[i] + TamaW)) &&
						((JikiTamaY[i] > Teki1Y[j] && JikiTamaY[i] < Teki1Y[j] + Teki1H) ||
							(Teki1Y[j] > JikiTamaY[i] && Teki1Y[j] < JikiTamaY[i] + TamaH)))
					{
						// 接触している
						Teki1Flag[j] = 0;
					}

					j = a;
					i = p;

					break;
				}
			}
		}
		// 画面外に出てしまった場合は存在状態を保持している変数に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);
	}
}
変数 i の不適切な書き換えもダメですが、
変数 i や j を -1 に設定したのに JikiTamaX[​i] や Teki1X[j] にアクセスするのもダメです。
配列の添字は、0以上要素数未満のみが有効な要素です。
当たり判定のループでは、変数 a と p をループに使うことにしたようなので、
判定にもこれらの変数を使うべきです。

さらに、 Teki1Flag[a] != 1 || JikiTamaFlag[p] != 1 という条件式も不適切です。
敵と弾の「どちらか」が存在「しないこと」を条件に当たり判定をする、というのはおかしいですね。
敵と弾「両方」が存在「する」ときのみ当たり判定をするべきです。
ついでに、敵か弾が無い枠が見つかったら
(当たったかにかかわらず) break; でループを抜ける、というのも不適切です。

最後に、弾についてはすでに変数 i でループをしているので、
その中でさらに変数 p でループをするのは無駄でしょう。

これらを踏まえ、この部分はこうするといいでしょう。

コード:

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++)
		{
				if (Teki1Flag[a] != 0)
				{
					if (((JikiTamaX[i] > Teki1X[a] && JikiTamaX[i] < Teki1X[a] + Teki1W) ||
						(Teki1X[a] > JikiTamaX[i] && Teki1X[a] < JikiTamaX[i] + TamaW)) &&
						((JikiTamaY[i] > Teki1Y[a] && JikiTamaY[i] < Teki1Y[a] + Teki1H) ||
							(Teki1Y[a] > JikiTamaY[i] && Teki1Y[a] < JikiTamaY[i] + TamaH)))
					{
						// 接触している
						Teki1Flag[a] = 0;
					}
				}
			}
		}
		// 画面外に出てしまった場合は存在状態を保持している変数に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);
	}
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: 公式のDXライブラリを見ながら当たり判定を実装しようとしているのですが。。。。。。

#5

投稿記事 by cupa » 2年前

わかりました。頑張って直してみます、、、、時間かかるかもしれませんが、、、

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

Re: 公式のDXライブラリを見ながら当たり判定を実装しようとしているのですが。。。。。。

#6

投稿記事 by cupa » 2年前

自分なりに直してみたのですが、配列を走査の違うやり方というのがわからず、フリーズは治ったもののやはり変わりません。(breakやif文、-1の代入などは直したつもりです。)
何しろ初めてのゲームなのでどこが悪いのかが経験上ないのでわからないのが辛いです、、、

ちょっと直してみたコード

コード:

#define WORLD_WIDTH 640
#define WORLD_HEIGHT 480
#define Tama 500
#define TEKI_MAX 50

#include "DxLib.h"

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

	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;
	int TekiCount;


	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;
	}

	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");
	TekiCount = 0;

	// 弾のグラフィックのサイズをえる
	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);
			}
			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 = 0;
						
							if (Teki1Flag[a] != 1 && 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)))
								{
									// 接触している
									Teki1Flag[a] = 0;
									JikiTamaFlag[p] = 0;
								}
								else {
								
									break;

								}

								j = a;
								i = p;
							}
					}
					// 画面外に出てしまった場合は存在状態を保持している変数に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) // 空いている場所を見つけたら
					{
						// j = t; // その添字をiに設定

						//int TekiPattern = GetRand(WORLD_WIDTH); // パターンではなく、発生する敵の X 座標

						//Teki1X[i] = TekiPattern;
						Teki1X[t] = GetRand(WORLD_WIDTH);

						//Teki1Y[j] += 3;

						Teki1Y[t] = -64;

						Teki1Flag[t] = 1;
						// DrawGraph(Teki1X[j], Teki1Y[j], Teki1Graph, true);

						break;
					}
				}
				//int TekiPattern = GetRand(640);

				//Teki1X[j] = TekiPattern;

				//Teki1Y[j] += 3;

				//DrawGraph(Teki1X[j], Teki1Y[j], Teki1Graph, true);
			}

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

					Teki1Y[j] += 3;

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

			

			

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


		}
		ScreenFlip();

	}


	DxLib_End();

	return 0;
}
↑ 全体のコード

↓ 直した部分のコード

コード:

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 = 0;
						
							if (Teki1Flag[a] != 1 && 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)))
								{
									// 接触している
									Teki1Flag[a] = 0;
									JikiTamaFlag[p] = 0;
								}
								else {
								
									break;

								}

								j = a;
								i = p;
							}
					}
よろしくおねがいします、、、

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

Re: 公式のDXライブラリを見ながら当たり判定を実装しようとしているのですが。。。。。。

#7

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

・pの値を0で固定しており、最初の要素以外の弾についての判定をしていない
・敵と弾の両方が「存在する」とき判定をするべきなのに、「存在しない」とき判定をするようになっている
・敵と弾の存在(しない)判定の通過後、接触していないと判定した時、不適切にbreak;で判定処理を打ち切っている
・敵と弾の存在(しない)判定の通過後、接触していると判定したとき、iの値を不適切に設定している

↓直したコード

コード:

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)))
								{
									// 接触している
									Teki1Flag[a] = 0;
									JikiTamaFlag[p] = 0;
								}
							}
					}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: 公式のDXライブラリを見ながら当たり判定を実装しようとしているのですが。。。。。。

#8

投稿記事 by cupa » 2年前

ありがとうございます!!できました!
まだまだ間違えている所ありましたね、、、いつもありがとうございます!

返信

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