操作キャラが消えない

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

操作キャラが消えない

#1

投稿記事 by yotumoto » 8年前

・敵の弾が当たる
    ↓
・プレイヤーを消す
    ↓
・点滅されながら、画面下から出てくる
    ↓
・点滅をやめ、動かせるようにする

という流れでプログラムを組んでいて
敵の弾が当たったときは動かせなくなるのですが
プレイヤーの描画が残ったままで消えません

点滅して画面下からプレイヤーが復帰するので
画面内にプレイヤーが2人描画されてしまいます。

プレイヤーが点滅をやめたら(座標が初期位置に戻ると)
死んだときの描画は消え、動かせるようになります。

敵の死んだときの描画等はできたのですが
プレイヤーだけなぜかうまくいきません。

分かる方いましたら教えていただきたいです
一応敵のソースも貼っておきます。

コード:

[player.cpp]
#include "pch.h"
#include"control.h"

PLAYER::PLAYER()
{
	//画像読み込み
	
	if(-1==LoadDivGraph("DATA/CHR/char_org.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 = 1;

	//弾初期化
	memset(shot, 0, sizeof(shot));

	//弾画像読み込み
	int temp = LoadGraph("DATA/BG/shot_org.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;
	dcount = 0;
	damageflag = false;
	s_dead = false;

}

void PLAYER::SetShotFlag(int index, bool flag)
{
	shot[index].flag = flag;
}

bool PLAYER::GetShotSound()
{
	return s_shot;
}

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(damageflag){
		if (dcount > 20) {
			if (dcount % 2 == 0) {
				SetDrawBlendMode(DX_BLENDMODE_ALPHA, 120);
				DrawGraph(PLAYER_INITX - width / 2, PLAYER_INITY - height / 2 + 60 - (dcount - 20), gh[1], TRUE);

				SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0);
			}
			else {
				DrawGraph(PLAYER_INITX - width / 2, PLAYER_INITY - height / 2 + 60 - (dcount - 20), gh[1], TRUE);
			}
		}
		++dcount;
	
		if (dcount == 80)
		{
			damageflag = false;
			dcount = 0;
			//座標を初期値に戻す
			x = PLAYER_INITX;
			y = PLAYER_INITY;

			//上向きの画像にする
			result = 1;
		}
		else 
		{
			//通常描画
			DrawGraph(x - width / 2, y - height / 2, gh[result], TRUE);
		}
	}
}

void PLAYER::Shot()
{
	s_shot = false;

	if (!damageflag) {

		//キーが押されててかつ、6ループに一回発射
		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;
				}
			}
			//ショットサウンドフラグを立てる
			s_shot = true;
		}

		//弾を移動させる処理
		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;
				}
			}
		}
	}
}

bool PLAYER::GetShotPosition(int index, double *x, double *y)
{
	if (shot[index].flag) {
		*x = shot[index].x;
		*y = shot[index].y;
		return true;
	}
	else {
		return false;
	}

}

void PLAYER::SetDamageFlag()
{
	damageflag = true;
}

bool PLAYER::GetDamageFlag()
{
	return damageflag;
}

bool PLAYER::All()
{
	//消滅していないときだけ実行
	if (!damageflag) {
		Move();
	}
	Shot();
	Draw();
	count++;

	return endflag;
}

コード:

[player.h]
class PLAYER{
private:
	//x座標,y座標
	double x,y;

	//画像幅
	int width,height;

	//グラフィックハンドル格納用配列
	int gh[12];

	//移動係数
	float move;

	//横方向と縦方向のカウント数。
	int xcount,ycount;
	//添字用変数
	int ix,iy,result;

	//プレイヤーのライフ
	int life;
	bool damageflag;
	bool endflag;
	//ダメージ中のカウント
	int dcount;

	//弾
	SHOT shot[PSHOT_NUM];

	//カウント
	int count;

	bool s_shot;
	bool s_dead;

private:
	void Move();
	void Draw();
	void Shot();

public:
	bool All();
	PLAYER();
	bool GetShotSound();
	bool GetShotPosition(int index, double *x, double *y);
	void SetShotFlag(int index, bool flag);
	void GetPosition(double *x, double *y);
	void SetDamageFlag();
	bool GetDamageFlag();

};

コード:

[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_org.png", 3, 1, 3, 27, 25, gh);
	}

	int temp = 0;
	//弾画像読み込み
	switch (stype)
	{
	case 0:
		temp = LoadGraph("DATA/BG/enemyshot_org1.png");
		break;
	case 1:
		temp = LoadGraph("DATA/BG/enemyshot_org1.png");
		break;
	case 2:
		temp = LoadGraph("DATA/BG/enemyshot_org2.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;
	s_shot = false;
	s_dead = false;
	
}


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) {
		//ショット音フラグを戻す
		s_shot = false;

		//プレイヤーの位置取得
		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;
					}
				}
				//ショットサウンドフラグを立てる
				s_shot = true;

			}
			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;
					}
				}
				//ショットサウンドフラグを立てる
				s_shot = true;

			}
			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) {

							//敵とプレイヤーとの逆正接から30度引いたラジアンを代入
							shot[i].rad = rad - (10 * 3.14 / 180);

						}
						else if (num == 1) {
							//敵とプレイヤーとの逆正接を代入
							shot[i].rad = rad;

						}
						else if (num == 2) {
							//敵とプレイヤーとの逆正接から30度足したラジアンを代入
							shot[i].rad = rad + (10 * M_PI / 180);

						}
						++num;

						//3発発射したら,numを0にしてループを抜ける。
						if (num == 3) {
							num = 0;
							break;
						}
					}
				}
				//ショットサウンドフラグを立てる
				s_shot = true;

			}
			break;

			//乱射ショット
		case 3:
			//10ループに一回発射。42までなので15発発射。
			if (scount % 3 == 0 && scount <= 42) {
				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;
					}
				}
				//ショットサウンドフラグを立てる
				s_shot = true;

			}
			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;
			s_dead = 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 || stype == 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 (!deadflag) {

		temp = count % 40 / 10;
		if (temp == 3)
			temp = 1;

		DrawGraph(x - width / 2, y - height / 2, gh[temp], TRUE);
	}
}

void ENEMY::GetPosition(double *x, double *y)
{
	*x = this->x;
	*y = this->y;
}

bool ENEMY::GetShotPosition(int index, double *x, double *y)
{
	if (shot[index].flag)
	{
		*x = shot[index].x;
		*y = shot[index].y;
		return true;
	}
	else
	{
		return false;
	}
}

void ENEMY::SetShotFlag(int index, bool flag)
{
	shot[index].flag = flag;
}

int ENEMY::GetShotType()
{
	return stype;
}

bool ENEMY::GetShotSound()
{
	return s_shot;
}

bool ENEMY::GetDeadSound()
{
	return s_dead;
}

void ENEMY::SetDeadFlag()
{
	deadflag = true;
}

bool ENEMY::GetDeadFlag()
{
	return deadflag;
}

bool ENEMY::All()
{
	Move();
	Shot();
	OutCheck();
	Draw();
	GetShotSound();

	++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;

	bool s_shot;
	bool s_dead;

private:
	void Move();
	void Shot();
	void Draw();
	bool OutCheck();
	bool ShotOutCheck(int i);

public:
	bool All();
	void GetPosition(double *x, double *y);
	bool GetShotPosition(int index, double *x, double *y);
	void SetShotFlag(int index, bool flag);
	int GetShotType();
	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);
	bool GetShotSound();
	void SetDeadFlag();
	bool GetDeadFlag();
	bool GetDeadSound();
};

コード:

[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);
	}

	//サウンドファイル読み込み
	s_eshot = LoadSoundMem("DATA/SOUND/enemyshot.wav");
	s_pshot = LoadSoundMem("DATA/SOUND/magic3.mp3");

	s_edead = LoadSoundMem("DATA/SOUND/enemydead.wav");
	s_pdead= LoadSoundMem("DATA/SOUND/enemydead.wav");

	eshot_flag = false;
	pshot_flag = false;
	edead_flag = false;
	pdead_flag = false;
}

bool CONTROL::CircleCollision(double c1, double c2, double cx1, double cx2, double cy1, double cy2)
{

	double hlength = c1 + c2;
	double xlength = cx1 - cx2;
	double ylength = cy1 - cy2;

	if (hlength*hlength >= xlength*xlength + ylength*ylength) {
		return true;
	}
	else {
		return false;
	}
}


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()
{
	//サウンドフラグを初期化
	eshot_flag = pshot_flag = edead_flag = pdead_flag = false;

	//描画領域を指定
	SetDrawArea(MARGIN, MARGIN, MARGIN + 380, MARGIN + 460);

	back->All();

	player->All();
	//プレイヤーサウンドフラグチェック
	if (player->GetShotSound()) {
		pshot_flag = true;
	}

	/*if (player->GetShotSound()) {
		pdead_flag = true;
	}*/

	for (int i = 0; i<ENEMY_NUM; i++) {
		if (enemy[i] != NULL) {
			//敵ショットサウンドフラグチェック
			if (enemy[i]->GetShotSound()) {
				eshot_flag = true;
			}

			if (enemy[i]->GetDeadSound()) {
				edead_flag = true;
			}

			if (enemy[i]->All()) {
				delete enemy[i];
				enemy[i] = NULL;
			}
		}
	}
	//当たり判定
	CollisionAll();

	SoundAll();

	++g_count;
}



void CONTROL::SoundAll()
{

	if (pshot_flag) {
		PlaySoundMem(s_pshot, DX_PLAYTYPE_BACK);
	}  

	if (eshot_flag) {
		PlaySoundMem(s_eshot, DX_PLAYTYPE_BACK);
	}

	if (edead_flag) { 
		PlaySoundMem(s_edead, DX_PLAYTYPE_BACK);
	}

}

void CONTROL::CollisionAll()
{
	double px, py, ex, ey;

	bool tempflag = false;

	//操作キャラの弾と敵との当たり判定
	for (int i = 0; i<PSHOT_NUM; ++i) {
		if (player->GetShotPosition(i, &px, &py)) {
			for (int s = 0; s<ENEMY_NUM; ++s) {
				//敵クラスのポインタがNULLじゃない、かつdeadflagがfalse(死んでない&帰還してない)
				if (enemy[s] != NULL && !enemy[s]->GetDeadFlag()) {
					enemy[s]->GetPosition(&ex, &ey);
					//当たり判定
					if (CircleCollision(PSHOT_COLLISION, ENEMY1_COLLISION, px, ex, py, ey)) {
						//当たっていれば、deadflagを立てる
						enemy[s]->SetDeadFlag();
						//当たった弾のフラグを戻す
						player->SetShotFlag(i, false);
						//敵消滅音フラグセット
						edead_flag = true;
					}
				}
			}
		}
	}

	//敵の弾と操作キャラとの当たり判定
	//プレイヤーが生きていれば
	if (!player->GetDamageFlag()) {
		player->GetPosition(&px, &py);
		for (int i = 0; i < ENEMY_NUM; i++) {
			if (enemy[i] != NULL) {
				for (int s = 0; s < ENEMY_SNUM; s++)
				{
					//弾フラグが立っていればtrueを返す
					if (enemy[i]->GetShotPosition(s, &ex, &ey)) {
						//弾によって当たり判定が違うのでswitch文で分岐
						switch (enemy[i]->GetShotType()) {
						case 0:
							//当たっていれば
							if (CircleCollision(PLAYER_COLLISION, ESHOT0_COLLISION, px, ex, py, ey))
							{
								tempflag = true;
							}
							break;

						case 1:
							if (CircleCollision(PLAYER_COLLISION, ESHOT1_COLLISION, px, ex, py, ey))
							{
								tempflag = true;
							}
							break;

						case 2:
							if (CircleCollision(PLAYER_COLLISION, ESHOT2_COLLISION, px, ex, py, ey))
							{
								tempflag = true;
							}
							break;

						}
						if (tempflag) {
							//操作キャラのdamageflagを立てる
							player->SetDamageFlag();
							//弾を消す
							enemy[i]->SetShotFlag(s,false);
							//プレイヤー消滅音フラグを立てる
							pdead_flag = true;
							//一時フラグを戻す
							tempflag = false;
						}
					}
				}
			}
		}
	}

}


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"
#include"title.h"

class CONTROL{
private:
	//プレイヤークラス
	PLAYER *player;
	
	//背景クラス
	BACK *back;

	//エネミークラス
	ENEMY *enemy[ENEMY_NUM];

	//サウンドハンドル
	int s_eshot;
	int s_pshot;
	int s_edead;
	int s_pdead;

	//サウンドを鳴らすかどうかのフラグ
	bool eshot_flag;
	bool pshot_flag;


	//敵死亡
	bool edead_flag;

	//プレイヤー死亡
	bool pdead_flag;

private:
	CONTROL();
	~CONTROL();
	void SoundAll();

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;
	}
	bool CircleCollision(double c1, double c2, double cx1, double cx2, double cy1, double cy2);
	void CollisionAll();

};

コード:

[pch.h]
//警告を消すための記述
#pragma warning(disable:4244)
#define _CRT_SECURE_NO_WARNINGS

//DXライブラリとdefine.hの取り込み
#include "DxLib.h"
#include "define.h"

コード:

#include <windows.h>

//プレイヤーの歩くスピード
#define PLAYER_SPEED 4

#define PLAYER_INITX 180
#define PLAYER_INITY 400
//x = 180;
//y = 400;

//座標取得
#define MARGIN 10

//背景スクロールスピード
#define SCROLL_SPEED 2

//弾処理
#define PSHOT_NUM 20
#define PSHOT_SPEED 14

//当たり判定用半径定義
#define PLAYER_COLLISION 4
#define ENEMY1_COLLISION 14

#define PSHOT_COLLISION 3
#define ESHOT0_COLLISION 10
#define ESHOT1_COLLISION 3
#define ESHOT2_COLLISION 2


//メッセージボックス
#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

yotumoto

Re: 操作キャラが消えない

#2

投稿記事 by yotumoto » 8年前

http://bituse.info/game/shot/16

ここのサイトを参考にして制作しています。

hide

Re: 操作キャラが消えない

#3

投稿記事 by hide » 8年前

現象とコードだけだと、ちゃんと調べたの?って思われてしまいます。
とりあえずアドバイスとしては、現象が発生する最低限までコードを削ってみては?
他人のコードを読むのは大変なので、みんな長ければ長いほどやりたがらないですよ。
コピペして再現環境つくるのもめんどくさいですしね。

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

Re: 操作キャラが消えない

#4

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

dcountが21~79のとき、
PLAYER::Draw()内のif(damageflag)内でDrawGraph()が2回呼び出され、
2体の主人公が描画されそうです。

でも、dcountが0~20の時は1体しか描画されなそうなんだけどな…?
(動かさずに適当に読んだだけなので、間違っているかもしれません)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: 操作キャラが消えない

#5

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

damageflagがfalseの時しか実行されないから今回の問題の原因ではなさそうだとは思いますが、
(特にPLAYER::Draw()が別にあるのに) PLAYER::Move()内で描画してしまっているのも気持ち悪いですね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

とけい

Re: 操作キャラが消えない

#6

投稿記事 by とけい » 8年前

>http://bituse.info/game/shot/16
>ここのサイトを参考にして制作しています。

私も上記のサイトで勉強させて頂きました。。。
(グレイズで投げ出しました・・・)

みけCATさまの指摘通り、
Draw()内で中括弧がずれています。

コード:

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(damageflag){
		if(dcount>20){
			if(dcount%2==0){
				SetDrawBlendMode(DX_BLENDMODE_ALPHA,140);
				DrawGraph(PLAYER_INITX-width/2,PLAYER_INITY-height/2+60-(dcount-20),gh[1],TRUE);
				SetDrawBlendMode(DX_BLENDMODE_NOBLEND,0);
			}else{
				DrawGraph(PLAYER_INITX-width/2,PLAYER_INITY-height/2+60-(dcount-20),gh[1],TRUE);
			}
		}
		++dcount;
		if(dcount==80){
			damageflag=false;
			dcount=0;
			//座標を初期値に戻す
			x=PLAYER_INITX;
			y=PLAYER_INITY;
			//上向きの画像にする
			result=1;
		}
	}else{                                                                                       //←ここの中括弧ずれ?
		//通常描画
		DrawGraph(x-width/2,y-height/2,gh[result],TRUE);
	}
}
オフトピック
私はすでに投げてしまったので、熱意も記憶もあやふやですが
グレイズができたら教えて欲しい。。。かも

yotumoto

Re: 操作キャラが消えない

#7

投稿記事 by yotumoto » 8年前

{ }の位置を修正すると
無事治りました!!
ありがとうございます!!

閉鎖

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