龍神録11章で躓いています。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
クールアイス

龍神録11章で躓いています。

#1

投稿記事 by クールアイス » 13年前

OS : Windows 7
コンパイラ名 : Microsoft Visual C++ 2010 Express

現在、[龍神録プログラミングの館]を独学で勉強中のc++を用いて書いてみようと頑張っています。
しかし、11章の[エクセルを使って敵の出現データを作ってみよう]で躓いてしまっています。
エラーは出ていないのですが、敵が一切出て来ず、それ以外のプレイヤーなどの処理は出来ているようです。
その為何が原因なのかさっぱりわかりません。

私の現在の技術は、[ロベールのc++入門講座]のクラスの説明に入ったところ当たりまでギリギリわかる程度です。
もしよろしければご回答お願いします。

以下コード

enemy.cpp

コード:

#include"Global.h"

//----------------------------------------------
//	行動パターン0
//----------------------------------------------
void EnemyPattern0(int i)
{
	int t = enemy[i].cnt;

	if(t == 0)
		enemy[i].vy = 2;	//	下がってくる
	if(t == 60)
		enemy[i].vy = 0;	//	停止

	//	登録された時間だけ停滞
	if(t == 60 + enemy[i].wait)
		enemy[i].vy = -2;	//	上昇
}

//----------------------------------------------
//	空いている敵番号検索
//----------------------------------------------
int EnemySearch()
{
	for(int i = 0; i < ENEMY_MAX; ++i)
	{
		if(enemy[i].flag == 0)
			return i;	//	空いている敵番号を返す		
	}

	return -1;	//	全部埋まっていたらエラー
}

//----------------------------------------------
//	敵データの登録
//----------------------------------------------
void EnemyEnter()
{
	int i;

	for(int t = 0; t < ENEMY_ORDER_MAX; ++t)
	{
		//	ゲーム時間がオーダーの瞬間なら
		if(enemyOrder[t].cnt == stageCount)
		{
			//	敵が空いていたら
			if((i = EnemySearch()) != -1)
			{
				enemy[i].flag		= 1;					//	フラグ 
				enemy[i].cnt		= 0;					//	カウンタ
				enemy[i].muki		= 1;					//	向き
				enemy[i].vx			= 0;					//	水平成分の速度
				enemy[i].vy			= 0;					//	鉛直成分の速度
				enemy[i].ang		= 0;					//	角度
				enemy[i].pattern	= enemyOrder[t].pattern;//	移動パターン
				enemy[i].knd		= enemyOrder[t].knd;	//	種類
				enemy[i].x			= enemyOrder[t].x;		//	座標x
				enemy[i].y			= enemyOrder[t].y;		//	座標y
				enemy[i].sp			= enemyOrder[t].sp;		//	スピード
				enemy[i].bltime		= enemyOrder[t].bltime;	//	弾の発射時間
				enemy[i].blknd		= enemyOrder[t].blknd;	//	弾幕の種類
				enemy[i].blknd2		= enemyOrder[t].blknd2;	//	弾の種類
				enemy[i].col		= enemyOrder[t].col;	//	色
				enemy[i].wait		= enemyOrder[t].wait;	//	停滞時間
				enemy[i].hp			= enemyOrder[t].hp;		//	体力
				enemy[i].hpMax		= enemy[i].hp;			//	体力最大値

				for(int j = 0; j < 6; ++j)
					enemy[i].itemNum[j] = enemyOrder[t].itemNum[j];//	アイテム
			}
		}
	}
}

//----------------------------------------------
//	敵の演算
//----------------------------------------------
void CalcEnemy()
{
	for(int i = 0; i < ENEMY_MAX; ++i)
	{
		//	フラグが立ったら
		if(enemy[i].flag == 1)
		{
			EnemyPattern0(i);	//	行動パターン0
			
			enemy[i].x += cos(enemy[i].ang) * enemy[i].sp;				//	移動角度
			enemy[i].y += sin(enemy[i].ang) * enemy[i].sp;
			enemy[i].x += enemy[i].vx;									//	移動
			enemy[i].x += enemy[i].vy;
			enemy[i].cnt++;												//	カウンタ
			enemy[i].img = enemy[i].muki * 3 + (enemy[i].cnt % 18) / 6;	//	アニメーション
			
			//	画面外で消去
			if(enemy[i].x < -20 || FIELD_MAX_X + 20 < enemy[i].x || 
				enemy[i].y < -20 || FIELD_MAX_Y + 20 < enemy[i].y)
                enemy[i].flag = 0;
		}
	}
}

//----------------------------------------------
//	敵のメイン処理
//----------------------------------------------
void EnemyMain()
{
	EnemyEnter();	//	敵データの登録
	CalcEnemy();	//	敵の演算
}
load.cpp

コード:

/*
	読み込み制御
*/

#include"Global.h"

//----------------------------------------------
//	読み込み
//----------------------------------------------
void Load()
{
	//	ボード
	boardImg[10] = LoadGraph("dat/img/board/10.png");
	boardImg[11] = LoadGraph("dat/img/board/11.png");
	boardImg[12] = LoadGraph("dat/img/board/12.png");
	boardImg[20] = LoadGraph("dat/img/board/20.png");
	
	//	プレイヤー
	LoadDivGraph("dat/img/char/0.png", 12, 4, 3, 73, 73, playerImg[0]);

	//	敵
	LoadDivGraph("dat/img/enemy/0.png", 9, 3, 3, 32, 32, enemyImg[0]);
}

//----------------------------------------------
//	敵情報をcsvで読み込んで格納
//----------------------------------------------
void LoadStory()
{
	int n,num,fp;
	char fname[32] = {"dat/csv/storyH0.csv"};
	int input[64];
	char inputc[64];

	//	ファイル読み込み
	fp = FileRead_open(fname);

	//	読み込み失敗
	if(fp == NULL)
	{
		printfDx("read error\n");
		return;
	}

	//	最初の2行だけ読み飛ばし
	for(int i = 0; i < 2; ++i)
		while(FileRead_getc(fp) != '\n');	//	改行まで1文字ずつ読み出し

	n = 0;
	num = 0;

	while(true)
	{
		for(int i = 0; i < 64; ++i)
		{
			//	1文字取得
			inputc[i] = input[i] = FileRead_getc(fp);

			//	スラッシュがあれば
			if(inputc[i] == '/')
			{
				//	改行まで1文字ずつ読み出し
				while(FileRead_getc(fp) != '\n');
				i = -1;	//	カウンタを最初に戻す
				continue;
			}

			//	カンマか改行なら
			if(input[i] == ',' || input[i] == '\n')
			{
				inputc[i] = '\0';	//	そこまでを文字列にする
				break;
			}

			//	ファイルの終わりなら
			if(input[i] == EOF)
			{
				goto EXFILE;	//	終了
			}
		}

		switch(num)
		{
			case 0: enemyOrder[n].cnt		=atoi(inputc);break;
			case 1: enemyOrder[n].pattern	=atoi(inputc);break;
			case 2: enemyOrder[n].knd		=atoi(inputc);break;
			case 3: enemyOrder[n].x			=atof(inputc);break;
			case 4: enemyOrder[n].y			=atof(inputc);break;
			case 5: enemyOrder[n].sp		=atof(inputc);break;
			case 6: enemyOrder[n].bltime	=atoi(inputc);break;
			case 7: enemyOrder[n].blknd		=atoi(inputc);break;
			case 8: enemyOrder[n].col		=atoi(inputc);break;
			case 9: enemyOrder[n].hp		=atoi(inputc);break;
			case 10:enemyOrder[n].blknd2	=atoi(inputc);break;
			case 11:enemyOrder[n].wait		=atoi(inputc);break;
			case 12:enemyOrder[n].itemNum[0]=atoi(inputc);break;
			case 13:enemyOrder[n].itemNum[1]=atoi(inputc);break;
			case 14:enemyOrder[n].itemNum[2]=atoi(inputc);break;
			case 15:enemyOrder[n].itemNum[3]=atoi(inputc);break;
			case 16:enemyOrder[n].itemNum[4]=atoi(inputc);break;
			case 17:enemyOrder[n].itemNum[5]=atoi(inputc);break;
		}
		num++;

		if(num == 18)
		{
			num = 0;
			n++;
		}
	}
EXFILE:
	FileRead_close(fp);	//	ファイルを閉じる
}
class.h

コード:

/*
	Class宣言
*/

//	プレイヤークラス
class Player
{
public:

	int flag;		//	フラグ
	int cnt;		//	カウンタ
	int power;		//	パワー
	int point;		//	ポイント
	int score;		//	スコア
	int num;		//	残機数
	int mutekiCnt;	//	無敵状態とカウント
	int shotMode;	//	ショットモード
	int money;		//	お金
	int img;		//	画像
	int slow;		//	スローかどうか
	double x,y;		//	座標x,y

public:
	
	Player()//	コンストラクタ
	:	flag()
	,	cnt()
	,	power()
	,	point()
	,	score()
	,	num()
	,	mutekiCnt()
	,	shotMode()
	,	money()
	,	img()
	,	slow()

	,	x()
	,	y()
	{}
};

//	敵クラス
class Enemy
{
public:

	int flag;		//	フラグ
	int cnt;		//	カウンタ
	int pattern;	//	移動パターン
	int muki;		//	向き
	int knd;		//	種類
	int hp;			//	体力
	int hpMax;		//	最大体力
	int itemNum[6];	//	アイテム
	int img;		//	画像

	double x,y;		//	座標x,y
	double vx,vy;	//	速度成分x,速度成分y
	double sp;		//	スピード
	double ang;	//	角度

	int bltime;		//	弾幕開始時間
	int blknd;		//	弾幕の種類
	int blknd2;		//	弾の種類
	int col;		//	色
	int state;		//	弾の状態
	int wtime;		//	出現までの待機時間
	int wait;		//	フィールドでの停滞時間

public:

	Enemy()//	コンストラクタ
	:	flag()
	,	cnt()
	,	pattern()
	,	muki()
	,	knd()
	,	hp()
	,	hpMax()
	,	itemNum()
	,	img()

	,	x()
	,	y()
	,	vx()
	,	vy()
	,	sp()
	,	ang()

	,	bltime()
	,	blknd()
	,	blknd2()
	,	col()
	,	state()
	,	wtime()
	,	wait()
	{}
};

//	敵の呼び出しクラス
class EnemyOrder
{
public:

	int cnt;		//	カウンタ
	int pattern;	//	移動パターン
	int knd;		//	敵の種類
	double x,y;		//	座標x,y
	double sp;		//	スピード
	int bltime;		//	弾幕開始時間
	int blknd;		//	弾幕の種類
	int col;		//	色
	int hp;			//	体力
	int blknd2;		//	弾の種類
	int wait;		//	フィールドでの停滞時間
	int itemNum[6];	//	アイテム

public:

	EnemyOrder()//	コンストラクタ
	:	cnt()
	,	pattern()
	,	knd()
	,	x()
	,	y()
	,	sp()
	,	bltime()
	,	blknd()
	,	col()
	,	hp()
	,	blknd2()
	,	wait()
	,	itemNum()
	{}
	
};

//	パッドクラス
class Pad
{
public:
	int key[PAD_MAX];	//	パッドキー
};

//	コンフィグクラス
class Config
{
public:
	int left;	//	左
	int up;		//	上
	int right;	//	右
	int down;	//	下
	int shot;	//	ショット
	int bomb;	//	ボム
	int slow;	//	低速
	int start;	//	スタート
	int change;	//	返信
};
 

トントン
記事: 100
登録日時: 15年前

Re: 龍神録11章で躓いています。

#2

投稿記事 by トントン » 13年前

ごめんなさい、ソースはきちんと見てないです。。。
駄目そうならちゃんと見ます。

とりあえず、できそうなものだけで良いので以下を確認してみてください。

・各関数は、正常に呼ばれているか
・enemyのフラグは狙ったタイミング時に1になっているか
・enemyの演算時にはenemyの座標が画面内に収まっているか
・画像は正常に読み込めているのか

クールアイス

Re: 龍神録11章で躓いています。

#3

投稿記事 by クールアイス » 13年前

回答ありがとうございます。

<<各関数は、正常に呼ばれているか
<<enemyのフラグは狙ったタイミング時に1になっているか
<<enemyの演算時にはenemyの座標が画面内に収まっているか
<<画像は正常に読み込めているのか

これらの項目なのですが、確認するには「ブレークポイント」を使えばいいのでしょうか?
使うとしたら、どこに置けば必要な結果が見られるでしょうか。

初心者なもので、質問ばかりで申し訳ありません。

トントン
記事: 100
登録日時: 15年前

Re: 龍神録11章で躓いています。

#4

投稿記事 by トントン » 13年前

クールアイス さんが書きました:回答ありがとうございます。

<<各関数は、正常に呼ばれているか
<<enemyのフラグは狙ったタイミング時に1になっているか
<<enemyの演算時にはenemyの座標が画面内に収まっているか
<<画像は正常に読み込めているのか

これらの項目なのですが、確認するには「ブレークポイント」を使えばいいのでしょうか?
使うとしたら、どこに置けば必要な結果が見られるでしょうか。

初心者なもので、質問ばかりで申し訳ありません。
確認方法は何でもいいと思いますが
ブレークポイントでいいと思います。

>各関数は、正常に呼ばれているか
→ 宣言、定義だけでは使われていないのはわかりますね?
必ず、どこかで呼ばれているはずです。

>enemyのフラグは狙ったタイミング時に1になっているか
→セットしたタイミング、はたまた演算するときのタイミングで1になっているか。
  自分がここで、フラグをセットしている。使うタイミングはここだ!
  と思う箇所で確認してみてください。

>enemyの演算時にはenemyの座標が画面内に収まっているか
→ enemyの演算時でも良いですし、画面に出力するときでも良いです。
※追加 座標などの設定が確認ができたら実際にエクセルファイルと比較してみてもいいと思います。

>画像は正常に読み込めているのか
→ 実績にあるプログラムで同じパスを設定して画像が出力できるか確認してみても良いですし
  関数が正常、異常を返してくれるなら、それで確認してみてもいいと思います。

クールアイス

Re: 龍神録11章で躓いています。

#5

投稿記事 by クールアイス » 13年前

さっそくブレークポイントを使ってみました。
すると、

enemy.cpp

コード:

//----------------------------------------------
//	敵データの登録
//----------------------------------------------
void EnemyEnter()
{
	int i;

	for(int t = 0; t < ENEMY_ORDER_MAX; ++t)
	{
		//	ゲーム時間がオーダーの瞬間なら
		if(enemyOrder[t].cnt == stageCount)
		{
			//	敵が空いていたら
			if((i = EnemySearch()) != -1)
			{
				enemy[i].flag		= 1;					//	フラグ 
				enemy[i].cnt		= 0;					//	カウンタ
				enemy[i].muki		= 1;					//	向き
				enemy[i].vx			= 0;					//	水平成分の速度
				enemy[i].vy			= 0;					//	鉛直成分の速度
				enemy[i].ang		= 0;					//	角度
				enemy[i].pattern	= enemyOrder[t].pattern;//	移動パターン
				enemy[i].knd		= enemyOrder[t].knd;	//	種類
				enemy[i].x			= enemyOrder[t].x;		//	座標x
				enemy[i].y			= enemyOrder[t].y;		//	座標y
				enemy[i].sp			= enemyOrder[t].sp;		//	スピード
				enemy[i].bltime		= enemyOrder[t].bltime;	//	弾の発射時間
				enemy[i].blknd		= enemyOrder[t].blknd;	//	弾幕の種類
				enemy[i].blknd2		= enemyOrder[t].blknd2;	//	弾の種類
				enemy[i].col		= enemyOrder[t].col;	//	色
				enemy[i].wait		= enemyOrder[t].wait;	//	停滞時間
				enemy[i].hp			= enemyOrder[t].hp;		//	体力
				enemy[i].hpMax		= enemy[i].hp;			//	体力最大値

				for(int j = 0; j < 6; ++j)
					enemy[i].itemNum[j] = enemyOrder[t].itemNum[j];//	アイテム
			}
		}
	}
}
の中の

コード:

//	敵が空いていたら
if((i = EnemySearch()) != -1)
の i がi = -858993460 というとんでもない数値になっていました。
ここがこんな数値になってしまうのは、この関数に原因があるのでしょうか・・・。

トントン
記事: 100
登録日時: 15年前

Re: 龍神録11章で躓いています。

#6

投稿記事 by トントン » 13年前

クールアイス さんが書きました:さっそくブレークポイントを使ってみました。

コード:

//	敵が空いていたら
if((i = EnemySearch()) != -1)
の i がi = -858993460 というとんでもない数値になっていました。
ここがこんな数値になってしまうのは、この関数に原因があるのでしょうか・・・。
if((i = EnemySearch()) != -1)の行で止めているせいだと思います。
次の行に進めて確認してみてください。

(ステップイン F11 ,ステップオーバー F10)

クールアイス

Re: 龍神録11章で躓いています。

#7

投稿記事 by クールアイス » 13年前

すいません・・・どうやらただの打ち間違いがあったようです。

原因は、

コード:

//----------------------------------------------
//	敵の演算
//----------------------------------------------
void CalcEnemy()
{
	for(int i = 0; i < ENEMY_MAX; ++i)
	{
		//	フラグが立ったら
		if(enemy[i].flag == 1)
		{
			EnemyPattern0(i);	//	行動パターン0
			
			enemy[i].x += cos(enemy[i].ang) * enemy[i].sp;				//	移動角度
			enemy[i].y += sin(enemy[i].ang) * enemy[i].sp;
			enemy[i].x += enemy[i].vx;									//	移動
			enemy[i].y += enemy[i].vy;
			enemy[i].cnt++;												//	カウンタ
			enemy[i].img = enemy[i].muki * 3 + (enemy[i].cnt % 18) / 6;	//	アニメーション
			
			//	画面外で消去
            if(enemy[i].x<-20 || FIELD_MAX_X+20<enemy[i].x || enemy[i].y<-20 || FIELD_MAX_Y+20<enemy[i].y)
                enemy[i].flag=0;
		}
	}
}
の中の移動成分を y ではなく x と書いてあったせいでした。
このコードは修正したもので、無事に動きました。
このようなミスで本当に申し訳ないです・・・。

しかし回答してくださったトントンさんのお陰で、プログラムのどこを見ればよいかが分かってきました。
本当にありがとうございました。

閉鎖

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