ページ 1 / 1
敵弾フラグが消えない
Posted: 2008年8月12日(火) 11:43
by ぬっち
現在、バグ取りのため、いろいろ試しているのですが、このバグ取りの中でどうしても、敵弾の組のフラグを消す時のバグがうまく取れません。
具体的には、
・異なる敵が連続して(短い間隔で)弾を発射すると、敵弾が全て画面外に出ても敵弾の組のフラグが消えない。
・すこし長めの間隔で敵が弾を発射したときは、ある程度フラグ処理がうまく行われる。
ということです。
・敵が単体の場合は処理がうまくいく。(たとえ何度も違う敵弾の組のフラグを立てた場合でも)
言葉だけではわからないと思いますので、敵弾の処理の部分のプログラムを載せておきます。
void enemy_shot_display(){
for(int i=0;i<EnemyTotal;i++){
if(EnemyShotGroup.flag==1 || EnemyShotGroup.flag==2){
EnemyShotGroup.counter++;
for(int j=0;j<EnemyShotTotal;j++){
if(EnemyShotGroup.EnemyShot[j].flag==1 || EnemyShotGroup.EnemyShot[j].flag==2){
SetDrawBlendMode(DX_BLENDMODE_ADD,256);
if(EnemyShotGroup.EnemyShot[j].img==83 || EnemyShotGroup.EnemyShot[j].img==84 || EnemyShotGroup.EnemyShot[j].img==85){
SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 );
}
DrawRotaGraph((int)EnemyShotGroup.EnemyShot[j].x,(int)EnemyShotGroup.EnemyShot[j].y,1.0f,EnemyShotGroup[i].EnemyShot[j].display_angle,image_enemy_shot[EnemyShotGroup[i].EnemyShot[j].img],TRUE);
SetDrawBlendMode(DX_BLENDMODE_NOBLEND,0);
if(EnemyShotGroup[i].EnemyShot[j].x<-20.0 || EnemyShotGroup[i].EnemyShot[j].x>440.0 || EnemyShotGroup[i].EnemyShot[j].y<-20.0 || EnemyShotGroup[i].EnemyShot[j].y>500.0){
EnemyShotGroup[i].EnemyShot[j].flag=0;
}
}
}
}
}
for(int i=0;i<EnemyTotal;i++){
if(EnemyShotGroup[i].flag==1 || EnemyShotGroup[i].flag==2){
for(int j=0;j<EnemyShotTotal;j++){
if(EnemyShotGroup[i].EnemyShot[j].flag==1 || EnemyShotGroup[i].EnemyShot[j].flag==2){
return;
}
}
for(int j=0;j<EnemyShotTotal;j++){
EnemyShotGroup[i].EnemyShot[j].graze=1;
}
EnemyShotGroup[i].flag=0;
}
}
}
ちなみに、この部分はシューティングの館のプログラムを参考にして作ってあります。
敵弾の存在フラグが2となっているのは、敵を撃破したときの敵弾の存在フラグです。
説明不足でしたら、ゲーム本体または、使っている全てのcppファイル、hファイルをUPすることも考えています。
よろしくお願いします。
Re:敵弾フラグが消えない
Posted: 2008年8月12日(火) 13:25
by Justy
実行できないので正しくは解りませんが、見る限りでは
2つめの i<EnemyTotalを条件にした forループ内で、returnをしている箇所が
気になります。
コードから推測するに、ここの処理は一連のEnemyShot[x]の弾が全て flag=0だった場合、
根っこのグループ側 EnemyShotGroup[x]のフラグも0にするのが目的ですが、ここで returnしてしまうと
以降にある配列の弾に関して処理が一切行われないように見えます。
(どこか別の場所で処理しているのかもしれませんが)
その為、配列の配置的に先に出た弾のグループが消えない限り、
後発の弾が消えないのだと思われます。
なので、きちんと forループを EnemyTotal分回してあげれば
うまくいくのではないでしょうか。
Re:敵弾フラグが消えない
Posted: 2008年8月12日(火) 17:26
by ぬっち
Justyさん返答ありがとうございます。
私もそのreturnが曲者かなと思っていたので、やはりそこかもしれませんね。
しかし、直そうと思っていたんですが、これ以外の方法でうまく敵弾のフラグを消す方法が思いつきません;;
ある敵弾の組の中の敵弾のフラグが全て消えているならば、その敵弾の組のフラグを消す。
消えていなければ、次の敵弾の組を見る。
このことの繰り返しを行って、全ての敵弾の組を見るということを考えればよいと思うのですが、これをプログラムにすることがうまく出来ません;;
何かいいアドバイスがありましたらよろしくお願いします。
Re:敵弾フラグが消えない
Posted: 2008年8月12日(火) 18:01
by array
これはSTGの館の考えで敵出現及び敵ショットのフラグを立ててるんですよね。んでちょっと考えてみました。
void enemy_shot_display(){
int count;
for(int i=0;i<EnemyTotal;i++){
if(EnemyShotGroup.flag==1 || EnemyShotGroup.flag==2){
EnemyShotGroup.counter++;
count = 0;
for(int j=0;j<EnemyShotTotal;j++){
if(EnemyShotGroup.EnemyShot[j].flag==1 || EnemyShotGroup.EnemyShot[j].flag==2){
SetDrawBlendMode(DX_BLENDMODE_ADD,256);
if(EnemyShotGroup.EnemyShot[j].img==83 || EnemyShotGroup.EnemyShot[j].img==84 || EnemyShotGroup.EnemyShot[j].img==85){
SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 );
}
DrawRotaGraph((int)EnemyShotGroup.EnemyShot[j].x,(int)EnemyShotGroup.EnemyShot[j].y,1.0f,EnemyShotGroup[i].EnemyShot[j].display_angle,image_enemy_shot[EnemyShotGroup[i].EnemyShot[j].img],TRUE);
SetDrawBlendMode(DX_BLENDMODE_NOBLEND,0);
if(EnemyShotGroup[i].EnemyShot[j].x<-20.0 || EnemyShotGroup[i].EnemyShot[j].x>440.0 || EnemyShotGroup[i].EnemyShot[j].y<-20.0 || EnemyShotGroup[i].EnemyShot[j].y>500.0){
EnemyShotGroup[i].EnemyShot[j].flag=0;
}
count ++;
}
if(count == 0 && j == EnemyShotTotal-1)
EnemyShotGroup[i].flag=0;
}
}
}
}
こんなのでうまくいきませんかね、カウントで出現中の弾[j]が1つもなければその[i]も0にする感じで考えてみたのですが
Re:敵弾フラグが消えない
Posted: 2008年8月12日(火) 18:20
by ぬっち
arrayさん返答ありがとうございます。
それぞれの組について数え上げるということですか。
この方法だと確かにうまくいきますね^^
しかし実行してみると、動作がかなり重くなってしまいました・・・。
プログラムから判断すると、計算量が増えて(ひとつの組に対して、数を数えるという操作をして)重くなっているのが原因かもしれませんね^^;
この辺は、私自身でも考えてみたいと思います。
ともかくこれで、先に進めることが出来るようになりました。
アドバイスありがとうございます^^
Re:敵弾フラグが消えない
Posted: 2008年8月12日(火) 18:40
by array
ちなみにですけど、EnemyShotGroup
.EnemyShot[j].flagが1か2かの時のみcountを加算しており、
if(count == 0 && j == EnemyShotTotal-1)
EnemyShotGroup.flag=0;
は最後に1回だけ、しかもカウントが1以上なら処理しないので、急激に重くはならないと思ったのですが、今見たら、無駄部分があるのかもしれませんね。なので後ろの部分だけ書き換えてみました。
/*省略*/
if(EnemyShotGroup.EnemyShot[j].x<-20.0 || EnemyShotGroup.EnemyShot[j].x>440.0 || EnemyShotGroup.EnemyShot[j].y<-20.0 || EnemyShotGroup.EnemyShot[j].y>500.0){
EnemyShotGroup.EnemyShot[j].flag=0;
}
if(count != 0)
count ++;
}
}
if(count == 0)
EnemyShotGroup.flag=0;
}
}
}
一応加算処理よりifで読み飛ばした方が処理は早いらしいので0の場合のみcountを加算させ、
if(count == 0 && j == EnemyShotTotal-1)
EnemyShotGroup.flag=0;
は、別にfor(j)の中に入ってる必要はなさそうなので外に出してみました。
これでもあまり変わらなそうだけど実質は軽くなるはずです(?)
もっともcountを取ること自体、無駄な処理かもしれませんが^^;
Re:敵弾フラグが消えない
Posted: 2008年8月12日(火) 19:41
by 管理人
画面内に弾が無い時フラグが落としたければ
void EnemyShotCalcDisp(){
int i,j;
for(i=0;i<ENEMY_TOTAL_NUM;i++){
if(EnemyShot.flag==1){
EnemyShot.counter++;
for(j=0;j<ENEMY_TOTAL_SHOT_NUM;j++){
if(EnemyShot.EnemyShots[j].flag==1){
DrawRotaGraph( 略.x , 略.y , 1.0f , 略.disp_angle , 略 , TRUE ) ;
if(EnemyShot.EnemyShots[j].x<-20.0||EnemyShot.EnemyShots[j].x>440.0||
EnemyShot.EnemyShots[j].y<-20.0||EnemyShot.EnemyShots[j].y>500)
EnemyShot.EnemyShots[j].flag=0;
}
}
}
}
for(i=0;i<ENEMY_TOTAL_NUM;i++){
if(EnemyShot.flag==1){
for(j=0;j<ENEMY_TOTAL_SHOT_NUM;j++){
if(EnemyShot.EnemyShots[j].flag==1)
break;
}
if(j==ENEMY_TOTAL_SHOT_NUM)
EnemyShot[i].flag=0;
}
}
}
これでどうでしょうか?
赤のif文にたどり着いたとき、jの値がループの上限値なら、最後までbreakが
行われなかった事がわかりますので、つまり弾が無い事がわかります。
Re:敵弾フラグが消えない
Posted: 2008年8月12日(火) 22:41
by Justy
見ていてちょっと気になったのですが、SetDrawBlendMode()の2つ目の引数って
0~255までですよね?
(実害はないと思いますが)何故に 256なんでしょ?
Re:敵弾フラグが消えない
Posted: 2008年8月12日(火) 23:39
by ぬっち
解決したけど、こんなにレスがつくとは・・・。
本当に親切な人たちが集まる掲示板ですね^^
>arrayさん
実行してみると、弾自体が発射後すぐに消えてしまうということが起こってしまいました。
発射された弾がcount=0と勘違いしてしまっているのではないかと考えたのですが・・・。
どうなのでしょうね;;
>管理人さん
書き換えてやってみましたが、今度はまったく敵のフラグが落ちないという事態に;;
後半部分のbreak辺りの処理がうまくいってない感じです。
>Justyさん
あ・・・、これは完全に間違えですね;;
指摘していただきありがとうございます。
このよう間違いもあることも考えると、何人かの人にプログラムを見せることも重要かもしれませんね^^;
テストプレイを重ねた結果、countによる重さは、弾が増えた時(多くの敵弾の組の存在フラグが立っている場合)に起こるようです。(プログラム見ればわかりますが^^;)
動作が遅くなった時、60(設定した最高値)の敵弾の組の存在フラグが立っていました。
なるべく、このようなことがならないよう、存在フラグを多く立てすぎないよう注意していく事も必要かもしれませんね。
Re:敵弾フラグが消えない
Posted: 2008年8月13日(水) 00:16
by 管理人
う~ん、うまくいくはずなんですけどね~。
もしかして
int i,j;
for(int i=0;i<ENEMY_TOTAL_NUM;i++){
if(EnemyShot.flag==1){
for(int j=0;j<ENEMY_TOTAL_SHOT_NUM;j++){
if(EnemyShot.EnemyShots[j].flag==1)
break;
}
こんな風に二重に宣言していませんか?
Re:敵弾フラグが消えない
Posted: 2008年8月13日(水) 00:17
by Justy
>テストプレイを重ねた結果、countによる重さは、弾が増えた時(多くの敵弾の組の存在フラグが立っている場合)に起こるようです。
>動作が遅くなった時、60(設定した最高値)の敵弾の組の存在フラグが立っていました
その「重さ」は countによるものというより、描画にかかるコストだったりしませんか?
それだけの数の弾分描画関数を呼ぶとそれなりに重くなりそうな気がします。
>弾自体が発射後すぐに消えてしまうということが起こってしまいました
理論的には arrayさんの方法でも管理人さんの方法でもうまくいくはず・・・なのですが、
ここ以外のところにも問題があるのかもしれませんね。
あれ? arrayさんのコードの訂正版で
if(count != 0)
って正しくは
if(!count)
だったりしませんか?
Re:敵弾フラグが消えない
Posted: 2008年8月13日(水) 00:32
by ぬっち
>管理人さん
2重宣言は特にありませんね・・・。
プログラムを見た感じではうまくいきそうなんですが・・・。
>Justyさん
実際に前の状態で行った時は、多少遅くなる程度で(FPSが59を切るくらいで)動作が重くなりませんでした。
また、配列数を増やしても、目に見えるほど重くなることはありませんでした。
しかし、countでのフラグの落とし方を導入してみると、FPSが40を切ることもあるくらい重くなってしまいます。
このことから、重くなるのが描写ではないと判断したのですが、どうでしょうか?
一応、重くなる対策として、敵の弾の出現間隔を調整することで落ち着きましたが、出来ればなんとか解決したいです;;
Re:敵弾フラグが消えない
Posted: 2008年8月13日(水) 00:52
by Justy
>しかし、countでのフラグの落とし方を導入してみると、FPSが40を切ることもあるくらい重くなってしまいます。
>このことから、重くなるのが描写ではないと判断したのですが、どうでしょうか?
なるほど。まだちょっとどっちかは判断が付かないんですが、
今の countの仕方は arrayさんの改良前か後でも、それ自体はそんなに大した処理では
ないはずなんですよ。
んー、なんでしょうねぇ。
一度、今現在のコードを出して頂いた方がいいのかもしれません。
Re:敵弾フラグが消えない
Posted: 2008年8月13日(水) 00:59
by Justy
>書き換えてやってみましたが、今度はまったく敵のフラグが落ちないという事態に;;
>後半部分のbreak辺りの処理がうまくいってない感じです。
いろんな可能性がありますが、ありがちなのは EnemyShotGroup.flagを 1にしたとき、
(或いは EnemyShotGroup.flagを 0にしたときでもいいですが)
ちゃんとそのグループ内の全ての EnemyShotGroup.EnemyShot[j].flagを 0に初期化していますか?
それをしていないと、同じ領域を2度目以降に使用する際に、前回使用したときの情報が
残ってしまっている可能性があります。
Re:敵弾フラグが消えない
Posted: 2008年8月13日(水) 02:19
by Justy
そういえば。
弾の flagが全て 0だからといって、グループの方も 0にしてしまっていいのでしょうか?
例えば計10発撃つはずだったのに、最初に一発撃った段階で、その弾が画面外に行ってしまって
flagが 0に。
そのグループは1発しかまだ発射していないからグループのフラグも 0になってしまい、
残りの9発が発射されなくなってしまったりしませんか?
Re:敵弾フラグが消えない
Posted: 2008年8月13日(水) 02:43
by 管理人
敵が画面内におらず、一つも登録された弾がなければ、それ以上計算する必要がないので、
弾幕データを消しても良いですよね。
龍神録の館だと、弾幕を開始した敵のフラグがオフになっていて、かつ、
弾幕の弾が全て画面上になければ弾幕データがオフになりますが、
シューティングゲームの館のサンプルでは、単に画面内になければオフになっていると思います。
龍神録の館では敵は倒されるか、画面外に出たらフラグに2を入れ、それで判断しています。
それにシューティングゲームの館のサンプルのままでは、弾幕の弾データは敵が倒されていても、
登録され続けるため、上のような方法で、改善しなければなりません。
Re:敵弾フラグが消えない
Posted: 2008年8月13日(水) 04:06
by Justy
>敵が画面内におらず、一つも登録された弾がなければ、それ以上計算する必要がないので、
>弾幕データを消しても良いですよね。
敵がいなくなれば、そうですね。
>龍神録の館だと、弾幕を開始した敵のフラグがオフになっていて、かつ、
なるほど。きっちり改善されているのですね。
Re:敵弾フラグが消えない
Posted: 2008年8月13日(水) 08:11
by ぬっち
>Justyさん
>弾の flagが全て 0だからといって、グループの方も 0にしてしまっていいのでしょうか?
確かにいわれてみれば、これは問題がありますね。
今まで、普通に作っていて何の問題もなかったので完全に見逃していました。
逆に、これを直せればボムを撃った時ややられた時に敵弾が全て消え、その後しばらく発射されないという事態を直せるかもしれませんね。
>管理人さん
敵を倒したときの弾の振る舞いは大丈夫なのですが、問題は敵のフラグと弾のフラグ関係に問題があるということですね。
今のところ、それによる問題が発生していないのですが、やはりここの改良をすべきでしょうか?
Re:敵弾フラグが消えない
Posted: 2008年8月13日(水) 17:36
by array
私の改良後のプログラムですが、Justyさんの仰るとおりで
if(count != 0) ×
if(!count) ○
が正しそうですね。一瞬同じに見えましたが、上だと一度もカウントしませんね(汗
それと管理人さんのプログラムなんですが、
if(j==ENEMY_TOTAL_SHOT_NUM) ×
if(j==ENEMY_TOTAL_SHOT_NUM - 1) ○
でよさそうじゃないですか?
↓より修正しときます
Re:敵弾フラグが消えない
Posted: 2008年8月13日(水) 18:40
by 管理人
>>arrayさん
これはループ中にbreakが行われたかどうかを判定する為に私はよく使う手なんですよ。
#include <stdio.h>
#define MAX 10
int main(){
int i;
for(i=0;i<MAX;i++){
if(i==15)
break;
}
if(i==MAX)
printf("途中でbreakが行われませんでした\n");
return 0;
}
このi==15を5にしたり10にしたりしてみて下さい。
iはMAX未満の状態がループ継続可能条件なわけですが、それを満たさなくなったからループから抜けたわけですよね。
だから、最後までi++が行われたのならiはMAXになっているはずです。
Re:敵弾フラグが消えない
Posted: 2008年8月13日(水) 19:30
by array
実行結果を確認しました、理解してるつもりだったのですけど、間違ってますね><
私はforで配列の
#include <stdio.h>
#define MAX 5
int main(){
int i,data[MAX] = {0};
for(i=0;i<MAX;i++)
printf("data[%d]=%d\n", i, data);
printf("----for終了----\n");
printf("i=%d\n",i);
return 0;
}
#####実行結果#####
data[0]=0
data[1]=0
data[2]=0
data[3]=0
data[4]=0
----for終了----
i=5
data[0~4]の配列の中身を見ると考えてたので←あってますよね
iが4カウントで止まっていると勘違いしてたのがアホな言動をした原因だったみたいです。
実際はforを抜けたら5になってたんですね><;
こんなことも知らなかったりするので、またミスしていた時は教えてくれると嬉しいです^^
Re:敵弾フラグが消えない
Posted: 2008年8月13日(水) 19:45
by 管理人
int data[5];
で用意すると、[0]~[4]が使用できる要素であることは正しいです。
また
(↓①②③は機種依存文字)
for(①;②;③){
//ごにょごにょ
}
において、
①はループの一番最初に一度だけ行われる処理
②はループ1周の最初に行われる処理
③はループ1周の最後に行われる処理
だから、上記と、処理は左からされること、0以外が条件文の真になることから③をはぶいてこんなことも。
#include <stdio.h>
#define MAX 5
int main(){
int i,data[MAX]={0,};
for( i=0 ; ++i && i<=MAX ;)
printf("data[%d]=%d\n", i-1, data[i-1]);
printf("----for終了----\n");
printf("i=%d\n",i);
return 0;
}
実行結果
data[0]=0
data[1]=0
data[2]=0
data[3]=0
data[4]=0
----for終了----
i=6
こんな事は普通しませんがw
Re:敵弾フラグが消えない
Posted: 2008年8月13日(水) 22:18
by ぬっち
arrayさんのプログラムを修正して試したところ、うまくいきました。(FPSが59以上で落ち着きました)
やはり、countを余計に数えていることによる、動作の重さであるということでした。
管理人さんのほうでは、なぜかうまくいかないので、今のところはarrayさんの方法を使わせていただきます。
このスレを立てたおかげで、新たなテクニック、動作の重さについていろいろと学ぶことが出来ました^^
レスしてくださった、管理人さん、Justyさん、arrayさんありがとうございます^^