上記のサイトを見ながらSTGを制作しているのですが
メインで 'CONTROL::CONTROL': private メンバー (クラス 'CONTROL' で宣言されている) にアクセスできません。
とエラーが出ています
分かる方いました教えていただきたいです。
[main.cpp]
#include "pch.h"
#include "control.h"
//キー取得用配列
char key[256];
int g_count;
int state = 0;
// プログラムは WinMain から始まります
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )
{
ChangeWindowMode(TRUE);
if( DxLib_Init() == -1 ) // DXライブラリ初期化処理
{
return -1 ; // エラーが起きたら直ちに終了
}
CONTROL *control = new CONTROL; //ここでエラーが出ます。
while(ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && GetHitKeyStateAll(key)==0){
control->All();
}
DxLib_End() ; // DXライブラリ使用の終了処理
return 0 ; // ソフトの終了
}
[pch.h]
//警告を消すための記述
#pragma warning(disable:4244)
#define _CRT_SECURE_NO_WARNINGS
//DXライブラリとdefine.hの取り込み
#include "DxLib.h"
#include "define.h"
[define.h]
#include <windows.h>
//プレイヤーの歩くスピード
#define PLAYER_SPEED 4
//座標取得
#define MARGIN 10
//背景スクロールスピード
#define SCROLL_SPEED 2
//弾処理
#define PSHOT_NUM 20
#define PSHOT_SPEED 14
//メッセージボックス
#define MSG(m) {\
MessageBox(NULL,m,"メッセージ",MB_OK);}
//extern宣言してkey配列にどこからでもアクセスできるようにする
extern char key[256];
extern int g_count;
//プレイヤー弾
struct SHOT
{
bool flag; //弾が発射中かどうか
double x; //x座標
double y; //y座標
int gh; //グラフィックハンドル
int width, height; //画像の幅と高さ
};
//エネミー弾
struct E_SHOT
{
bool flag; //弾が発射中かどうか
double x; //x座標
double y; //y座標
double rad; //角度(ラジアン)
int gh; //グラフィックハンドル
int width, height; //画像の幅と高さ
int pattern; //ショットパターン
int speed; //弾スピード
};
#define ENEMY_SNUM 50
//エネミーデータ
struct ENEMY_DATA
{
int type; //敵種類
int stype; //弾種類
int m_pattern; //移動パターン
int s_pattern; //発射パターン
int in_time; //出現時間
int stop_time; //停止時間
int shot_time; //弾発射時間
int out_time; //帰還時間
int x; //x座標
int y; //y座標
int speed; //弾スピード
int hp; //HP
int item; //アイテム
};
#define ENEMY_NUM 5
[control.cpp]
#include "pch.h"
#include "control.h"
CONTROL::CONTROL()
{
player = new PLAYER;
back = new BACK;
FILE *fp;
ENEMY_DATA data[ENEMY_NUM];
char buf[100];
int c;
int col = 1;
int row = 0;
memset(buf, 0, sizeof(buf));
fp = fopen("DATA/ENEMY/enemydata.csv", "r");
//ヘッダ読み飛ばし
while (fgetc(fp) != '\n');
while (1) {
while (1) {
c = fgetc(fp);
//末尾ならループを抜ける。
if (c == EOF)
goto out;
//カンマか改行でなければ、文字としてつなげる
if (c != ',' && c != '\n')
strcat(buf, (const char*)&c);
//カンマか改行ならループ抜ける。
else
break;
}
//ここに来たということは、1セル分の文字列が出来上がったということ
switch (col) {
//1列目は敵種類を表す。atoi関数で数値として代入。
case 1: data[row].type = atoi(buf); break;
//2列目は弾種類。以降省略。
case 2: data[row].stype = atoi(buf); break;
case 3: data[row].m_pattern = atoi(buf); break;
case 4: data[row].s_pattern = atoi(buf); break;
case 5: data[row].in_time = atoi(buf); break;
case 6: data[row].stop_time = atoi(buf); break;
case 7: data[row].shot_time = atoi(buf); break;
case 8: data[row].out_time = atoi(buf); break;
case 9: data[row].x = atoi(buf); break;
case 10: data[row].y = atoi(buf); break;
case 11: data[row].speed = atoi(buf); break;
case 12: data[row].hp = atoi(buf); break;
case 13: data[row].item = atoi(buf); break;
}
//バッファを初期化
memset(buf, 0, sizeof(buf));
//列数を足す
++col;
//もし読み込んだ文字が改行だったら列数を初期化して行数を増やす
if (c == '\n') {
col = 1;
++row;
}
}
out:
//敵クラス生成
for (int i = 0; i<ENEMY_NUM; ++i)
{
enemy[i] = new ENEMY(data[i].type, data[i].stype, data[i].m_pattern, data[i].s_pattern, data[i].in_time, data[i].stop_time, data[i].shot_time,
data[i].out_time, data[i].x, data[i].y, data[i].speed, data[i].hp, data[i].item);
}
}
void CONTROL::GetPlayerPosition(double *x, double *y)
{
double tempx, tempy;
player->GetPosition(&tempx, &tempy);
*x = tempx;
*y = tempy;
}
void CONTROL::GetEnemyPosition(int index, double *x, double *y)
{
double tempx, tempy;
//指定した添字の敵の座標を取得
enemy[index]->GetPosition(&tempx, &tempy);
//代入
*x = tempx;
*y = tempy;
}
void CONTROL::All()
{
//描画領域を指定
SetDrawArea(MARGIN, MARGIN, MARGIN + 380, MARGIN + 460);
back->All();
player->All();
for (int i = 0; i<ENEMY_NUM; ++i) {
if (enemy[i] != NULL) {
if (enemy[i]->All()) {
delete enemy[i];
enemy[i] = NULL;
}
}
}
++g_count;
}
CONTROL::~CONTROL()
{
delete player;
delete back;
for (int i = 0; i<ENEMY_NUM; ++i) {
if (enemy[i] != NULL) {
delete enemy[i];
}
}
}
[control.h]
#include "player.h"
#include"back.h"
#include"enemy.h"
class CONTROL{
private:
//プレイヤークラス
PLAYER *player;
//背景クラス
BACK *back;
//エネミークラス
ENEMY *enemy[ENEMY_NUM];
private:
CONTROL();
~CONTROL();
public:
void All();
void GetPlayerPosition(double *x, double *y);
void GetEnemyPosition(int index, double *x, double *y);
static CONTROL& GetInstance() {
static CONTROL control;
return control;
}
};
[enemy.cpp]
#define _USE_MATH_DEFINES
#include"pch.h"
#include"control.h"
#include"math.h"
#include<ctime>
#include<cstdlib>
ENEMY::ENEMY(int type, int stype,int m_pattern,int s_pattern,int in_time,int stop_time, int shot_time, int out_time,
int x, int y, int speed, int hp, int item)
{
//サイズ
width = 27;
height = 25;
//敵の種類
this->type = type;
this->stype = stype;
//移動パターンとショットパターン
this->m_pattern = m_pattern;
this->s_pattern = s_pattern;
//座標セット
this->x = x;
this->y = y;
//出現、停止、発射、帰還時間セット
this->in_time = in_time;
this->stop_time = stop_time;
this->shot_time = shot_time;
this->out_time = out_time;
//HPとアイテム代入
this->hp = hp;
this->item = item;
//敵画像読み込み
if (type == 0)
{
LoadDivGraph("DATA/BG/enemy.png", 3, 1, 3, 27, 25, gh);
}
int temp;
//弾画像読み込み
switch (stype)
{
case 0:
temp = LoadGraph("DATA/BG/enemyshot1.png");
break;
case 1:
temp = LoadGraph("DATA/BG/enemyshot2.png");
break;
case 2:
temp = LoadGraph("DATA/BG/enemyshot3.png");
break;
}
int w, h;
GetGraphSize(temp, &w, &h);
//弾の初期化
for (int i = 0; i < ENEMY_SNUM; ++i)
{
shot[i].flag = false;
shot[i].gh = temp;
shot[i].width = w;
shot[i].height = h;
shot[i].pattern = s_pattern;
shot[i].speed = speed;
shot[i].x = x;
shot[i].y = y;
}
count = 0;
scount = 0;
num = 0;
rad = 0;
deadflag = false;
endflag = false;
sflag = false;
}
void ENEMY::GetPosition(double *x, double *y)
{
*x = this->x;
*y = this->y;
}
void ENEMY::Move()
{
//まだ生きてるか画面内に居るときだけ処理
if (!deadflag) {
switch (m_pattern) {
//途中で止まって、そのまま後ろに帰るパターン
case 0:
//出てきてから止まる時間までの間なら下に移動
if (in_time<g_count && g_count<stop_time) {
y += 2;
//帰還時間を過ぎたら戻る。
}
else if (g_count>out_time) {
y -= 2;
}
break;
//そのまま止まらずに下に行くパターン
case 1:
if (in_time <= g_count) {
y += 2;
}
break;
//ちょっとずつ左に移動しながら消えていく
case 2:
if (in_time <= g_count) {
y += 1;
if (count % 10 == 0) {
x -= 1;
}
}
break;
//ちょっとずつ右に移動しながら消えていく
case 3:
if (in_time <= g_count) {
y += 1;
if (count % 10 == 0) {
x += 1;
}
}
break;
}
//画面からはみ出したら、deadflag(はみ出すか死ぬかのフラグ)をtrueにする。
if (g_count >= stop_time) {
if (OutCheck()) {
deadflag = true;
}
}
++count;
}
}
void ENEMY::Shot()
{
//CONTROLクラスの参照
CONTROL &control = CONTROL::GetInstance();
double px, py;
//発射タイミングになったら、フラグを立てる
if (shot_time == g_count)
{
sflag = true;
}
//フラグ立ってるときだけ
if (sflag) {
//プレイヤーの位置取得
control.GetPlayerPosition(&px, &py);
//敵とプレイヤーとの座標の差から逆正接を求める。
//初回だけ実行
if (scount == 0)
rad = atan2(py - y, px - x);
switch (s_pattern)
{
//前方に発射
case 0:
//5ループに一回発射。20までなので5発発射。
if (scount % 5 == 0 && scount <= 20)
{
for (int i = 0; i < ENEMY_SNUM; ++i)
{
//フラグが立ってない弾を探して、座標等をセット
if (shot[i].flag == false)
{
shot[i].flag = true;
shot[i].x = x;
shot[i].y = y;
shot[i].rad = rad;
break;
}
}
}
break;
//プレイヤーに向かって直線ショット
case 1:
//6ループに一回発射。54までのなので10発発射。
if (scount % 6 == 0 && scount < 54)
{
for (int i = 0; i < ENEMY_SNUM; i++)
{
//フラグが立っていない弾を探して、座標等をセット
if (shot[i].flag == false)
{
shot[i].flag = true;
shot[i].x = x;
shot[i].y = y;
shot[i].rad = rad;
break;
}
}
}
break;
//3直線ショット
case 2:
//10ループに一回発射。1ループ3発なので5ループさせると15発発射
if (scount % 10 == 0 && scount <= 40)
{
for (int i = 0; i < ENEMY_SNUM; i++)
{
//フラグが立っていない弾を探して、座標等をセット
if (shot[i].flag == false)
{
shot[i].flag = true;
shot[i].x = x;
shot[i].y = y;
//0の時は左寄り
if (num == 0)
{
//敵とプレイヤーとの逆正接から10度引いたらラジアンを代入
shot[i].rad = rad - (10 * 3.14 / 180);
}
//1の時はプレイヤーに一直線
else if (num == 1)
{
//敵とプレイヤーとの逆正接を代入
shot[i].rad = rad;
}
//2の時は右寄り
else if (num == 2)
{
//敵とプレイヤーの逆正接から10度足したらラジアンを代入
shot[i].rad = rad + (10 * M_PI / 180);
}
++num;
//3発発射したら、numを0にしてループを抜ける
if (num == 3)
{
num = 0;
break;
}
}
}
}
break;
//乱射ショット
case 3:
//ループ毎に1発発射
for (int i = 0; i < ENEMY_SNUM; i++)
{
//フラグが立ってない弾を探して、座標等をセット
if (shot[i].flag == false)
{
shot[i].flag = true;
shot[i].x = x;
shot[i].y = y;
//初回だけ乱数初期化
if (num == 0)
srand((unsigned int)time(NULL));
shot[i].rad = atan2(py - y, px - x) - (60 * M_PI / 180) + ((rand() % 120)*M_PI / 180);
++num;
break;
}
}
break;
}
//フラグが立ってる弾の数
int s = 0;
//フラグ立ってる弾だけ、弾の移動を行う
for (int i = 0; i < ENEMY_SNUM; ++i) {
if (shot[i].flag) {
switch (shot[i].pattern) {
//単純に下に発射
case 0:
shot[i].y += shot[i].speed;
break;
case 1:
shot[i].x += shot[i].speed*cos(shot[i].rad);
shot[i].y += shot[i].speed*sin(shot[i].rad);
break;
case 2:
shot[i].x += shot[i].speed*cos(shot[i].rad);
shot[i].y += shot[i].speed*sin(shot[i].rad);
break;
case 3:
shot[i].x += shot[i].speed*cos(shot[i].rad);
shot[i].y += shot[i].speed*sin(shot[i].rad);
break;
}
//弾が画面をはみ出たらフラグを戻す。
if (ShotOutCheck(i)) {
shot[i].flag = false;
continue;
}
++s;
}
}
//sがゼロということは発射中の弾がない。
//かつdeadflagがTRUEということはこの敵のクラスは消滅させてもよい
if (s == 0 && deadflag) {
//敵クラス消滅フラグをTRUEにする
endflag = true;
}
++scount;
}
}
bool ENEMY::ShotOutCheck(int i)
{
//弾が画面をはみ出たらフラグを戻す。
if (shot[i].x < -20 || shot[i].x>420 || shot[i].y < -20 || shot[i].y>500)
{
return true;
}
else
{
return false;
}
}
bool ENEMY::OutCheck()
{
if (x<-50 || x>520 || y<-50 || y>530) {
return true;
}
else {
return false;
}
}
void ENEMY::Draw()
{
int temp;
//弾から最初に描画
for (int i = 0; i < ENEMY_SNUM; ++i)
{
if (shot[i].flag)
{
if (stype == 0 || state == 2)
{
DrawGraph(shot[i].x - shot[i].width / 2, shot[i].y - shot[i].height / 2, shot[i].gh, true);
}
else
{
DrawRotaGraph(shot[i].x, shot[i].y, 1.0, shot[i].rad + (90 * M_PI / 180), shot[i].gh, true);
}
}
}
if (!endflag)
{
temp = count % 40 / 10;
if (temp == 3)
temp = 1;
DrawGraph(x, y, gh[temp], TRUE);
}
}
bool ENEMY::All()
{
Move();
Shot();
OutCheck();
Draw();
++count;
return endflag;
}
[enemy.h]
class ENEMY {
private:
//座標とグラフィックハンドル
double x, y;
int gh[3];
//画像サイズ
int width, height;
//出現、停止、帰還、発射タイミング
int in_time, stop_time, out_time, shot_time;
//敵の種類
int type;
//弾の種類
int stype;
//移動パターン
int m_pattern;
//ショットパターン
int s_pattern;
//HP
int hp;
//アイテム
int item;
//敵が出現してからのカウント
int count;
//発射した段数
int num;
//発射直後のラジアン
double rad;
//敵消滅フラグ
bool deadflag;
//敵クラス消滅フラグ
bool endflag;
//弾構造体
E_SHOT shot[ENEMY_SNUM];
//ショットが撃てるようになったかのフラグ
bool sflag;
//ショットが打てるようになってからのカウント
int scount;
private:
void Move();
void Shot();
void Draw();
bool OutCheck();
bool ShotOutCheck(int i);
public:
bool All();
void GetPosition(double *x, double *y);
ENEMY(int type, int stype, int m_pattern, int s_pattern, int in_time, int stop_time, int shot_time, int out_time,
int x, int y, int speed, int hp, int item);
};
[player.cpp]
#include "pch.h"
#include"control.h"
PLAYER::PLAYER()
{
//画像読み込み
if(-1==LoadDivGraph("DATA/CHR/charall_2.png",12,3,4,29,40,gh)){
MSG("エラー発生");
}
width=29;
height=40;
//移動係数
move=1.0f;
//横方向と縦方向のカウント数。
xcount=0,ycount=0;
//添字用変数
ix=0,iy=0,result=0;
//初期位置
x=180;
y=400;
//生死確認
life=true;
//弾初期化
memset(shot, 0, sizeof(shot));
//弾画像読み込み
int temp = LoadGraph("DATA/BG/shot_2.png");
int w, h;
GetGraphSize(temp, &w, &h);
//フラグ全部falseにしとく
//グラッフィックハンドルと画像のサイズを代入しとく
for (int i = 0; i < PSHOT_NUM; ++i)
{
shot[i].flag = false;
shot[i].gh = temp;
shot[i].width = w;
shot[i].height = h;
}
count = 0;
}
void PLAYER::GetPosition(double *x, double *y)
{
*x = this->x;
*y = this->y;
}
void PLAYER::Move()
{
if(key[KEY_INPUT_LEFT]==1 || key[KEY_INPUT_RIGHT]==1){
if(key[KEY_INPUT_UP]==1 || key[KEY_INPUT_DOWN]==1){
//移動係数を0.71に設定
move=0.71f;
}else{
//斜めじゃなければ1.0に設定
move=1.0f;
}
}else if(key[KEY_INPUT_UP]==1 || key[KEY_INPUT_DOWN]==1){
move=1.0f;
}
if(key[KEY_INPUT_LEFT]==1){
x-=(int)PLAYER_SPEED*move;
}
if(key[KEY_INPUT_RIGHT]==1){
x+=(int)PLAYER_SPEED*move;
}
if(key[KEY_INPUT_UP]==1){
y-=(int)PLAYER_SPEED*move;
}
if(key[KEY_INPUT_DOWN]==1){
y+=(int)PLAYER_SPEED*move;
}
//左キーが押されてて、かつxcountが0以上なら0にしてから1引く。
//それ以外は1引く
if(key[KEY_INPUT_LEFT]==1){
if(xcount>0)
xcount=0;
--xcount;
}
//右キーが押されてて、かつxcountが0以下なら0にしてから1足す。
//それ以外は1引く
if(key[KEY_INPUT_RIGHT]==1){
if(xcount<0)
xcount=0;
++xcount;
}
//上キーが押されてて、かつycountが0以上なら0にしてから1引く。
//それ以外は1引く
if(key[KEY_INPUT_UP]==1){
if(ycount>0)
ycount=0;
--ycount;
}
//下キーが押されてて、かつycountが0以下なら0にしてから1足す。
//それ以外は1足す
if(key[KEY_INPUT_DOWN]==1){
if(ycount<0)
ycount=0;
++ycount;
}
//カウント数から添字を求める。
ix=abs(xcount)%30/10;
iy=abs(ycount)%30/10;
//xカウントがプラスなら右向きなので2行目の先頭添字番号を足す。
if(xcount>0){
ix+=3;
result=ix;
}else if(xcount<0){
//マイナスなら左向きなので、4行目の先頭添字番号を足す。
ix+=9;
result=ix;
}
//yカウントがプラスなら下向きなので、3行目の先頭添字番号を足す。
if(ycount>0){
iy+=6;
result=iy;
}else if(ycount<0){
//1行目の先頭添字番号は0なので何もする必要なし。(分かりやすくするために書いときました)
iy+=0;
result=iy;
}
//斜め移動の場合は横顔を優先
if(move==0.71f)
result=ix;
//押されてなければカウントをゼロにする。
if(key[KEY_INPUT_LEFT]!=1 && key[KEY_INPUT_RIGHT]!=1){
xcount=0;
}
if(key[KEY_INPUT_UP]!=1 && key[KEY_INPUT_DOWN]!=1){
ycount=0;
}
//< span class="strees">
//キャラの移動制御
if (x > 400 - MARGIN)
{
x = 400 - MARGIN;
}
else if (x < MARGIN)
{
x = MARGIN;
}
if (y > 480 - height / 2 - MARGIN)
{
y = 480 - height / 2 - MARGIN;
}
else if (y < height / 2 + MARGIN)
{
y = height / 2 + MARGIN;
}
//←キーが押されてて、かつxcountが0以上なら0にしてから1引く
//それ以外は1引く
if (key[KEY_INPUT_LEFT] == 1)
{
if (xcount > 0)
xcount = 0;
--xcount;
}
//→キーが押されてて、かつxcountが0以下なら0にしてから1足す
//それ以外は1引く
if (key[KEY_INPUT_RIGHT] == 1)
{
if (xcount < 0)
xcount = 0;
++xcount;
}
//↑キーが押されてて、かつycountが0以下なら0にしてから1足す
//それいがいは1引く
if (key[KEY_INPUT_UP] == 1)
{
if (ycount > 0)
ycount = 0;
--ycount;
}
//↓キーが押されてて、かつycountが0以下なら0にしてから1足す
//それいがいは1足す
if (key[KEY_INPUT_DOWN] == 1)
{
if (ycount < 0)
ycount = 0;
++ycount;
}
//カウント数から添字を求める
ix = abs(xcount) % 30 / 10;
iy = abs(ycount) % 30 / 10;
//xカウントがプラスなら右向きなので2行目の先頭添字番号を足す
if (xcount > 0)
{
ix += 3;
result = ix;
}
else if (xcount < 0)
{
//マイナスなら左向きなので4行目の先頭添字を足す
ix += 9;
result = ix;
}
//yカウントがプラスなら下向きなので,3行目の先頭添字を足す
if (ycount > 0)
{
iy += 6;
result = iy;
}
else if (ycount < 0)
{
//1行目の先頭添字番号は0なので何も刷る必要なし
iy += 0;
result = iy;
}
//斜めの移動の場合は横顔を優先
if (move == 0.71f)
result = ix;
//描画
DrawGraph(x - width / 2, y - height / 2, gh[result], TRUE);
//押されていなければカウントをゼロにする
if (key[KEY_INPUT_LEFT] != 1 && key[KEY_INPUT_RIGHT != 1])
{
xcount = 0;
}
if (key[KEY_INPUT_UP] != 1 && key[KEY_INPUT_DOWN] != 1)
{
ycount = 0;
}
}
void PLAYER::Draw()
{
//弾描画
for (int i = 0; i < PSHOT_NUM; i++)
{
if (shot[i].flag)
{
DrawGraph(shot[i].x - shot[i].width / 2,
shot[i].y - shot[i].height / 2, shot[i].gh, TRUE);
}
}
//生きてれば描画
if(life){
//描画
DrawGraph(x-width/2,y-height/2,gh[result],TRUE);
}
}
void PLAYER::Shot()
{
//キーが押されててかつ、6ループに1回発射
if (key[KEY_INPUT_Z] == 1 && count % 6 == 0)
{
for (int i = 0; i < PSHOT_NUM; i++)
{
if (shot[i].flag == false)
{
shot[i].flag = true;
shot[i].x = x;
shot[i].y = y;
break;
}
}
}
//弾を移動させる処理
for (int i = 0; i < PSHOT_NUM; i++)
{
//発射している弾だけ
if (shot[i].flag)
{
shot[i].y -= PSHOT_SPEED;
//画面の外にはみ出したらフラグを戻す
if (shot[i].y < -10)
{
shot[i].flag = false;
}
}
}
}
void PLAYER::All()
{
Move();
Shot();
Draw();
count++;
}
[payer.h]
class PLAYER{
private:
//x座標,y座標
double x,y;
//画像幅
int width,height;
//グラフィックハンドル格納用配列
int gh[12];
//移動係数
float move;
//横方向と縦方向のカウント数。
int xcount,ycount;
//添字用変数
int ix,iy,result;
//生きてるかどうかのフラグ
bool life;
//弾
SHOT shot[PSHOT_NUM];
//カウント
int count;
private:
void Move();
void Draw();
void Shot();
public:
PLAYER();
void GetPosition(double *x, double *y);
void All();
};