ページ 11

敵のショットが描画されない

Posted: 2014年11月16日(日) 23:29
by north
いつもご質問に答えていただきありがとうございます。
今回質問したいのは敵のショットの描画についてです。
龍神録の第13章を参考に敵のショットのプログラムを組んでみたのですが、敵の弾が描画されず、どのように修正したらよいかわからず
困っております。
一応デバッガを使ってみてみたところ敵の構造体を格納するEnemyInfoとプレイヤーの構造体を格納するPlayerInfoと弾の画像のハンドルを格納している
BulletImageが「エラーです。シンボルが見つかりません」「エラーです。式を評価できません」となっておりこれではないかなと思っております。
ただ、これがどのようにしたら修正できるのかがわかりません。
以下がコードとなります。

Bullet.h

コード:

#ifndef BULLETH
#define BULLETH

#include <stdio.h>
#include <string.h>
#include <iostream>
#include "DxLib.h"
#include "Enemy.h"
#include "Model.h"
using namespace std;

//敵1匹が持つ弾の最大数
#define SHOT_BULLET_MAX (1000)

//一度に画面に表示できる敵の弾幕の最大数
#define SHOT_MAX (30)

//ショットの種類の最大数
#define SHOT_KND_MAX (1)

//効果音の種類の最大数
#define SE_MAX (100)

class CBullet
{
public:
	//弾に関する構造体
	typedef struct
	{
		int Flag;
		int Kind;
		int Count;
		int Color;
		int State;
		int Till; //少なくとも消さない時間
		int Effect; //エフェクトの種類
		VECTOR Pos;
		float Angle;
		float Speed;
		float BaseAngle[1]; //ベースの角度
		float RemSpd; //一時記憶スピード

	}BULLET_PARAM;
	
	typedef struct
	{
		int Flag;
		int Kind;
		int Count;
		int Number;
		float BaseAngle[1]; //ベース角度
		float BaseSpeed[1]; //ベーススピード
		BULLET_PARAM tBullet[SHOT_BULLET_MAX];
	}SHOT_PARAM;
private:
	SHOT_PARAM tShot[SHOT_MAX];
	CEnemy::ENEMY_PARAM* EnemyInfo;
	CModel::PLAYER_PARAM PlayerInfo;
	int BulletImage[10][10]; //弾の画像
public:
	CBullet();
	~CBullet();
	void LoadBullet();
	void SetPlayerParam(CModel::PLAYER_PARAM player);
	void SetEnemyParam(CEnemy::ENEMY_PARAM* enemy);
	//空いている弾を探す
	int ShotSearch(int ShotNumber);
	//n番目のショットを登録した敵と自機との角度を返す
	float Shotatan2(int ShotNumber);
	void ShotMain();
	void ShotBulletPattern000(int ShotNumber);
	void ShotCalc(int ShotNumber);
	void DrawShot();
	void (CBullet::*ShotBulletPattern[SHOT_KND_MAX])(int);
};
#endif
Bullet.cpp

コード:

#include "Enemy.h"
#include "Bullet.h"

CBullet::CBullet()
{
	memset(tShot, 0, sizeof(SHOT_PARAM) * SHOT_MAX);
	for(int ii = 0; ii < SHOT_MAX; ii++)
	{
		for(int jj; jj < SHOT_BULLET_MAX; jj++)
		{
			tShot[ii].tBullet[jj].Pos.y = -280.0f;
		}
	}
	ShotBulletPattern[0] = &CBullet::ShotBulletPattern000;
}
CBullet::~CBullet()
{}
//----------------------------------------------------------------
void CBullet::LoadBullet()
{
	LoadDivGraph("./Bullet/b0.png" , 5 , 5 , 1 , 76 , 76 , BulletImage[0]) ;
    LoadDivGraph("./Bullet/b1.png" , 6 , 6 , 1 , 22 , 22 , BulletImage[1]) ;
    LoadDivGraph("./Bullet/b2.png" , 10 , 10 , 1 , 5 , 120 , BulletImage[2]) ;
    LoadDivGraph("./Bullet/b3.png" , 5 , 5 , 1 , 19 , 34 , BulletImage[3]) ;
    LoadDivGraph("./Bullet/b4.png" , 10 , 10 , 1 , 38 , 38 , BulletImage[4]) ;
    LoadDivGraph("./Bullet/b5.png" , 3 , 3 , 1 , 14 , 16 , BulletImage[5]) ;
    LoadDivGraph("./Bullet/b6.png" , 3 , 3 , 1 , 14 , 18 , BulletImage[6]) ;
    LoadDivGraph("./Bullet/b7.png" , 9 , 9 , 1 , 16 , 16 , BulletImage[7]) ;
    LoadDivGraph("./Bullet/b8.png" , 10 , 10 , 1 , 12 , 18 ,BulletImage[8]) ;
    LoadDivGraph("./Bullet/b9.png" , 3 , 3 , 1 , 13 , 19 , BulletImage[9]) ;
}
//----------------------------------------------------------------
void CBullet::SetEnemyParam(CEnemy::ENEMY_PARAM* enemy)
{
	EnemyInfo = enemy;
}
//----------------------------------------------------------------
void CBullet::SetPlayerParam(CModel::PLAYER_PARAM player)
{
	PlayerInfo = player;
}
//----------------------------------------------------------------
float CBullet::Shotatan2(int ShotNumber)
{
	return atan2(PlayerInfo.PlayerPos.z - EnemyInfo[tShot[ShotNumber].Number].Pos.z, PlayerInfo.PlayerPos.x - EnemyInfo[tShot[ShotNumber].Number].Pos.x);
}
//----------------------------------------------------------------
//空いている弾を探す
int CBullet::ShotSearch(int ShotNumber)
{
	for(int ii = 0; ii < SHOT_BULLET_MAX; ii++)
	{
		if(tShot[ShotNumber].tBullet[ii].Flag == 0)
		{
			return ii;
		}
	}
	return -1;
}
//----------------------------------------------------------------
void CBullet::ShotMain()
{
	for(int ii = 0; ii < SHOT_MAX; ii++)
	{
		//フラグが立っていて、設定した種類が間違っていなければ(オーバーフロー対策)
		if(tShot[ii].Flag != 0 && 0 <= tShot[ii].Kind && tShot[ii].Kind < SHOT_KND_MAX)
		{
			(this->*ShotBulletPattern[tShot[ii].Kind])(ii); //.kndの弾幕計算関数を呼ぶ関数ポインタ
			ShotCalc(ii); //ii番目の弾幕を計算
			tShot[ii].Count++;
		}
	}
}
	
//----------------------------------------------------------------
//1発だけ、自機に向かって直線移動
void CBullet::ShotBulletPattern000(int ShotNumber)
{
	int BulletNumber;
	if(tShot[ShotNumber].Count == 0) //弾幕が始まって0カウント目
	{
		//敵が倒されていなくて、探した登録可能な弾番号が有効なら
		if(tShot[ShotNumber].Flag != 2 && (BulletNumber = ShotSearch(ShotNumber)) != -1)
		{
			tShot[ShotNumber].tBullet[BulletNumber].Kind = EnemyInfo[tShot[ShotNumber].Number].BulletKind2;
			tShot[ShotNumber].tBullet[BulletNumber].Angle = Shotatan2(ShotNumber);
			tShot[ShotNumber].tBullet[BulletNumber].Flag = 1;
			tShot[ShotNumber].tBullet[BulletNumber].Pos.x = EnemyInfo[tShot[ShotNumber].Number].Pos.x;
			tShot[ShotNumber].tBullet[BulletNumber].Pos.z = EnemyInfo[tShot[ShotNumber].Number].Pos.z;
			tShot[ShotNumber].tBullet[BulletNumber].Color = EnemyInfo[tShot[ShotNumber].Number].Color;
			tShot[ShotNumber].tBullet[BulletNumber].Count = 0;
			tShot[ShotNumber].tBullet[BulletNumber].Speed = 0.5f;
		}
	}
}
//----------------------------------------------------------------
void CBullet::ShotCalc(int ShotNumber)
{
	int Max = 0;
	//敵が倒されたら
	if(EnemyInfo[tShot[ShotNumber].Number].Flag != 1)
	{
		tShot[ShotNumber].Flag = 2; //それ以上ショットを登録しない
	}
	//ShotNumber番目の弾幕データの弾を計算
	for(int ii = 0; ii < SHOT_BULLET_MAX; ii++)
	{
		//その弾が登録されていたら
		if(tShot[ShotNumber].tBullet[ii].Flag > 0)
		{
			tShot[ShotNumber].tBullet[ii].Pos.x += cos(tShot[ShotNumber].tBullet[ii].Angle) * tShot[ShotNumber].tBullet[ii].Speed;
			tShot[ShotNumber].tBullet[ii].Pos.z -= sin(tShot[ShotNumber].tBullet[ii].Angle) * tShot[ShotNumber].tBullet[ii].Speed;
			tShot[ShotNumber].tBullet[ii].Count++;
			if(tShot[ShotNumber].tBullet[ii].Pos.x < 248 || tShot[ShotNumber].tBullet[ii].Pos.x > 390 ||
				tShot[ShotNumber].tBullet[ii].Pos.z < 170 || tShot[ShotNumber].tBullet[ii].Pos.z > 325)
			{
				tShot[ShotNumber].tBullet[ii].Flag = 0;
			}
		}
	}
	//現在表示中の弾が一つでもあるか調べる
	for(int ii = 0; ii < SHOT_BULLET_MAX; ii++)
	{
		if(tShot[ShotNumber].tBullet[ii].Flag > 0)
		{
			return;
		}
	}
	if(EnemyInfo[tShot[ShotNumber].Number].Flag != 1)
	{
		tShot[ShotNumber].Flag = 0; //終了
		EnemyInfo[tShot[ShotNumber].Number].Flag = 0;
	}
}
//----------------------------------------------------------------
void CBullet::DrawShot()
{
	 SetDrawMode(DX_DRAWMODE_BILINEAR);//線形補完描画
	 for(int ii = 0; ii < SHOT_MAX; ii++)
	 {
		 if(tShot[ii].Flag > 0)
		 {
			 for(int jj = 0; jj < SHOT_BULLET_MAX; jj++)
			 {
				 if(tShot[ii].tBullet[jj].Flag != 0)
				 {
					 if(tShot[ii].tBullet[jj].Effect == 1)
					 {
						 SetDrawBlendMode(DX_BLENDMODE_ADD, 255);
					 }
					 DrawBillboard3D(tShot[ii].tBullet[jj].Pos, tShot[ii].tBullet[jj].Pos.x + PLAYER_MOVEX_MIN,
						 tShot[ii].tBullet[jj].Pos.z, 1.0f, tShot[ii].tBullet[jj].Angle + PI/2, BulletImage[tShot[ii].tBullet[jj].Kind][tShot[ii].tBullet[jj].Color], TRUE);
					 if(tShot[ii].tBullet[jj].Effect == 1)
					 {
						 SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0);
					 }
				 }
			 }
		 }
	}
	 SetDrawMode(DX_DRAWMODE_NEAREST); //描画形式を戻す
}
Main.cpp

コード:

#include "DxLib.h"
#include "Input.h"
#include "Stage.h"
#include "Camera.h"
#include "Model.h"
#include "Enemy.h"
#include "Bullet.h"
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;

#define ISLAND (0)
#define MIKU (0)
#define BACK (1)
#define SCREENWIDTH (1280)
#define SCREENHIGH (720)
#define SCREENBIT (32)
const int MaxStage = 2;
typedef struct CAMERA_DATA;

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
		ChangeWindowMode(TRUE);
		SetGraphMode(SCREENWIDTH ,SCREENHIGH ,SCREENBIT);	// 画面モードの設定
        // DXライブラリ初期化処理
		if( DxLib_Init() < 0 )
		{
			// エラーが発生したら直ちに終了
			return -1 ;
		}
		SetDrawScreen( DX_SCREEN_BACK );
		int StageCount = 0;
		CInput* input = new CInput();
		//カメラの設定
		CCamera* camera = new CCamera();
		CCamera::CAMERA_DATA CameraInfo;
		//カメラはZ軸が画面上方向になるよう第7、8、9引数のうちZ軸の第9引数を1.0にする(通常はY軸が上方向なので第8引数が1.0)
		camera->CameraInit(320.0f, -110.0f,  220.0f, 320.0f, -280.0f, 240.0f, 0.0f, 0.0f, 1.0f);
		CameraInfo = camera->GetCameraParam();
		camera->CameraSet(CameraInfo);
		//モデルの初期設定
		CModel* model = new CModel();
		CModel::PLAYER_PARAM PlayerInfo; 
		model->LoadFile(MIKU, "PlayerModel/Miku/Miku.mv1");					//キャラクターのモデルの読み込み
		model->SetPlayerRoll(MIKU, 90.0f, 0.0f, 0.0f);					//プレイヤーモデルの初期回転値
		model->SetPlayerPos(MIKU, 320.0f, -280.0f, 177.0f);								//プレイヤーモデルの初期位置
		PlayerInfo = model->GetPlayerParam();												// 描画先を裏画面にする
		//古いアニメーション情報を削除
		model->EraseAnimInfo(PlayerInfo);
		//アニメーション情報を初期化
		model->InitAnime(PlayerInfo.NowAnimNum, PlayerInfo.PlayerModel[MIKU], 0);
		PlayerInfo.AnimeState = CModel::WAIT;
		model->SetAnimeInfo(PlayerInfo);
		//敵の設定
		CEnemy* enemy = new CEnemy();
		CEnemy::ENEMY_PARAM* EnemyState;
		enemy->LoadEnemyOrder();
		enemy->LoadEnemy(CEnemy::ENEMY0, "Enemy/enemy1.x");
		//弾の設定
		CBullet* bullet = new CBullet();
		bullet->LoadBullet();
		//2D読み込み
		int SideBar = LoadGraph("Graphic/Dammy.png");
		while(ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0  && input->gpUpdateKey() == 0)
		{
			input->UpdatePad();
			//キャラの移動
			/*if(input->TriggerPad & PAD_INPUT_RIGHT)
			{
				PlayerInfo.PlayerPos.x -= 10;
			}
			else if(input->TriggerPad & PAD_INPUT_LEFT)
			{
				PlayerInfo.PlayerPos.x += 10;
			}
			else if(input->TriggerPad & PAD_INPUT_UP)
			{
				PlayerInfo.PlayerPos.z += 10;
			}
			else if(input->TriggerPad & PAD_INPUT_DOWN)
			{
				PlayerInfo.PlayerPos.z -= 10;
			}
			else if(input->Key1[KEY_INPUT_RETURN] != 0)
			{
				PlayerInfo.PlayerPos.y += 10;
			}
			else if(input->Key1[KEY_INPUT_BACK] != 0)
			{
				PlayerInfo.PlayerPos.y -= 10;
			}
			else if(input->Key1[KEY_INPUT_SPACE] != 0)
			{
				break;
			}
			model->SetPlayerPos(MIKU, PlayerInfo.PlayerPos.x, PlayerInfo.PlayerPos.y, PlayerInfo.PlayerPos.z);*/
			model->SetMoveAngle();
			model->MovePlayerModel();
			model->DrawModel(MIKU);
			enemy->EnemyEntery(StageCount);
			enemy->EnemyAction();
			enemy->EnemyDrow(CEnemy::ENEMY0);
			PlayerInfo = model->GetPlayerParam();
			EnemyState = enemy->GetEnemyParam();
			bullet->SetPlayerParam(PlayerInfo);
			bullet->SetEnemyParam(EnemyState);
			bullet->ShotMain();
			bullet->DrawShot();
			DrawGraph(0, 0, SideBar, TRUE);
			DrawGraph(1000, 0, SideBar, TRUE);
			DrawFormatString(100, 340, 0x666666,"X %f Y %f Z %f", PlayerInfo.PlayerPos.x, PlayerInfo.PlayerPos.y, PlayerInfo.PlayerPos.z);
			StageCount++;
		}
		model->UnLoadModel(MIKU);
		delete model;
        WaitKey();      // キー入力待ち
        DxLib_End();    // DXライブラリ終了処理
        return 0;
}
もしかしたら初歩的なミスで躓いてしまっているかもしれないですが、ご教授して頂けたらと思います。
どうかよろしくお願い致します。

Re: 敵のショットが描画されない

Posted: 2014年11月18日(火) 00:01
by north
こちらでも同じ質問を投稿させていただきました。
http://hpcgi2.nifty.com/natupaji/bbs/patio.cgi
よろしくお願い致します

Re: 敵のショットが描画されない

Posted: 2014年11月19日(水) 04:12
by north
描画されない問題ですが
下記のコードをBullet.cppに入れ忘れていたためでした。

コード:

void CBullet::ShotEntry(int EnemyNumber)
{
	for(int ii = 0; ii < SHOT_MAX; ii++)
	{
		if(tShot[ii].Flag == 0)
		{
			memset(&tShot[ii], 0, sizeof(SHOT_PARAM));
			tShot[ii].Flag = 1;
			tShot[ii].Kind = EnemyInfo[EnemyNumber].BulletKind;
			tShot[ii].Number = ii;
			tShot[ii].Count = 0;
			return;
		}
	}
}
また、Enemy.cppのvoid EnemyAction()
に下記のコードを追加しました。

コード:

if(tEnemyParam[ii].BulletTime == tEnemyParam[ii].Count)
{
	CBullet bullet;
	bullet.ShotEntry(ii);
}
しかしコンパイルをすると
main.cppの103行目でハンドルされていない例外が発生しましたと出てしまいます。
これの原因がわからず困っております。
念の為Enemy関係のコードも載せておきます。
Enemy.h

コード:

#ifndef ENEMYH
#define ENEMYH
//-----------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <iostream>
#include "DxLib.h"
#include <Math.h>
using namespace std;

#define ENEMY_MODEL_KIND (3)
#define ENEMY_MAX (30)
#define ENEMY_ORDER_MAX (500) //敵の出現情報最大数
#define ENEMY_MOVEX_MIN (252)
#define ENEMY_MOVEX_MAX (385)
#define ENEMY_MOVEZ_MIN (177)
#define ENEMY_MOVEZ_MAX (300)
#define ENEMY_PATTERN_MAX (11)
#define PI 3.1415926535898
#define PI2 (PI*2)
//------------------------------------------------------------

class CEnemy
{
public:
	//敵の情報の構造体
	typedef struct
	{
		int Flag;	//敵のフラグ
		int Count;	//敵のカウンター
		int Pattern;	//敵の移動パターン
		int Muki;	//敵の向き
		int Kind;	//敵の種類
		int Hp;		//敵のHP
		int MaxHp;	//敵の最大HP
		int Item_n[6];	//落とすアイテム
		int ModelHandle[ENEMY_MODEL_KIND];	//敵のモデルの格納ハンドル
		int Model;
		VECTOR Pos;	//敵の座標
		float VX;	//速度X成分
		float VZ;	//速度Z成分
		float Spd;	//スピード
		float Angle;	//角度
		int BulletTime;	//弾幕開始時間
		int BulletKind;	//弾幕の種類
		int BulletKind2;	//弾幕の種類
		int Color;	//色
		int State;	//状態
		int WaitTime;	//待機時間
		int Wait;	//停滞時間
	}ENEMY_PARAM;
	//CSVファイルから読み取った敵データを格納するための構造体
	typedef struct
	{
		int Count;
		int Pattern;
		int Kind;
		float PosX;
		float PosZ;
		float Speed;
		int BulletTime;
		int BulletKind;
		int Color;
		int Hp;
		int BulletKind2;
		int Wait;
		int Item_n[6];
	}ENEMY_ORDER;
	enum ENEMY_KIND{ENEMY0, ENEMY1, ENEMY2};
private:
	ENEMY_PARAM tEnemyParam[ENEMY_MAX];
	ENEMY_ORDER tEnemyOrder[ENEMY_ORDER_MAX];
	/*void EnemyPattern0(int EnemyCount);
	void EnemyPattern1(int EnemyCount);
	void EnemyPattern2(int EnemyCount);
	void EnemyPattern3(int EnemyCount);
	void EnemyPattern4(int EnemyCount);
	void EnemyPattern5(int EnemyCount);
	void EnemyPattern6(int EnemyCount);
	void EnemyPattern7(int EnemyCount);
	void EnemyPattern8(int EnemyCount);
	void EnemyPattern9(int EnemyCount);
	void EnemyPattern10(int EnemyCount);*/
	int EnemyNumberSearch();
public:
	CEnemy();
	~CEnemy();
	int LoadEnemy(int EnemyNum, string FileName);
	void UnLoadEnemy(int EnemyNum);
	void LoadEnemyOrder();
	void EnemyEntery(int StageCount);
	void EnemyAction();
	void EnemyDrow(int EnemyNum);
	ENEMY_PARAM *GetEnemyParam();
	float Rang(float Angle);
	void (CEnemy::*EnemyPattern[ENEMY_PATTERN_MAX])(int);
	void EnemyPattern0(int EnemyCount);
	void EnemyPattern1(int EnemyCount);
	void EnemyPattern2(int EnemyCount);
	void EnemyPattern3(int EnemyCount);
	void EnemyPattern4(int EnemyCount);
	void EnemyPattern5(int EnemyCount);
	void EnemyPattern6(int EnemyCount);
	void EnemyPattern7(int EnemyCount);
	void EnemyPattern8(int EnemyCount);
	void EnemyPattern9(int EnemyCount);
	void EnemyPattern10(int EnemyCount);
};
#endif
Enemy.cpp

コード:

#include "Enemy.h"
#include "Bullet.h"

CEnemy::CEnemy()
{
	memset(tEnemyParam, 0, sizeof(ENEMY_PARAM) * ENEMY_MAX);//敵データの初期化
	for(int ii = 0; ii < ENEMY_MAX; ii++)
	{
		tEnemyParam[ii].Pos.y = -280.0f;
	}
	memset(tEnemyOrder, 0, sizeof(ENEMY_ORDER) * ENEMY_ORDER_MAX);
	EnemyPattern[0] = &CEnemy::EnemyPattern0;
	EnemyPattern[1] = &CEnemy::EnemyPattern1;
	EnemyPattern[2] = &CEnemy::EnemyPattern2;
	EnemyPattern[3] = &CEnemy::EnemyPattern3;
	EnemyPattern[4] = &CEnemy::EnemyPattern4;
	EnemyPattern[5] = &CEnemy::EnemyPattern5;
	EnemyPattern[6] = &CEnemy::EnemyPattern6;
	EnemyPattern[7] = &CEnemy::EnemyPattern7;
	EnemyPattern[8] = &CEnemy::EnemyPattern8;
	EnemyPattern[9] = &CEnemy::EnemyPattern9;
	EnemyPattern[10] = &CEnemy::EnemyPattern10;
}
//------------------------------------------------------------
CEnemy::~CEnemy()
{}
//------------------------------------------------------------
int CEnemy::LoadEnemy(int EnemyNum, std::string FileName)
{
	
	for(int ii = 0; ii < ENEMY_MAX; ii++)
	{
		//SetUseASyncLoadFlag(TRUE);
		switch (EnemyNum)
		{
			case ENEMY0:

				tEnemyParam[ii].ModelHandle[ENEMY0] = MV1LoadModel(FileName.c_str());
				break;

			case ENEMY1:
				tEnemyParam[ii].ModelHandle[ENEMY1] = MV1LoadModel(FileName.c_str());
				break;

			case ENEMY2:
				tEnemyParam[ii].ModelHandle[ENEMY2] = MV1LoadModel(FileName.c_str());
				break;
		}
		//SetUseASyncLoadFlag(FALSE);
		if(tEnemyParam[ii].ModelHandle[EnemyNum] == -1)
		{
			return -1;
		}
		//MV1SetScale(tPlayerParam.PlayerModel[ModelNum], VGet(1, 1, 1));
		//読み込み成功
	}
	return 1;
}
//------------------------------------------------------------
void CEnemy::UnLoadEnemy(int EnemyNum)
{
	for(int ii = 0; ii < ENEMY_MAX; ii++)
	{
		if(tEnemyParam[ii].ModelHandle[EnemyNum] != 0)
		{
			MV1DeleteModel(tEnemyParam[ii].ModelHandle[EnemyNum]);
		}
	}
}
//------------------------------------------------------------
void CEnemy::LoadEnemyOrder()
{
	int Line;
	int Number;
	int fp;
	char FileName[32] = {"EnemyState/storyH0.csv"};
	int input[64];
	char inputc[64];

	fp = FileRead_open(FileName); //ファイルの読み込み
	if(fp == NULL)
	{
		printfDx("read error\n");
		return;
	}
	for(int ii = 0; ii < 2; ii++) //最初の2行は飛ばす
	{
		while(FileRead_getc(fp) != '\n');
	}
	Line = 0;
	Number = 0;
	while(1)
	{
		for(int ii = 0; ii < 64; ii++)
		{
			inputc[ii] = input[ii] = FileRead_getc(fp); //1文字取得する
			if(inputc[ii] == '/') //スラッシュがあれば
			{
				while(FileRead_getc(fp) != '\n'); //開業までループ
				ii = 1; //カウンタを最初に戻す
				continue;
			}
			if(input[ii] == ',' || input[ii] == '\n') //カンマか改行なら
			{
				inputc[ii] = '\0'; //そこまでを文字列とする
				break;
			}
			if(input[ii] == EOF) //ファイルの終わりなら
			{
				goto EXFILE; //終了
			}
		}
		switch(Number)
		{
			case 0:
				tEnemyOrder[Line].Count = atoi(inputc);
				break;
			case 1:
				tEnemyOrder[Line].Pattern = atoi(inputc);
				break;
			case 2:
				tEnemyOrder[Line].Kind = atoi(inputc);
				break;
			case 3:
				tEnemyOrder[Line].PosX = atoi(inputc);
				break;
			case 4:
				tEnemyOrder[Line].PosZ = atoi(inputc);
				break;
			case 5:
				tEnemyOrder[Line].Speed = atoi(inputc);
				break;
			case 6:
				tEnemyOrder[Line].BulletTime = atoi(inputc);
				break;
			case 7:
				tEnemyOrder[Line].BulletKind = atoi(inputc);
				break;
			case 8:
				tEnemyOrder[Line].Color = atoi(inputc);
				break;
			case 9:
				tEnemyOrder[Line].Hp = atoi(inputc);
				break;
			case 10:
				tEnemyOrder[Line].BulletKind2 = atoi(inputc);
				break;
			case 11:
				tEnemyOrder[Line].Wait = atoi(inputc);
				break;
			case 12:
				tEnemyOrder[Line].Item_n[0] = atoi(inputc);
				break;
			case 13:
				tEnemyOrder[Line].Item_n[1] = atoi(inputc);
				break;
			case 14:
				tEnemyOrder[Line].Item_n[2] = atoi(inputc);
				break;
			case 15:
				tEnemyOrder[Line].Item_n[3] = atoi(inputc);
				break;
			case 16:
				tEnemyOrder[Line].Item_n[4] = atoi(inputc);
				break;
			case 17:
				tEnemyOrder[Line].Item_n[5] = atoi(inputc);
				break;
		}
		Number++;
		if(Number == 18)
		{
			Number = 0;
			Line++;
		}
	}
EXFILE:
	FileRead_close(fp);
}
//------------------------------------------------------------
void CEnemy::EnemyPattern0(int EnemyCount)
{
	if(tEnemyParam[EnemyCount].Count == 0)
	{
		tEnemyParam[EnemyCount].VZ = -0.5f; //下がってくる
	}
	if(tEnemyParam[EnemyCount].Count == 40)
	{
		tEnemyParam[EnemyCount].VZ = 0.0f; //止まる
	}
	if(tEnemyParam[EnemyCount].Count == 40 + tEnemyParam[EnemyCount].Wait) //登録された時間だけ停滞する
	{
		tEnemyParam[EnemyCount].VZ = 0.5f; //上がっていく
	}
}
//------------------------------------------------------------
void CEnemy::EnemyPattern1(int EnemyCount)
{
	if(tEnemyParam[EnemyCount].Count == 0)
	{
		tEnemyParam[EnemyCount].VZ = -0.5f; //下がってくる
	}
	if(tEnemyParam[EnemyCount].Count == 40)
	{
		tEnemyParam[EnemyCount].VZ = 0; //止まる
	}
	if(tEnemyParam[EnemyCount].Count == 40 + tEnemyParam[EnemyCount].Wait) //登録された時間だけ停滞する
	{
		tEnemyParam[EnemyCount].VX = -0.3f; //左へ
		tEnemyParam[EnemyCount].VZ = -0.4f; //下がっていく
		tEnemyParam[EnemyCount].Muki = 0; //左向きセット
	}
}
//------------------------------------------------------------
void CEnemy::EnemyPattern2(int EnemyCount)
{
	if(tEnemyParam[EnemyCount].Count == 0)
	{
		tEnemyParam[EnemyCount].VZ = -0.5f; //下がる
	}
	if(tEnemyParam[EnemyCount].Count == 40)
	{
		tEnemyParam[EnemyCount].VZ = 0.0f; //停滞する
	}
	if(tEnemyParam[EnemyCount].Count == 40 + tEnemyParam[EnemyCount].Wait)
	{
		tEnemyParam[EnemyCount].VX = 0.3f; //右へ
		tEnemyParam[EnemyCount].VZ = -0.4f; //下がる
		tEnemyParam[EnemyCount].Muki = 2; //右向きセット
	}
}
//------------------------------------------------------------
void CEnemy::EnemyPattern3(int EnemyCount)
{
	if(tEnemyParam[EnemyCount].Count == 0)
	{
		tEnemyParam[EnemyCount].VZ = -0.7f;
	}
	if(tEnemyParam[EnemyCount].Count == 30)
	{
		tEnemyParam[EnemyCount].Muki = 0;
	}
	if(tEnemyParam[EnemyCount].Count < 100)
	{
		tEnemyParam[EnemyCount].VX -= 0.7f / 100.0f;
		tEnemyParam[EnemyCount].VZ += 0.4f / 100.0f;
	}
}
//------------------------------------------------------------
void CEnemy::EnemyPattern4(int EnemyCount)
{
	if(tEnemyParam[EnemyCount].Count == 0)
	{
		tEnemyParam[EnemyCount].VZ = -0.7f;
	}
	if(tEnemyParam[EnemyCount].Count == 30)
	{
		tEnemyParam[EnemyCount].Muki = 2;
	}
	if(tEnemyParam[EnemyCount].Count < 100)
	{
		tEnemyParam[EnemyCount].VX += 0.7f / 100.0f;
		tEnemyParam[EnemyCount].VZ -= 0.7f / 100.0f;
	}
}
//------------------------------------------------------------
void CEnemy::EnemyPattern5(int EnemyCount)
{
	if(tEnemyParam[EnemyCount].Count == 0)
	{
		tEnemyParam[EnemyCount].VX -= 0.3f;
		tEnemyParam[EnemyCount].VZ = -0.4f;
		tEnemyParam[EnemyCount].Muki = 0;
	}
}
//------------------------------------------------------------
void CEnemy::EnemyPattern6(int EnemyCount)
{
	if(tEnemyParam[EnemyCount].Count == 0)
	{
		tEnemyParam[EnemyCount].VX += 0.3f;
		tEnemyParam[EnemyCount].VZ = -0.4f;
		tEnemyParam[EnemyCount].Muki = 2;
	}
}
//------------------------------------------------------------
void CEnemy::EnemyPattern7(int EnemyCount)
{
	if(tEnemyParam[EnemyCount].Count == tEnemyParam[EnemyCount].Wait)
	{
		tEnemyParam[EnemyCount].VX =-0.7f;
		tEnemyParam[EnemyCount].VZ =+0.5f;
		tEnemyParam[EnemyCount].Muki = 0;
	}
}
//------------------------------------------------------------
void CEnemy::EnemyPattern8(int EnemyCount)
{
	if(tEnemyParam[EnemyCount].Count == tEnemyParam[EnemyCount].Wait)
	{
		tEnemyParam[EnemyCount].VX =+1.7f;
		tEnemyParam[EnemyCount].VZ =+0.5f;
		tEnemyParam[EnemyCount].Muki = 2;
	}
}
//------------------------------------------------------------
void CEnemy::EnemyPattern9(int EnemyCount)
{
	if(tEnemyParam[EnemyCount].Count == tEnemyParam[EnemyCount].Wait)
	{
		tEnemyParam[EnemyCount].VZ = 0.4f;
	}
}
//------------------------------------------------------------
void CEnemy::EnemyPattern10(int EnemyCount)
{
	if(tEnemyParam[EnemyCount].Count == 0)
	{
		tEnemyParam[EnemyCount].VZ = -0.4f;
	}
	if(tEnemyParam[EnemyCount].Count == 40)
	{
		tEnemyParam[EnemyCount].VZ = 0.0f;
	}
	if(tEnemyParam[EnemyCount].Count > 40)
	{
		if(tEnemyParam[EnemyCount].Count % 60 == 0)
		{
			int rng = cos(tEnemyParam[EnemyCount].Angle) < 0 ? 0 : 1;
			tEnemyParam[EnemyCount].Spd = 2.5f + Rang(2);
			tEnemyParam[EnemyCount].Angle = Rang(PI/4) + PI * rng;
			tEnemyParam[EnemyCount].Muki = 2 - 2 * rng;
		}
		tEnemyParam[EnemyCount].Spd *= 0.95f;
	}
	if(tEnemyParam[EnemyCount].Count >= 40 + tEnemyParam[EnemyCount].Wait)
	{
		tEnemyParam[EnemyCount].VZ += 0.008f;
	}
}
//------------------------------------------------------------
int CEnemy::EnemyNumberSearch()
{
	for(int ii = 0; ii < ENEMY_MAX; ii++)//フラグの立っていないEnemyを探す
	{
		if(tEnemyParam[ii].Flag == 0)
		{
			return ii; //使用可能番号を返す
		}
	}
	return -1; //全部埋まっていたらエラーを返す
}
//------------------------------------------------------------
void CEnemy::EnemyEntery(int StageCount)
{
	int Number = 0;
	for(int ii = 0; ii < ENEMY_ORDER_MAX; ii++)
	{
		//現在の瞬間がオーダーの瞬間なら
		if(tEnemyOrder[ii].Count == StageCount)
		{
			if((Number = EnemyNumberSearch()) != -1)
			{
				tEnemyParam[Number].Flag = 1;
				tEnemyParam[Number].Count = 0;
				tEnemyParam[Number].Pattern = tEnemyOrder[ii].Pattern;
				tEnemyParam[Number].Muki = 1;
				tEnemyParam[Number].Kind = tEnemyOrder[ii].Kind;
				tEnemyParam[Number].Pos.x = tEnemyOrder[ii].PosX;
				tEnemyParam[Number].Pos.z = tEnemyOrder[ii].PosZ;
				tEnemyParam[Number].Spd = tEnemyOrder[ii].Speed;
				tEnemyParam[Number].BulletTime = tEnemyOrder[ii].BulletTime;
				tEnemyParam[Number].BulletKind = tEnemyOrder[ii].BulletKind;
				tEnemyParam[Number].BulletKind2 = tEnemyOrder[ii].BulletKind2;
				tEnemyParam[Number].Color = tEnemyOrder[ii].Color;
				tEnemyParam[Number].Wait = tEnemyOrder[ii].Wait;
				tEnemyParam[Number].Hp = tEnemyOrder[ii].Hp;
				tEnemyParam[Number].MaxHp = tEnemyOrder[ii].Hp;
				tEnemyParam[Number].VX = 0;
				tEnemyParam[Number].VZ = 0;
				tEnemyParam[Number].Angle = 0;
				for(int jj = 0; jj < 6; jj++)
				{
					tEnemyParam[Number].Item_n[jj] = tEnemyOrder[ii].Item_n[jj];
				}
				MV1SetPosition(tEnemyParam[Number].ModelHandle[ENEMY0], tEnemyParam[Number].Pos);
			}
		}
	}
}
//------------------------------------------------------------
void CEnemy::EnemyAction()
{
	for(int ii = 0; ii < ENEMY_MAX; ii++)
	{
		//敵のフラグがオンだったら
		if(tEnemyParam[ii].Flag == 1)
		{
			(this->*EnemyPattern[tEnemyParam[ii].Pattern])(ii);
			tEnemyParam[ii].Pos.x += cos(tEnemyParam[ii].Angle) * tEnemyParam[ii].Spd;
			tEnemyParam[ii].Pos.z += sin(tEnemyParam[ii].Angle) * tEnemyParam[ii].Spd;
			tEnemyParam[ii].Pos.x += tEnemyParam[ii].VX;
			tEnemyParam[ii].Pos.z += tEnemyParam[ii].VZ;
			tEnemyParam[ii].Count++;
			tEnemyParam[ii].Model = tEnemyParam[ii].Muki * 3 + (tEnemyParam[ii].Count % 18) / 6;
			//敵が画面外から外れたら消す
			if(tEnemyParam[ii].Pos.x < 248 || tEnemyParam[ii].Pos.x > 390 || tEnemyParam[ii].Pos.z < 170 || tEnemyParam[ii].Pos.z > 325)
			{
				tEnemyParam[ii].Flag = 0;
			}
			if(tEnemyParam[ii].BulletTime == tEnemyParam[ii].Count)
			{
				CBullet bullet;
				bullet.ShotEntry(ii);
			}
			MV1SetPosition(tEnemyParam[ii].ModelHandle[ENEMY0], tEnemyParam[ii].Pos);
		}
	}
}
//------------------------------------------------------------
void CEnemy::EnemyDrow(int EnemyNum)
{
	VECTOR POS;
	for(int ii = 0; ii < ENEMY_MAX; ii++)
	{
		if(tEnemyParam[ii].Flag == 1)
		{
			MV1DrawModel(tEnemyParam[ii].ModelHandle[tEnemyParam[ii].Kind]);
		}
		POS = MV1GetPosition(tEnemyParam[ii].ModelHandle[EnemyNum]);
	}
}
//------------------------------------------------------------
CEnemy::ENEMY_PARAM* CEnemy::GetEnemyParam()
{
	return tEnemyParam;
}
//------------------------------------------------------------
float CEnemy::Rang(float Angle)
{
	return (-Angle + Angle * 2 * GetRand(10000) / 10000.0f);
}
どうしても原因がわからず本当に困っております。
ご教授願えたらと思いますのでどうかよろしくお願い致します。

Re: 敵のショットが描画されない

Posted: 2014年11月19日(水) 10:31
by softya(ソフト屋)
時間がなくて調べられないですが、デバッガで情報が表示されない場合。
・変数の寿命が尽きている
・Releaseビルドしている
・ポインタが範囲外を指している
などが考えられます。

あと丸投げ状態に近いので答えが寄せられないんだと思いますが、前にデバッグ方法を教えたと思いますが、
発生・更新・描画のどの部位にあるのか絞り込みもできていませんか?
デバッガが使えなくても、変数の値確認ならprintfDXやDrawFormatStringやなんならOutputDebugStringなど工夫の余地はあるはずです。
デバッグは創意工夫です。ありとあらゆることを試しましょう。

Re: 敵のショットが描画されない

Posted: 2014年11月19日(水) 16:43
by north
確かに丸投げに近い状態でした。
申し訳ありません。
こちらで調べて今わかっているのはmain.cppの102行目のEnemyAction()まではブレークが来ているのですが、
この後、EnemyAction()の中に入ると中に書かれている処理がスキップされて次の行のEnemyDrow(CEnemy::ENEMY0)まで行ってしまい
「ハンドルされていない例外が発生しました(スタックオーバーフロー)」と出てしまいます。
原因っぽいEnemy.cppの392行目のEnemyAction関数内の413行目と414行目に記載しました
CBullet bullet
bullet.ShotEntry(ii)の部分をコメントアウトしましたら発生しなくなりました(弾は描画されたおりません)
もしかしたらnewしていないのが原因かと思い下記のように修正したところ

コード:

CBullet *bullet;
bullet = new CBullet();
bullet->ShotEntry(ii);
Bullet.cppのShotEntry関数内の172行目でアクセス違反が起こり、EnmyInfoの中身が「エラーです。式を評価できません」
となっており、Enemy.cppのtEnemyParamの情報が取得できていませんでした。
上記を踏まえた上で
・Enemy.cppでBullet.cppの関数を使いたいときはnewするしかないのでしょうか?
・なぜtEnemyParamの値が取得できていないのでしょうか?
上記2点がどうしてもわかりません。ご教授願えたらと思います。

Re: 敵のショットが描画されない

Posted: 2014年11月20日(木) 22:59
by softya(ソフト屋)
すいません。やはり時間がないので大雑把にしか見れてませんが、CBulletをローカル定義して使われてもローカル変数と同じなのでWinMainのCBulletには情報は伝わりません。
ブロックを抜けた時点で情報は破棄されます。ちゃんと情報が伝わっていないことを確認してみてください。
なお、インスタンスというか変数の寿命について勉強された方が良いように思いますので、別プログラムを作って色々実験をなさるべきだと思います。

Re: 敵のショットが描画されない

Posted: 2014年11月20日(木) 23:10
by north
なんとなくローカルで定義されているのでの寿命が尽きてしまっているせいかなと思っていたのですが確信がもてませんでしたので
ご質問させていただきました。おっしゃる通りもう一度変数の寿命について勉強し直すべきかなと痛感いたしました。
本当はBullet.hをEnemy.hにインクルードして龍神録に記載されている通りにやりたかったのですが、そうしますと
Bullet.hでEnemy.hをインクルードしているにもかかわらず、CEnemyが定義されていないと出てしまいこれの原因がなぜなのか
わからず現在のやり方にいたしました。これも自分の勉強不足だと思いますのでもしよろしければ教えていただければと思います。

Re: 敵のショットが描画されない

Posted: 2014年11月20日(木) 23:21
by softya(ソフト屋)
お互いに参照しているのだと思いますが、そうするとエラーになりますね。
避けるのが一番だと思いますが、前方参照で切り抜けられる場合があります。

「C++/前方参照 - PukiWiki」
http://peridotto.com/wiki/index.php?C%2 ... B%B2%BE%C8

Re: 敵のショットが描画されない

Posted: 2014年11月24日(月) 17:33
by north
ありがとうございます。
やはり避けるのが一番だとは思うのですがそこはもう自分の設計のミスとしか言いようがないので
前方参照やexternを使ってやってみたいと思います。