ページ 11

STG:自機のショットが発射されません

Posted: 2012年8月25日(土) 04:13
by たれかつ
初めまして。
使用しているのはVC++2010です。
今、「龍神録プログラミングの館」と「新・C言語~ゲームプログラミングの館~」を見ながらSTGを作っています。
(http://dixq.net/rp/17.html)を参考にしながら自機にショットを発射させようとしているのですが、うまくいきません。
うまくいかない、というのは、
・自機の前方から一度に二発発射させようとしている→一発のみ
・発射させたあと→一瞬で画面から消える
・一瞬で画面から消えた後→x,y座標ともに-1085862613のようなとんでもない位置に移動している
といった事になっています。
座標が変わる部分に関しては、ほぼ丸写しのようなものになっているにもかかわらず、なぜこのようになってしまうのかがわからなく、どこが間違えているのかの見当もつきません。
見づらい部分もあると思いますが、自機のショットに関するコードがありますのでよろしくお願いします

コード:

#define PI 3.1415926f
#define PS_MAX 8
#define FIELD_MAX_X 450
#define FIELD_MAX_Y 440
#define FIELD_X 150
#define FIELD_Y 30
static int m_count;
static int m_pshot;
static int m_i,m_j;
static float m_dran_x,m_dran_y;
static int m_pshotpos_x[2] = {-10,10};
static int m_pshotpos_y[2] = {-30,-30};
typedef struct {
	float x,y;	//座標
	int flag;			//フラグ
} pshot_t;
pshot_t pshot[PS_MAX];
void player_shot_initalize()
{
	m_pshot = LoadGraph("画像/player_shot.png");
	for (m_i = 0;m_i < PS_MAX;++m_i) {
		pshot[m_i].flag = 0;
	}
}

void player_shot_update(float p_x,float p_y)
{
	for(m_i = 0;m_i < PS_MAX; ++m_i) {
		if(pshot[m_i].flag == 1) {
			m_dran_x = 3 + 12 / 2;
			m_dran_y = 3 + 17 / 2;
			pshot[m_i].x += cos(PI / 2) * 3;
			pshot[m_i].y += sin(PI / 2) * 3;
			if (pshot[m_i].x <-m_dran_x || pshot[m_i].x > FIELD_MAX_X + m_dran_x ||
				pshot[m_i].y <-m_dran_y || pshot[m_i].y < FIELD_MAX_Y + m_dran_y) {
					pshot[m_i].flag = 0;
		    } 
		}
	}
	if (keyboard_get(KEY_INPUT_Z) > 0) {
		++m_count;
		if (m_count % 10 == 0) {
			for (m_i = 0;m_i < 2;m_i++) {
				for(m_j = 0;m_j < 2;++m_j) {
					if (pshot[m_j].flag == 0) {
						pshot[m_j].flag = 1;
						pshot[m_j].x = p_x + m_pshotpos_x[m_i];
						pshot[m_j].y = p_y + m_pshotpos_y[m_i];
					}
				}
			} 
		}
	} else {
			m_count = 0;
	}
}
void player_shot_draw()
{
	for (m_i = 0;m_i < PS_MAX;++m_i) {
		if (pshot[m_i].flag > 0) {
			DrawRotaGraphF(pshot[m_i].x,pshot[m_i].y,1.0,0.0,m_pshot,true);
		}
	}
}

void player_shot_finalize()
{
	DeleteGraph(m_pshot);
}

Re: STG:自機のショットが発射されません

Posted: 2012年8月25日(土) 05:47
by box
たれかつ さんが書きました:

コード:

				for(m_j = 0;m_j < 2;++m_j) {
					if (pshot[m_j].flag == 0) {
						pshot[m_j].flag = 1;
						pshot[m_j].x = p_x + m_pshotpos_x[m_i];
						pshot[m_j].y = p_y + m_pshotpos_y[m_i];
					}
				}
何もわかっていなくて申し訳ありませんが、このループは2回まわるだけで大丈夫なんですね?
他のところではPS_MAX回まわっているようであるのに対し、ここだけ違っているようなので
少しだけ気になりました。

Re: STG:自機のショットが発射されません

Posted: 2012年8月25日(土) 14:56
by たれかつ
box さんが書きました: 何もわかっていなくて申し訳ありませんが、このループは2回まわるだけで大丈夫なんですね?
他のところではPS_MAX回まわっているようであるのに対し、ここだけ違っているようなので
少しだけ気になりました。
ご指摘ありがとうございます。
確認したところ、その部分はPS_MAXでないと駄目な部分でした。ありがとうございます。

現在、自分で問題を解決しようと試行錯誤していたところ、
一瞬で消えてあらぬ座標に飛んでいってしまう問題に関しては

コード:

if (pshot[m_i].x <-m_dran_x || pshot[m_i].x > FIELD_MAX_X + m_dran_x ||
    pshot[m_i].y <-m_dran_y || pshot[m_i].y < FIELD_MAX_Y + m_dran_y) {
の"FIELD_MAX_Y"を"FIELD_Y"に直したところ、ちゃんと自機前方から発射され画面上端で消えるという動作になりました。
また、二発のうち片方一発のみしか発射されない問題に関しては、いまいちどのようにすればよいのかわからなくなってしまったので、

コード:

			for(m_j = 0;m_j < PS_MAX / 2;++m_j) {
				if (pshot[m_j].flag == 0) {
					pshot[m_j].flag = 1;
					pshot[m_j].x = p_x + m_pshotpos_x[0];
					pshot[m_j].y = p_y + m_pshotpos_y[0];
				}
			}
			for(m_j = PS_MAX / 2;m_j < PS_MAX;++m_j) {
				if (pshot[m_j].flag == 0) {
					pshot[m_j].flag = 1;
					pshot[m_j].x = p_x + m_pshotpos_x[1];
					pshot[m_j].y = p_y + m_pshotpos_y[1];
				}
			}
と言う形にして無理やり解決しました。

ここで自分の予想とは別の問題がでてきてしまいましたが、このトピックとは関係のない話になってしまうので省略します。
しょうもないことでわざわざこのようなトピックを立ててしまい、ご迷惑をおかけしました。

Re: STG:自機のショットが発射されません

Posted: 2012年8月25日(土) 15:12
by nil
たれかつ さんが書きました:

コード:

			for(m_j = 0;m_j < PS_MAX / 2;++m_j) {
				if (pshot[m_j].flag == 0) {
					pshot[m_j].flag = 1;
					pshot[m_j].x = p_x + m_pshotpos_x[0];
					pshot[m_j].y = p_y + m_pshotpos_y[0];
				}
			}
			for(m_j = PS_MAX / 2;m_j < PS_MAX;++m_j) {
				if (pshot[m_j].flag == 0) {
					pshot[m_j].flag = 1;
					pshot[m_j].x = p_x + m_pshotpos_x[1];
					pshot[m_j].y = p_y + m_pshotpos_y[1];
				}
			}
少々気になったので書きます。
中身がほぼ同じfor文を2つ書くことは少々強引な解決法のように思えます(後のバグの原因にもなります)。
このような場合、

コード:

			for(m_j = 0;m_j < PS_MAX;++m_j) {
				if (pshot[m_j].flag == 0) {
					pshot[m_j].flag = 1;
					pshot[m_j].x = p_x + m_pshotpos_x[m_j%2];
					pshot[m_j].y = p_y + m_pshotpos_y[m_j%2];
				}
			}
こう書くのが妥当かと思います。

Re: STG:自機のショットが発射されません

Posted: 2012年8月25日(土) 15:25
by たれかつ
涼雅 さんが書きました: 少々気になったので書きます。
中身がほぼ同じfor文を2つ書くことは少々強引な解決法のように思えます(後のバグの原因にもなります)。
早速コードのほうを変更しました。
手直ししていただいてありがとうございました。

Re: STG:自機のショットが発射されません

Posted: 2012年8月25日(土) 15:29
by Dixq (管理人)
> 涼雅さん

m_pshotpos_xおよびm_pshotpos_yの配列要素は

コード:

            for(m_j = 0;m_j < PS_MAX;++m_j) {
                if (pshot[m_j].flag == 0) {
                    pshot[m_j].flag = 1;
                    pshot[m_j].x = p_x + m_pshotpos_x[m_j/(PS_MAX/2)];
                    pshot[m_j].y = p_y + m_pshotpos_y[m_j/(PS_MAX/2)];
                }
            }
が正しくないでしょうか?

コードをまとめるのは良いことだと思いますが、それによってコードが難読化してしまう時はまた別の方法をとることを検討するのもありかもしれません。

Re: STG:自機のショットが発射されません

Posted: 2012年8月25日(土) 17:52
by ISLe
発射するときも『消滅するときも』ふたつ同時であれば良いのですが、インデックスが偶数&偶数または奇数&奇数になる可能性があるのでは?

素直に

コード:

            for (m_i = 0;m_i < 2;m_i++) { // 2発発射
                for(m_j = 0;m_j < PS_MAX;++m_j) {
                    if (pshot[m_j].flag == 0) {
                        pshot[m_j].flag = 1;
                        pshot[m_j].x = p_x + m_pshotpos_x[m_i];
                        pshot[m_j].y = p_y + m_pshotpos_y[m_i];
                        break; // 必要なのでは
                    }
                }
            } 
で良いような。

ループの無駄を省くには

コード:

            int m_i = 0;
            for(m_j = 0;m_j < PS_MAX;++m_j) {
                if (pshot[m_j].flag == 0) {
                    pshot[m_j].flag = 1;
                    pshot[m_j].x = p_x + m_pshotpos_x[m_i];
                    pshot[m_j].y = p_y + m_pshotpos_y[m_i];
                    if (++m_i >= 2) break; // 2発撃ったら抜ける
                }
            }
とか。