ページ 11

敵弾の描画順序について

Posted: 2010年9月24日(金) 00:04
by サンタクロース
こんばんわ。

龍神録プログラミングの館を参考にしているのですけど、一つ疑問が浮かびました

敵の弾の描画順序を入れ替るにはどうすれば良いでしょうか?

描画はソースが下に来るほど上に描画されるようになっていたと思ったので試しに
下のように場合分けしてみましたが変化はありませんでした。

回答よろしくお願いします。
if(boss_shot.bullet[j].knd==10){
                       DrawRotaGraphF(
                       boss_shot.bullet[j].x+FX+dn.x, boss_shot.bullet[j].y+FY+dn.y,
                       1.0, disp_angle,
                       img_bullet[boss_shot.bullet[j].knd][boss_shot.bullet[j].co[/url],TRUE);
                   }
                       else if(boss_shot.bullet[j].knd==6 || boss_shot.bullet[j].knd==7 || boss_shot.bullet[j].knd==8 ||
                       boss_shot.bullet[j].knd==11 || boss_shot.bullet[j].knd==12){
                       DrawRotaGraphF(
                       boss_shot.bullet[j].x+FX+dn.x, boss_shot.bullet[j].y+FY+dn.y,
                       1.0, disp_angle,
                       img_bullet[boss_shot.bullet[j].knd][boss_shot.bullet[j].co[/url],TRUE);
                   }
                   else{
                       DrawRotaGraphF(
                       boss_shot.bullet[j].x+FX+dn.x, boss_shot.bullet[j].y+FY+dn.y,
                       1.0, disp_angle,
                       img_bullet[boss_shot.bullet[j].knd][boss_shot.bullet[j].co[/url],TRUE);
                   }
               
               }

Re:敵弾の描画順序について

Posted: 2010年9月24日(金) 01:05
by 真等
こんにちは!

>描画はソースが下に来るほど上に描画される

とのことですが、そうでない場合もあるかもしれません。
例えば、

for ( int i=0; i<2; ++i ) {
DrawRotaGraphF(boss_shot.bullet[j].x, 略); // 描画1
DrawRotaGraphF(boss_shot.bullet[j].x, 略); // 描画2
}

この場合ですと、ソースとして見れば「描画2」が下にありますが、実際にfor文を展開すれば、
DrawRotaGraphF(boss_shot.bullet[0].x, 略); // 描画1
DrawRotaGraphF(boss_shot.bullet[1].x, 略); // 描画2
DrawRotaGraphF(boss_shot.bullet[0].x, 略); // 描画1
DrawRotaGraphF(boss_shot.bullet[1].x, 略); // 描画2
となりまして、3行目の「描画1」は2行目の「描画2」より上に来ることになります。



見当違いのこと言ってたらすいません。

Re:敵弾の描画順序について

Posted: 2010年9月24日(金) 01:21
by ft
そのコードですと配列に格納されている順番(j)で描画されてしまいます。
(例えばj=100の時にboss_shot.bullet[j].knd==6を満たして、次のj=101の時にboss_shot.bullet[j].knd==10を満たしても、結局knd=10の方が後で描かれるため前回の上に描かれてしまいます)
そこで私は描画直前に弾の構造体の中身をソートする関数を挟んでいます。
龍神録のサンプルのままですと、jの値が小さければ下に描かれますので、
優先的に下に描きたい弾情報と若い値のjに入っている弾情報を交換する感じです。
私の場合とりあえず1種類の弾だけですが、
//弾情報ソート
void bullet_sort(){
    int i;
    static int n;
    //ソート元情報保存用変数
    float smx,smy,smangle,smspd;
    int smflag,smcnt,smstate,smknd,smcol,smeff,smeff_detail;
    //ソート先情報保存用変数
    float ssx,ssy,ssangle,ssspd;
    int ssflag,sscnt,ssstate,ssknd,sscol,sseff,sseff_detail;
    for(i=0;i<BOSS_BULLET_MAX;i++){
        if(boss_shot.bullet.knd==10){//もし弾の種類が10だったら
            //元の弾情報保存
            smx=boss_shot.bullet.x;
            smy=boss_shot.bullet.y;
            smangle=boss_shot.bullet.angle;
            smspd=boss_shot.bullet.spd;
            smflag=boss_shot.bullet.flag;
            smcnt=boss_shot.bullet.cnt;
            smstate=boss_shot.bullet.state;
            smknd=boss_shot.bullet.knd;
            smcol=boss_shot.bullet.col;
            smeff=boss_shot.bullet[i].eff;
            smeff_detail=boss_shot.bullet[i].eff_detail;
            //ソート先の弾情報保存
            ssx=boss_shot.bullet[n].x;
            ssy=boss_shot.bullet[n].y;
            ssangle=boss_shot.bullet[n].angle;
            ssspd=boss_shot.bullet[n].spd;
            ssflag=boss_shot.bullet[n].flag;
            sscnt=boss_shot.bullet[n].cnt;
            ssstate=boss_shot.bullet[n].state;
            ssknd=boss_shot.bullet[n].knd;
            sscol=boss_shot.bullet[n].col;
            sseff=boss_shot.bullet[n].eff;
            sseff_detail=boss_shot.bullet[n].eff_detail;
            //弾情報を交換する
            //ソート1
            boss_shot.bullet[n].x=smx;
            boss_shot.bullet[n].y=smy;
            boss_shot.bullet[n].angle=smangle;
            boss_shot.bullet[n].spd=smspd;
            boss_shot.bullet[n].flag=smflag;
            boss_shot.bullet[n].cnt=smcnt;
            boss_shot.bullet[n].state=smstate;
            boss_shot.bullet[n].knd=smknd;
            boss_shot.bullet[n].col=smcol;
            boss_shot.bullet[n].eff=smeff;
            boss_shot.bullet[n].eff_detail=smeff_detail;    
            //ソート2
            boss_shot.bullet[i].x=ssx;
            boss_shot.bullet[i].y=ssy;
            boss_shot.bullet[i].angle=ssangle;
            boss_shot.bullet[i].spd=ssspd;
            boss_shot.bullet[i].flag=ssflag;
            boss_shot.bullet[i].cnt=sscnt;
            boss_shot.bullet[i].state=ssstate;
            boss_shot.bullet[i].knd=ssknd;
            boss_shot.bullet[i].col=sscol;
            boss_shot.bullet[i].eff=sseff;
            boss_shot.bullet[i].eff_detail=sseff_detail;
            n++;//nをひとつ進める
        }
    }
    n=0;
}

こんな感じでやっています。
flagを加えてちょっと改変すれば数種類の弾ソートも可能だと思います。
もっと良い方法があると思いますので参考までに…


あとここからは蛇足なのですが弾の描画順ということで、連なって描かれる弾を綺麗に描画する方法があります。
おそらくサンプルのままだと、連なる弾の重なり方は時間が経つと添付画像の上のようにバラバラになると思います。これは弾の検索を毎回0~BOSS_BULLET_MAX全て調べているため、画面外に行ったなどしてフラグが空いた弾が若い値のjの場合、その値から優先的に弾を作ってしまうからです。
そこで、空いてる弾の検索でフラグが立っていない弾のインデックスを保存し、次に検索する時は前回+1から空き弾を検索することで下の画像にように割と綺麗にできます。
search_boss_shotを
int search_boss_shot(){//空き番号を返す
    int i,b_num;
    if(b_num>=BOSS_BULLET_MAX)b_num=0;
    for(i=b_num;i<BOSS_BULLET_MAX-100;i++){
        if(boss_shot.bullet[i].flag==0){
            b_num=i+1;
            return i;
        }
    }
    return -1;
}

という感じです。
たまにおかしくなりますが結構いけますw

Re:敵弾の描画順序について

Posted: 2010年9月24日(金) 06:15
by Justy
>敵の弾の描画順序を入れ替るにはどうすれば良いでしょうか?
 今の配列構造のままでやるなら int renderingOrder[BOSS_BULLET_MAX] という配列を作って、
描画したい boss_shot.bullet配列のインデックスを格納しておき、[color=sans-serif]boss_shot.bullet[renderingOrder[j]][/font]とすれば
renderingOrderで指定した順に描画されます。

Re:敵弾の描画順序について

Posted: 2010年9月30日(木) 00:57
by サンタクロース
真等さん、ftさん、Justyさん回答ありがとうございます。
今回はftさんのソースをいじらせて使わせてもらいました。
ただ本体がPSPなので、毎描画?ごとに使うと処理落ちがすごいですね(笑)。
自分は弾を撃った直後に使うようにしました(かなりその場しのぎっぽいですが)
Justyさんの方法はとても効率が良さそうですね。
時間があればそちらの方法でも試してみたいと思います。