斜め俯瞰2D(クォータービュー)の描画順について
Posted: 2012年6月30日(土) 03:49
現在クォータービューのゲームを作成中のものです。
前回の質問ではお世話になりました。
どうやらファイル読み込みエラーのメッセージ表示がf<0で間違っていたために読み込みが成功しているにもかかわらずエラーメッセージをprintfDxしていたことに加え、新規追加したAIの挙動プログラムのエラーにより以降の画面描画がストップしていたせいであたかもマップ読み込みの時点でエラーが出ているように見えていたものと思われます。
現在バグなく順調です。
さて、本題ですがただいまオブジェクト(キャラクター、障害物、射出された弾等のマップ上に描画される小物)の描画関数を作っています。
y成分だけを比較して見かけ奥の方(y座標が小さい方)から描画をする簡単な関数は以下のような形で完成しています。
なんだかごちゃごちゃして人様に見せられるような有様ではありませんがご容赦ください……。
この関数は各オブジェクトの画像描画時の中心座標同士を比較させて描画順を決定しているのですが、これだけだとレーザーなどある一方向に長い(もっと言うならy座標に幅があるユニークな形状の)オブジェクトを描画した際、奥行きによる重なりを無視した描画をしてしまいます。
例えば、レーザー上のある一点では柱より手前にレーザーが来ているように見えても、レーザーを延ばしていった先では柱の後ろに隠れてしまうかもしれませんよね。
そうなると私の場合リストで一つ一つのオブジェクトの大きさ形を見極めてソートしていくような面倒くさいプログラムしか思いつかないのですが、何か良い方法はないものでしょうか。
前回の質問ではお世話になりました。
どうやらファイル読み込みエラーのメッセージ表示がf<0で間違っていたために読み込みが成功しているにもかかわらずエラーメッセージをprintfDxしていたことに加え、新規追加したAIの挙動プログラムのエラーにより以降の画面描画がストップしていたせいであたかもマップ読み込みの時点でエラーが出ているように見えていたものと思われます。
現在バグなく順調です。
さて、本題ですがただいまオブジェクト(キャラクター、障害物、射出された弾等のマップ上に描画される小物)の描画関数を作っています。
y成分だけを比較して見かけ奥の方(y座標が小さい方)から描画をする簡単な関数は以下のような形で完成しています。
なんだかごちゃごちゃして人様に見せられるような有様ではありませんがご容赦ください……。
struct Charadata
{
float muki;//変換前、向きラジアン
int type;//敵の種類
int graph[8];//各方向グラフィック格納変数
int time;//生存時間変数
int act;//アクション把握用変数
int dashtimer;
int hantei;//持っている当たり判定の数(最大4個)
int area[4][3];//判定のエリア(長径)、判定の[1]=x座標 [2]=y座標
float lockx;
float locky;
float x;
float y;
};
struct ATKdat
{
int chara;//射出した敵キャラの番号
int type;//攻撃の種類
int time;//存在時間
double x;//中心座標
double y;//中心座標
float muki;
int graph[8];//画像
int hantei;//判定の個数(最大16個)
int area[16][3];//判定のエリア(長径)、判定の[1]=x座標 [2]=y座標
};
extern struct Charadata Chara[128];//0=P1 32-62=enemy 63=boss 64-=object
extern struct ATKdat Atk[256];
void Drawfunc()
{
float y[384][3];//[個数][3つの要素(x座標:y座標:存在(-1=存在しない))]
float min;
int muki=0;
int count=0;
//キャラクターの存在によって初期化の値を変更する
for(int i=0;i<128;i++){
if(Chara[i].type!=0){
y[i][0]=Chara[i].x;
y[i][1]=Chara[i].y;
y[i][2]=1;
}
if(Chara[i].type==0){y[i][2]=0;}
}
//Atkも同様に初期化
for(int i=0;i<256;i++){
if(Atk[i].type!=0){
y[i+128][0]=Atk[i].x;
y[i+128][1]=Atk[i].y;
y[i+128][2]=1;
}
if(Atk[i].type==0){y[i+128][2]=0;}
}
float g_x=Chara[0].x+Xdis(50,UtoQ(Chara[0].muki));
float g_y=Chara[0].y-Ydis(50,UtoQ(Chara[0].muki));
DrawGraph(320-g_x,240-g_y,UseMisData.graph,TRUE);//背景描画
//以下キャラ、オブジェクト、弾の描画
while(1){
min=10000000000;
count=0;
for(int i=0;i<384;i++){
if(y[i][1]<=min && y[i][2]==1){
min=y[i][1];
}
}
for(int i=0;i<384;i++){
if(y[i][1]<=min && y[i][2]!=0){
y[i][2]=0;
if(i<128){//キャラクター構造体
if(Chara[i].muki<=0+PAI/8 || Chara[i].muki>PAI/4*7+PAI/8){muki=0;}
if(Chara[i].muki>=PAI/4-PAI/8 && Chara[i].muki<PAI/4+PAI/8){muki=1;}
if(Chara[i].muki>=PAI/4*2-PAI/8 && Chara[i].muki<PAI/4*2+PAI/8){muki=2;}
if(Chara[i].muki>=PAI/4*3-PAI/8 && Chara[i].muki<PAI/4*3+PAI/8){muki=3;}
if(Chara[i].muki>=PAI/4*4-PAI/8 && Chara[i].muki<PAI/4*4+PAI/8){muki=4;}
if(Chara[i].muki>=PAI/4*5-PAI/8 && Chara[i].muki<PAI/4*5+PAI/8){muki=5;}
if(Chara[i].muki>=PAI/4*6-PAI/8 && Chara[i].muki<PAI/4*6+PAI/8){muki=6;}
if(Chara[i].muki>=PAI/4*7-PAI/8 && Chara[i].muki<PAI/4*7+PAI/8){muki=7;}
DrawRotaGraph(320-(g_x-Chara[i].x),240-(g_y-Chara[i].y),1,0,Chara[i].graph[muki],TRUE,FALSE);
}
if(i>=128){//攻撃構造体
if(Atk[i-128].muki<=0+PAI/8 || Atk[i-128].muki>PAI/4*7+PAI/8){muki=0;}
if(Atk[i-128].muki>=PAI/4-PAI/8 && Atk[i-128].muki<PAI/4+PAI/8){muki=1;}
if(Atk[i-128].muki>=PAI/4*2-PAI/8 && Atk[i-128].muki<PAI/4*2+PAI/8){muki=2;}
if(Atk[i-128].muki>=PAI/4*3-PAI/8 && Atk[i-128].muki<PAI/4*3+PAI/8){muki=3;}
if(Atk[i-128].muki>=PAI/4*4-PAI/8 && Atk[i-128].muki<PAI/4*4+PAI/8){muki=4;}
if(Atk[i-128].muki>=PAI/4*5-PAI/8 && Atk[i-128].muki<PAI/4*5+PAI/8){muki=5;}
if(Atk[i-128].muki>=PAI/4*6-PAI/8 && Atk[i-128].muki<PAI/4*6+PAI/8){muki=6;}
if(Atk[i-128].muki>=PAI/4*7-PAI/8 && Atk[i-128].muki<PAI/4*7+PAI/8){muki=7;}
DrawRotaGraph(320-(g_x-Atk[i-128].x),240-(g_y-Atk[i-128].y),1,Atk[i-128].muki,Atk[i-128].graph[muki],TRUE,FALSE);
}
}
}
for(int i=0;i<384;i++){
if(y[i][2]==1){count=1;}
}
if(count==0){break;}
}
}
この関数は各オブジェクトの画像描画時の中心座標同士を比較させて描画順を決定しているのですが、これだけだとレーザーなどある一方向に長い(もっと言うならy座標に幅があるユニークな形状の)オブジェクトを描画した際、奥行きによる重なりを無視した描画をしてしまいます。
例えば、レーザー上のある一点では柱より手前にレーザーが来ているように見えても、レーザーを延ばしていった先では柱の後ろに隠れてしまうかもしれませんよね。
そうなると私の場合リストで一つ一つのオブジェクトの大きさ形を見極めてソートしていくような面倒くさいプログラムしか思いつかないのですが、何か良い方法はないものでしょうか。