現在、龍神録プログラミングの館を参考にSTGを作成しているのですが、第11章のところでつまずいております。
具体的には複数出てくるはずの敵が1体しか出てこず、何が原因なのかわからず困っております。
敵に3Dモデルを使用しているため座標は3D軸となっております。
下記がコードとなります
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)
//------------------------------------------------------------
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);
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);
};
#endif
#include "Enemy.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);
}
//------------------------------------------------------------
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 == 60)
{
tEnemyParam[EnemyCount].VZ = 0.0f; //止まる
}
if(tEnemyParam[EnemyCount].Count == 60 + tEnemyParam[EnemyCount].Wait) //登録された時間だけ停滞する
{
tEnemyParam[EnemyCount].VZ = 0.5f; //上がっていく
}
}
//------------------------------------------------------------
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)
{
EnemyPattern0(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;
}
MV1SetPosition(tEnemyParam[ii].ModelHandle[ENEMY0], tEnemyParam[ii].Pos);
}
}
}
//------------------------------------------------------------
void CEnemy::EnemyDrow(int EnemyNum)
{
for(int ii = 0; ii < ENEMY_MAX; ii++)
{
if(tEnemyParam[ii].Flag == 1)
{
MV1DrawModel(tEnemyParam[ii].ModelHandle[EnemyNum]);
}
}
}
#include "DxLib.h"
#include "Input.h"
#include "Stage.h"
#include "Camera.h"
#include "Model.h"
#include "Enemy.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 = 0;
model->SetAnimeInfo(PlayerInfo);
//敵の設定
CEnemy* enemy = new CEnemy();
enemy->LoadEnemyOrder();
enemy->LoadEnemy(CEnemy::ENEMY0, "Enemy/enemy1.x");
//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();
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;
}
/カウンタ,移動パターン,敵の種類,x座標,Z座標,スピード,発射時間,弾幕種類,弾の色,体力,弾種類,待機時間,アイテム1,2,3,4,5,6
/cnt,pattern,knd,x座標,Z座標,sp,bltime,blknd,col,hp,blknd2,wait,item_n[0],,,,,
100,0,0,290,310,0,150,0,0,100,0,120,0,-1,-1,-1,-1,-1
110,0,0,295,310,0,150,0,0,100,0,120,0,-1,-1,-1,-1,-1
120,0,0,300,310,0,150,0,0,100,0,120,0,-1,-1,-1,-1,-1
130,0,0,315,310,0,150,0,0,100,0,120,0,-1,-1,-1,-1,-1
140,0,0,320,310,0,150,0,0,100,0,120,0,-1,-1,-1,-1,-1
150,0,0,325,310,0,150,0,0,100,0,120,0,-1,-1,-1,-1,-1
160,0,0,330,310,0,150,0,0,100,0,120,0,-1,-1,-1,-1,-1
170,0,0,335,310,0,150,0,0,100,0,120,0,-1,-1,-1,-1,-1
180,0,0,340,310,0,150,0,0,100,0,120,0,-1,-1,-1,-1,-1
190,0,0,345,310,0,150,0,0,100,0,120,0,-1,-1,-1,-1,-1
もしかしたら初歩的なところでつまづいているかもしれないですがご教授していただければと思います。