SEがうまく再生されません。

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

SEがうまく再生されません。

#1

投稿記事 by mattun » 8年前

プレイヤーの弾のSEはうまく再生されるのですが
敵の弾のSEがうまく再生されません
敵の弾が発射していない時でもバッググラウンドで再生されてしまいます(永続的に)
何度も見直したのですが原因が分かりません
分かる方いましたら教えていただきたいです。
下記サイトを参考にして制作しています。
http://bituse.info/game/shot/14

コード:

[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 = 0;
 //弾画像読み込み
 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) {
  //ショット音フラグを戻す
  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;
  }
  ++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::SetDeadFlag()
{
 deadflag = true;
}
bool ENEMY::GetShotSound()
{
 return s_shot;
}
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;
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);
 bool GetShotSound();
 void SetDeadFlag();
 bool GetDeadFlag();
};

コード:

[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::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 (shot[i].flag)
  {
   DrawGraph(shot[i].x - shot[i].width / -1,
    shot[i].y - shot[i].height / 1, shot[i].gh, TRUE);
  }
  if (shot[i].flag)
  {
   DrawGraph(shot[i].x - shot[i].width / 0.5,
    shot[i].y - shot[i].height / 1, shot[i].gh, TRUE);
  }*/

 }
 //生きてれば描画
 if(life){
  //描画
  DrawGraph(x-width/2,y-height/2,gh[result],TRUE);
 }
}
void PLAYER::Shot()
{
 s_shot = false;
 //キーが押されててかつ、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::All()
{
 Move();
 Shot();
 Draw();
 GetShotSound();
 count++;
}

コード:

[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;
 //生きてるかどうかのフラグ
 bool life;
 //弾
 SHOT shot[PSHOT_NUM];
 //カウント
 int count;
 bool s_shot;
private:
 void Move();
 void Draw();
 void Shot();
public:
 PLAYER();
 void GetPosition(double *x, double *y);
 bool GetShotSound();
 bool GetShotPosition(int index, double *x, double *y);
 void All();
 void SetShotFlag(int index, bool flag); 
};

コード:

[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/playershot.wav");
 edead_flag = LoadSoundMem("DATA/SOUND/enemydead.wav");

 eshot_flag = false;
 pshot_flag = false;
 edead_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 = false;
 //描画領域を指定
 SetDrawArea(MARGIN, MARGIN, MARGIN + 380, MARGIN + 460);
 back->All();
 player->All();
 //プレイヤーサウンドフラグチェック
 if (player->GetShotSound()) {
  pshot_flag = true;
 }
 for (int i = 0; i<ENEMY_NUM; i++) {
  if (enemy[i] != NULL) {
   //敵ショットサウンドフラグチェック
   if (enemy[i]->GetShotSound()) {    //ここの行をコメントアウトすると
    eshot_flag = true;         //バックグラウンドで敵の弾のSEが永続的に再生バグが治ったので
   }                       //恐らくここのコードが間違っているのかなと自分は思っています。
   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_eshot, DX_PLAYTYPE_BACK);
 }
}
void CONTROL::CollisionAll()
{
 double px, py, ex, ey;
 //操作キャラの弾と敵との当たり判定
 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;
     }
    }
   }
  }
 }
}


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;
 //サウンドを鳴らすかどうかのフラグ
 bool eshot_flag;
 bool pshot_flag;
 //敵死亡
 bool edead_flag;
 //bool s_shot;
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"

コード:

[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 PLAYER_COLLISION 6
#define ENEMY1_COLLISION 14
#define PSHOT_COLLISION 3
#define ESHOT1_COLLISION 12
#define ESHOT2_COLLISION 3
#define ESHOT3_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

コード:

[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 ;   // エラーが起きたら直ちに終了
 }

 while(ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && GetHitKeyStateAll(key)==0){
  
 
  CONTROL::GetInstance().All();
  
 }

 DxLib_End() ;    // DXライブラリ使用の終了処理
 return 0 ;    // ソフトの終了 
}

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

Re: SEがうまく再生されません。

#2

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

スマホでざっと読んだだけなので自信は無いですが、発射タイミングになるまで敵のs_shotが初期化されていないのがまずいかもしれないと思いました。
mattun さんが書きました: //ここの行をコメントアウトすると
//バックグラウンドで敵の弾のSEが永続的に再生バグが治ったので
//恐らくここのコードが間違っているのかなと自分は思っています。
本当にこれでバグが治ったのですか?
単にSE再生機能を切って不都合が発生しないように隠しただけではないですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

mattun

Re: SEがうまく再生されません。

#3

投稿記事 by mattun » 8年前

回答者さんの仰っている通り
SE再生処理を伏せているだけでした。

enemyのs_shotを初期化すると
正常に作動しました

ありがとうございます。

閉鎖

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