C/C++縦スクロールゲーム

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

C/C++縦スクロールゲーム

#1

投稿記事 by samusu0905 » 10年前

C/C++で縦スクロールゲームを作ってます。そこでですが、敵の数をループさせる処理をしたいのですが、
敵の数は複数発生してはいるものの、敵の数がループしてくれなくて困ってます。
ここにコードを載せます

コード:

//発生-------------------------------------------------------------------------------------
void EnemySet(void)
{
	int i;

	for(i=0; i<ENEMY1_MAX; i++)
	{
		//敵が存在していなければ
		if(gEnemy1[i].flg == OFF)
		{
			EnemySetOne(i);			//発生の実施を行う
		}
	}
}


//発生の実施--------------------------------------------------------------------------
void EnemySetOne(int i)
{
  for(i=0; i<ENEMY1_MAX; i++)
  {
	if(rand()%40 == 0)
	{
		gEnemy1[i].flg = ON;
		gEnemy1[i].y = 0;                           //Y座標を設定
		gEnemy1[i].x = rand()%GS_WINDOW_WIDTH;      //X座標を設定

		if( rand()%2 == 0)
		{
		gEnemy1[i].dir = 2;      //右向き
		}else
		{
		gEnemy1[i].dir = -2;    //左向き
		}
	}
  }
}
こんな感じのコードです。
付けたし・間違い等々あればよろしくお願いします。
最後に編集したユーザー 御津凪 on 2014年3月20日(木) 03:00 [ 編集 1 回目 ]
理由: コードタグがミスしていたので直しました

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: C/C++縦スクロールゲーム

#2

投稿記事 by softya(ソフト屋) » 10年前

存在していなければとガードをしているにもかかわらずEnemySetOne()で無条件に全キャラを再発生させています。
これが原因ではないでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: C/C++縦スクロールゲーム

#3

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

「敵の数をループさせる処理」とは、具体的にどのような処理でしょうか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

samusu0905
記事: 336
登録日時: 10年前

Re: C/C++縦スクロールゲーム

#4

投稿記事 by samusu0905 » 10年前

敵を10体発生させた後、for文で敵の数10体を無限ループさせる処理です。

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

Re: C/C++縦スクロールゲーム

#5

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

samusu0905 さんが書きました:敵を10体発生させた後、for文で敵の数10体を無限ループさせる処理です。
ごめんなさい。まだ私には意味がよくわかりません。
「敵の数を無限ループさせる」とはどういうことですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

samusu0905
記事: 336
登録日時: 10年前

Re: C/C++縦スクロールゲーム

#6

投稿記事 by samusu0905 » 10年前

プログラムに間違いがあれば、正しいプログラムを書いていただくとありがたいです。
お願いします。

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

Re: C/C++縦スクロールゲーム

#7

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

samusu0905 さんが書きました:プログラムに間違いがあれば、正しいプログラムを書いていただくとありがたいです。
お願いします。
提示されている範囲では定義されていない変数や定数がある以外、文法エラーは無さそうです。
仕様がわからなければ、「間違いがある」かどうかは判定できません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Ryo

Re: C/C++縦スクロールゲーム

#8

投稿記事 by Ryo » 10年前

18行目で、iを引数にして値をもらっているのに
20行目でi=0としているのは、何を意図しているのでしょうか?

samusu0905
記事: 336
登録日時: 10年前

Re: C/C++縦スクロールゲーム

#9

投稿記事 by samusu0905 » 10年前

敵の数を無限ループさせるのですから、敵の数を無限に発生させるということです。

samusu0905
記事: 336
登録日時: 10年前

Re: C/C++縦スクロールゲーム

#10

投稿記事 by samusu0905 » 10年前

ああ、EnemySetOne(int i)
for(i=0; i<ENEMY1_MAX; i++)
ここの部分ですか?
ここはただの間違いだと思います。
さっき、直しました。
直したコード載せます。

コード:

//発生-------------------------------------------------------------------------------------
void EnemySet(void)
{
	int i;

	for(i=0; i<ENEMY1_MAX; i++)
	{
		if(gEnemy1[i].flg == OFF)
		{
			EnemySetOne(i);			//発生の実施を行う
		}
	}
}


//発生の実施--------------------------------------------------------------------------
void EnemySetOne(int i)
{
	if(rand()%50 == 0)
	{
		gEnemy1[i].flg = ON;
		gEnemy1[i].y = GS_WINDOW_HEIGHT;            //Y座標を設定
		gEnemy1[i].y = rand()%-1;
		gEnemy1[i].x = rand()%GS_WINDOW_WIDTH;      //X座標を設定

		if( rand()%2 == 0)
		{
		gEnemy1[i].dir = 2;      //右向き
		}
		else
		{
		gEnemy1[i].dir = -2;    //左向き
		}
	}
}
[code]

修正しました。敵は複数発生しますが、ループして発生してくれないんです。
多分自分でもどこか間違いがあると思いますが、色々とやっても中々思いつきませんでした;;

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

Re: C/C++縦スクロールゲーム

#11

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

このコードの中には「10体」という条件は含まれていませんね。
EnemySetをどのようなタイミングで呼んでいるかもわからないですが、
まずこれを「敵をn体発生させる」という処理に書き換えますか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

samusu0905
記事: 336
登録日時: 10年前

Re: C/C++縦スクロールゲーム

#12

投稿記事 by samusu0905 » 10年前

はい、お願いします。

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

Re: C/C++縦スクロールゲーム

#13

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

1. 空いている(gEnemy1.flg == OFFである)添字iのリスト(配列)を作る
2-1. 空いている添字がn個以下なら、それら全てに対して敵を発生させる
2-2. 空いている添字がn個を超えるなら、1で作ったリストをシャッフルして、最初のn個の添字に対して敵を発生させる
という方針でいいと思います。
そのために、EnemySetOneを呼んだら必ず敵が発生するようにしましょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: C/C++縦スクロールゲーム

#14

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

書いてみました。
よく考えたら、シャッフルしなくてもいいかもしれませんね。

コード:

//発生-------------------------------------------------------------------------------------
void EnemySet(int n)
{
	int i;
	int emptyIndexList[ENEMY1_MAX];
	int emptyIndexCount=0;

	for(i=0; i<ENEMY1_MAX; i++)
	{
		if(gEnemy1[i].flg == OFF)
		{
			enptyIndexList[emptyIndexCount++]=i; //空きの場所を登録する
		}
	}
	if(emptyIndexCount<=n)
	{
		n=emptyIndexCount;
	}
	else
	{
		//シャッフルを行う
		for(i=emptyIndexCount-1; i>0; i--)
		{
			int pos=rand()%(i+1);
			int tmp=emptyIndexList[i];
			emptyIndexList[i]=emptyIndexList[pos];
			emptyIndexList[pos]=tmp;
		}
	}
	for(i=0; i<n; i++)
	{
		EnemySetOne(emptyIndexList[i]); //発生の実施を行う
	}
}


//発生の実施--------------------------------------------------------------------------
void EnemySetOne(int i)
{
	gEnemy1[i].flg = ON;
	gEnemy1[i].y = GS_WINDOW_HEIGHT; //Y座標を設定
	gEnemy1[i].y = rand()%-1;
	gEnemy1[i].x = rand()%GS_WINDOW_WIDTH; //X座標を設定

	if( rand()%2 == 0)
	{
		gEnemy1[i].dir = 2; //右向き
	}
	else
	{
		gEnemy1[i].dir = -2; //左向き
	}
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

N.R

Re: C/C++縦スクロールゲーム

#15

投稿記事 by N.R » 10年前

想像するなら
EnemySet() を毎フレーム呼んで敵が死ぬとすぐに発生するようにしているのを「敵の数を無限に発生」と言っているのではないでしょうか

if( rand()%50 == 0 )
の意図がいまひとつ分かりませんが
いきなり再生するのもなんなので、少し時間が空くのを期待した処理という所でしょうか

samusu0905
記事: 336
登録日時: 10年前

Re: C/C++縦スクロールゲーム

#16

投稿記事 by samusu0905 » 10年前

上記のプログラムを参考に書きましたが、正常に動いたと思ったら、プレイ画面でエラーがでました。
敵は発生したものの、プレイ画面に移動して直ぐにゲームが止まってしまいました;;
ENEMY1_MAXなんですが、このプログラムで、この関数は敵の数が10体定義されています。
ですから、int nは定義不要だと思います。

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

Re: C/C++縦スクロールゲーム

#17

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

samusu0905 さんが書きました:上記のプログラムを参考に書きましたが、正常に動いたと思ったら、プレイ画面でエラーがでました。
敵は発生したものの、プレイ画面に移動して直ぐにゲームが止まってしまいました;;
テストしていないので、自分のプログラムにバグがあったかもしれません。
…と思ったら、「参考に書きました」ですか。では、そのプログラムを貼っていただけますか?
samusu0905 さんが書きました:ENEMY1_MAXなんですが、このプログラムで、この関数は敵の数が10体定義されています。
ですから、int nは定義不要だと思います。
では、「EnemySet関数を呼んだら必ず発生させられるだけ敵を発生させる」という仕様でいいですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

samusu0905
記事: 336
登録日時: 10年前

Re: C/C++縦スクロールゲーム

#18

投稿記事 by samusu0905 » 10年前

はい、それで構いません。お願いします。

samusu0905
記事: 336
登録日時: 10年前

Re: C/C++縦スクロールゲーム

#19

投稿記事 by samusu0905 » 10年前

さっきのプログラムですが、参考と言ってもほとんど同じように書いて、少し変えて書き込んだだけです。
変えた場所は、 int nとなっているところをvoidのままにして、nを使っているところをENMEY1_MAXに変えたりした
だけです。n個って言いましたよね?あれはこのプログラムでは多分不要かと思います。さっきまでの文章にも書きましたが、ENEMY1_MAXが敵の数が10体であることを他のヘッダファイルで定義されているので、
nは書かなくても問題ないかと思います。色々と世話を焼かせて申し訳ございません。

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

Re: C/C++縦スクロールゲーム

#20

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

では、とりあえずシンプルにこれでいいと思います。

コード:

//発生-------------------------------------------------------------------------------------
void EnemySet(void)
{
	int i;

	for(i=0; i<ENEMY1_MAX; i++)
	{
		if(gEnemy1[i].flg == OFF)
		{
			EnemySetOne(i); //発生の実施を行う
		}
	}
}


//発生の実施--------------------------------------------------------------------------
void EnemySetOne(int i)
{
	gEnemy1[i].flg = ON;
	gEnemy1[i].y = 0; //Y座標を設定
	gEnemy1[i].x = rand()%GS_WINDOW_WIDTH; //X座標を設定

	if( rand()%2 == 0)
	{
		gEnemy1[i].dir = 2; //右向き
	}
	else
	{
		gEnemy1[i].dir = -2; //左向き
	}
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

samusu0905
記事: 336
登録日時: 10年前

Re: C/C++縦スクロールゲーム

#21

投稿記事 by samusu0905 » 10年前

[EnemySet関数を呼んだら必ず発生させられるだけ敵を発生させ、敵の数の分だけループさせる]という処理にできればしてもらえませんか? [敵の数の分だけループさせる]ということですから、敵10体をループして発生させるという処理をできればお願いします。わがまま言ってすみません。

samusu0905
記事: 336
登録日時: 10年前

Re: C/C++縦スクロールゲーム

#22

投稿記事 by samusu0905 » 10年前

上記のプログラムは以前、僕が書いたプログラムと同じですよ。結果は発生してもループしませんでした。

アバター
usao
記事: 1887
登録日時: 11年前

Re: C/C++縦スクロールゲーム

#23

投稿記事 by usao » 10年前

No20のコードにはとりあえずループが存在しているわけですが,それに対して
>ループしませんでした
とのことですから,
あなたの言う「ループ」とは,それとはまったく違うものであるということですよね.
だとしたら,(最初に説明を求められて,うやむやになってる感のある)
>敵の数をループ
という言葉の真の意味が,おそらく誰にも伝わってないものと推測します.

まず,自分にしか通じない言葉を繰り返すのをやめて
まともな日本語で説明するところから初めてみてはいかがでしょうか.
「数をループ」とは何か,
一体あなたは何を観測して「ループしていない」と言っているのか,
全体として何をしたいのか.

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

Re: C/C++縦スクロールゲーム

#24

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

EnemySetを呼んでいる部分のソースコードは提示できますか?
可能であれば提示していただけるとありがたいです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

samusu0905
記事: 336
登録日時: 10年前

Re: C/C++縦スクロールゲーム

#25

投稿記事 by samusu0905 » 10年前

敵10体を単純に無限ループさせたいだけです。[ループしていない]というのは、つまり敵が10体発生していて、
それがfor文によってループされていないということです。 まともな日本語で説明できていなくてすみませんでした。

samusu0905
記事: 336
登録日時: 10年前

Re: C/C++縦スクロールゲーム

#26

投稿記事 by samusu0905 » 10年前

コード:

//メイン処理-------------------------------------------------------------------------
void GamePlayMain(void)
{
	//各ファイルのメイン処理
	DragonMain();
	FireMain();
	EnemyMain();
	CollisionMain();


	if( gDragonLife.HP <= 0)
	{
		gSceneMode = MODE_GAMEOVER;
		gsStopSound( sGamePlayBGM1);
		return;
	}
}
[code]
ここで呼んでいます。ゲームプレイのコードの部分です。

そして先ほどのコードがこれです。一応、敵のソースコードを全部提示します↓ 
そうすればわかりやすいですか?
[code]
//*******************************************************************
//  敵処理
//*******************************************************************
#include <stdio.h>			//C言語
#include "gs.h"				//学内ライブラリィ
#include "def.h"			//共通定義
#include "Enemy.h"			//敵


//宣言--------------------------------------------
OBJ  gEnemy1[ENEMY1_MAX];				//敵1の構造体

//参照--------------------------------------------
extern gsTexture sEnemy1;	//敵
extern int gScore;			//スコア


//開始-----------------------------------------------------------------------------
void EnemyStart(void)
{
	int i;

	//敵の数ループ
	for(i=0; i<ENEMY1_MAX; i++)
	{
		gEnemy1[i].flg = OFF;			//存在しない(初期設定)
	}
}


//メイン処理------------------------------------------------------------------------
void EnemyMain(void)
{
	EnemySet();					//発生
	EnemyMove();				//移動
	EnemyInScreen();			//移動範囲の制限
}


//表示------------------------------------------------------------------------------------
void EnemyDraw(void)
{
	int i;

	//敵の数ループ
	for(i=0; i<ENEMY1_MAX; i++)
	{
		//存在すれば
		if( gEnemy1[i].flg == ON)
		{
			gsDraw2D( sEnemy1, gEnemy1[i].x, gEnemy1[i].y );			//敵
		}
	}
}


//発生-------------------------------------------------------------------------------------
void EnemySet(void)
{
	int i;

	for(i=0; i<ENEMY1_MAX; i++)
	{
		//敵が存在していなければ
		if(gEnemy1[i].flg == OFF)
		{
			gEnemy1[i].flg = ON;
			
			EnemySetOne(i);			//発生の実施を行う
		}
	}
}


//発生の実施--------------------------------------------------------------------------
void EnemySetOne(int i)
{
	if(rand()%50 == 0)
	{
		gEnemy1[i].flg = ON;
		gEnemy1[i].y = GS_WINDOW_HEIGHT;            //Y座標を設定
		gEnemy1[i].y = rand()%-1;
		gEnemy1[i].x = rand()%GS_WINDOW_WIDTH;      //X座標を設定
	}


	if( rand()%2 == 0)
	{
		gEnemy1[i].dir = 2;      //右向き
	}
	else
	{
		gEnemy1[i].dir = -2;    //左向き
	}
}


//移動--------------------------------------------------------------------------------
void EnemyMove(void)
{
	int i;

	//敵1の数ループ
	for(i=0; i<ENEMY1_MAX; i++)
	{
		if( gEnemy1[i].flg == ON)
		{
			gEnemy1[i].y += 2;							//下に移動
			if( gEnemy1[i].y >= 350)
			{
				gEnemy1[i].x += gEnemy1[i].dir;			//左右に移動
			}
		}
	}
}


//移動範囲の制限----------------------------------------------------------------------------
void EnemyInScreen(void)
{
	int i;

	//敵1の数ループ
	for(i=0; i<ENEMY1_MAX; i++)
	{
		//存在すれば
		if( gEnemy1[i].flg == ON)
		{
			EnemyInScreenOne(i);		//移動範囲の制限の実施
		}
	}
}


//移動範囲の制限の実施----------------------------------------------------------------------
void EnemyInScreenOne(int i)
{
	if( gEnemy1[i].flg == ON)
	{
		//下向き
		if(gEnemy1[i].y < -ENEMY1_YSIZE)
		{
			gEnemy1[i].flg = OFF;		//存在しなくする
		}

		//右向き
		if( gEnemy1[i].x < 20)
		{
			gEnemy1[i].dir = 3;
		}

		//左向き
		if( gEnemy1[i].x > 330)
		{
			gEnemy1[i].dir = -3;
		}

	}
}
[code]
長いですが、こんな感じです。

samusu0905
記事: 336
登録日時: 10年前

Re: C/C++縦スクロールゲーム

#27

投稿記事 by samusu0905 » 10年前

インデントがわかりずらいですね;; 見えずらくてすみません。

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

Re: C/C++縦スクロールゲーム

#28

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

samusu0905 さんが書きました:敵10体を単純に無限ループさせたいだけです。[ループしていない]というのは、つまり敵が10体発生していて、
それがfor文によってループされていないということです。 まともな日本語で説明できていなくてすみませんでした。
「敵の数を無限ループさせたい」から「敵を無限ループさせたい」に言い直されたようですが、
申し訳ありませんがまだ私には理解できません。
こんな感じでしょうか?

コード:

//メイン処理------------------------------------------------------------------------
void EnemyMain(void)
{
	for(;;){
		EnemySet();					//発生
		EnemyMove();				//移動
		EnemyInScreen();			//移動範囲の制限
	}
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: C/C++縦スクロールゲーム

#29

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

samusu0905 さんが書きました:インデントがわかりずらいですね;; 見えずらくてすみません。
インデント自体はわかりやすいので、BBcodeを有効にした状態できちんとcodeタグで囲んでください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

samusu0905
記事: 336
登録日時: 10年前

Re: C/C++縦スクロールゲーム

#30

投稿記事 by samusu0905 » 10年前

[敵10体を無限に発生させたい]とでも言えばわかりますか?

hide

Re: C/C++縦スクロールゲーム

#31

投稿記事 by hide » 10年前

samusu0905 さんが書きました:敵10体を単純に無限ループさせたいだけです。[ループしていない]というのは、つまり敵が10体発生していて、
それがfor文によってループされていないということです。 まともな日本語で説明できていなくてすみませんでした。
○○をループする と書くときは大抵○○には何らかの処理が入るはずだと思います。
例 変数aに1を足す処理をループする。
で、敵という単語は処理では無いので、敵をループでは伝わらないのですよ。

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

Re: C/C++縦スクロールゲーム

#32

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

samusu0905 さんが書きました:[敵10体を無限に発生させたい]とでも言えばわかりますか?
わかった気がします。
EnemyInScreenOne関数、141行目の条件式が怪しいと思います。
他に敵の消滅条件が無ければ、敵は(gEnemy1.yの型によって、事実上または本当に)消滅することはありません。

ENEMY1_YSIZEが正の整数であると仮定した場合、
事実上:gEnemy1.yの型が例えばintの場合、オーバーフローして負の値になれば消滅します。
本当に:gEnemy1.yの型が例えばunsigned intの場合、gEnemy1.yは常に0以上なので消滅することはありません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

N.R

Re: C/C++縦スクロールゲーム

#33

投稿記事 by N.R » 10年前

要約すると

画面上に敵が最大10体まで発生する
敵が画面外に出ると消滅
消滅した敵はすぐに再発生する
という仕様で

結果は
敵が再発生せず
最初に発生させた10体が消滅すると全ていなくなってしまう <- 敵がループしない

という事ですかね

samusu0905
記事: 336
登録日時: 10年前

Re: C/C++縦スクロールゲーム

#34

投稿記事 by samusu0905 » 10年前

はい、そのとおりです。
説明不足で本当にすみませんでした。
もっとちゃんとした説明をします。
N.Rさんの言うとおりです。画面上に敵が最大10体まで発生して、敵が画面の下に移動して画面から消滅したらまた画面上から発生する処理がしたかったんです。
あれですかね、やはり移動範囲が可笑しかったですかね?

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

Re: C/C++縦スクロールゲーム

#35

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

予想ですが、

コード:

		if(gEnemy1[i].y < -ENEMY1_YSIZE)
という行(141行目)を、

コード:

		if(gEnemy1[i].y > GS_WINDOW_HEIGHT+ENEMY1_YSIZE)
としてみてください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

samusu0905
記事: 336
登録日時: 10年前

Re: C/C++縦スクロールゲーム

#36

投稿記事 by samusu0905 » 10年前

移動範囲の制限実施のところを自分なりに工夫したらループできました!!
色々と教えていただき有難うございました^^
これからはもっと説明を分かりやすくします。

閉鎖

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