ページ 1 / 1
クォータービューの描画順位
Posted: 2009年7月07日(火) 23:26
by クロウ
以前も質問させていただきましたが、クォータービューにおいてのキャラクターとマップの描画順位についてです。
以前の質問した時には、スクロールは連続的なのに対し、キャラクターの移動は離散的であるところまでできたのですが、連続的に移動させると描画順位が狂ってしまっていました。
当時は離散的な描画でもよかったのですが、今現在作っているクォータービューのパズルアクションではアクション性が出てきたので、タクティクスオウガなどのクォータービューのゲームのようにキャラクターが移動中の描画をしても描画順位が狂わないようにしたいのです。
今の描画方法ですと、どう頑張っても離散的にしかならなさそうなのでアドバイスをお願いします。
今現在のマップとキャラクターの描画部分を載せておきます。また、表示するマップデータと読み込み部分を添付しました。
#define MAPSIZEMAX_X 32//マップの広さX
#define MAPSIZEMAX_Y 32//マップの広さY
void dataDraw( void )
{
//int i, f ;//i:キャラの数,x:forループx座標,y:forループy座標,f:マップの段数
int px, py ;//描画座標
int hx = 288;
int hy = 64;//初期描画位置の補正
for(int y = 0; y < MAPSIZEMAX_Y; y++ ){
for(int x = 0; x < MAPSIZEMAX_X; x++ )
{
px = hx-(y*32)+(x*32) + scroll_X(99);
py = hy+(y*16)+(x*16) + scroll_Y(99/*適当な値を入れている*/);
if(mapData.field[y][x] != -1){//マップデータがNULLでなければ
for(int f = 0;( f < mapData.fieldHigh[y][x] || mapData.fieldHigh[y][x] == 99); f++ ){
//高さ分積む(処理落ちしているので中身を空洞に)
//マップチップを並べる
if(px <= 600 + 64 && px >= 0 - 64 && py <= 600 + 48 && py >= 0 - 48){//描画領域内のみ描画
if(f == mapData.fieldHigh[y][x] - 1){//高さ以外の部分を空洞にする
DrawGraph( px, py-f*16, dat.Pic.MapChip[ mapData.field[y][x] ], TRUE );//マップチップの描画
}
}
//障害物を描画
if(mapData.hurdle[y][x] != 0){
DrawGraph( px, py-mapData.fieldHigh[y][x]*16, dat.Pic.MapObject[ mapData.hurdle[y][x]/*iaMap[y][x]*//*f%4*/ ], TRUE );
}
for(int i = 0; i < CHARAMAX; i++ ){
if(NPC.alive[y][x] == true){
NPCDraw(px ,py -48 , mapData.fieldHigh[y][x] - 1 , x ,y , NPCData.rank , i);
//NPCの描画
}
if(enemyData.alive == true && enemyData.true_X/16 == x && enemyData.true_Y/16 == y){//敵を描画
enemyDraw(px ,py -48 , mapData.fieldHigh[y][x] - 1 , x ,y , enemyData.rank , i);
}
if( ch[playe[/url].true_X/16 == x && ch[playe[/url].true_Y/16 == y ){
charaDrawMain(px , py -48 , mapData.fieldHigh[y][x] -1 , i , ch.type );//プレイヤーを描画
}
}
}
}
}
}
Re:クォータービューの描画順位
Posted: 2009年7月08日(水) 01:27
by ねこ
離散的の意味がよく分からないんですが、多分移動中に本来奥にあるオブジェクトが手前に描画されてるって事ですよね。
恐らくマップチップの真上に居る時は思い通りの描画になっている、と。
if( ch[playe[/url].true_X/16 == x && ch[playe[/url].true_Y/16 == y )
この処理を
int x1 = ch[playe[/url].true_X/16;
int x2 = x1 + 1;
int y1 = ch[playe[/url].true_Y/16;
int y2 = y1 + 1;
int cx = max( x1, x2 );
int cy = max( y1, y2 );
f( cx == x && cy == y )
と書き変えると一部上手くいきませんか?
※方向の絡みがよく把握出来てないのでmaxかminか+1か-1か変わるかもしれないです。
それから多分高さ考慮が足りないと思うんですが・・・時間が押しちゃったので誰かにバトンタッチ・・・
Re:クォータービューの描画順位
Posted: 2009年7月08日(水) 02:35
by Justy
描画順位が狂う、というのは例えば、今いるブロックから同じ高さの隣り合った左右どちらかの手前に
移動しようとすると、移動の途中で下半身が消え、移動が終わると正常に戻っている、
みたいな状態でしょうか。
正直これだけの情報では何がどうおかしいのかよくわからないので推測になりますが
どのブロックの上にいるのか、の判定がおかしいんでしょうね。
16で割っているので、15のところまで進んでも以前のブロックの位置にいると
判定しているのが原因のような気もしますね。
Re:クォータービューの描画順位
Posted: 2009年7月08日(水) 12:10
by ねこ
見直すと凄い変な処理書いてる、すいませんorz
現在乗っているマップチップの位置の座標をP1( x1, y1, z1 )とします( fはzと置き換えます )
現在のマップチップからずれてる方向にあるマップチップの座標をP2( x2, y2, z2 )とします。
P1からP2に対するそれぞれのxyz距離を1.0とした時、キャラの位置dx,dy,dzを0.0~1.0の間で求めます。
int cx = dx < 0.5 ? x1 : x2;
int cy = dy < 0.5 ? y1 : y2;
int cz = dz < 0.5 ? z1 : z2;
として、求めたcx,cy,czをif分の判定に使用します。
なお、この方法はマップチップ自体がずれる場合には有用ではありません。
これでなんとかならないかなぁ。
Re:クォータービューの描画順位
Posted: 2009年7月08日(水) 22:38
by クロウ
Justyさん>
移動前、移動後との断続的な描画をやめたときの移動中はこのスクリーンショットのような状況になっています。
ねこさん>
離散的に描画されているといいましたが、つまり移動前と移動後だけ描画されていて、移動中の描画が抜けてしまっていることになっています。
このcx,cy,czをif文に判定するということは
if( ch[playe[/url].true_X/16 == x && ch[playe[/url].true_Y/16 == y )のx,yを
cx,cyに書き換えるということですか?
Re:クォータービューの描画順位
Posted: 2009年7月08日(水) 23:11
by ねこ
>クロウ様
逆ですね、ch[playe[/url].tru_X/16をcxに変えます。
http://ux.getuploader.com/neco3death/do ... Sample.lzh
pass:dxlib
サンプル作ってみましたが、一応こんな動きをすれば良いのかな。
※最初に「R」キー押してデータ読むとサンプル時のブロック読みます。
Re:クォータービューの描画順位
Posted: 2009年7月08日(水) 23:54
by クロウ
そうです。
そんな動きを求めています。
Re:クォータービューの描画順位
Posted: 2009年7月09日(木) 01:23
by ねこ
<そんな動きを求めています。
了解しました。と言っても既に前レスで必要な考慮は書いてますのでお試しください。
要は現在居る位置はどのマップチップ上なのかを移動元から移動先への進み具合で切り変えるだけです。
Re:クォータービューの描画順位
Posted: 2009年7月09日(木) 18:18
by クロウ
ねこさん>
上の二つのレスを参考に書いてみましたが・・・。
サンプル通りにいきません。
こんな変な動きをしています。
*上(画面上では右上)にいくとき、一度二つ分進んで移動先の座標に戻ってくる
*下(左下)に行くとき、一度上昇して移動先の座標に戻ってくる
*右(右下)に行くとき、少し上昇して移動する。
*左(左上)に行くとき、少し上昇して移動する。
下に書いてみた部分のどこが間違っているんでしょうか?
int x1,y1,z1,x2,y2,z2;//比較用変数
x1 = y1 = z1 = x2 = y2 = z2 = 0;//初期化
//プレイヤーが立っている位置
x1 = ch[playe[/url].true_X/16;
y1 = ch[playe[/url].true_Y/16;
z1 = mapData.fieldHigh[ch[playe[/url].true_Y/16][ch[playe[/url].true_X/16];
//プレイヤーの移動先の座標
if(ch[playe[/url].vector == up){
x2 = x1;
y2 = y1 - 1;
z2 = mapData.fieldHigh[y2][x2];
}
if(ch[playe[/url].vector == down){
x2 = x1;
y2 = y1 + 1;
z2 = mapData.fieldHigh[y2][x2];
}
if(ch[playe[/url].vector == left){
x2 = x1 - 1;
y2 = y1;
z2 = mapData.fieldHigh[y2][x2];
}
if(ch[playe[/url].vector == down){
x2 = x1 + 1;
y2 = y1;
z2 = mapData.fieldHigh[y2][x2];
}
float dx,dy,dz;//プレイヤーの移動中の座標(0.0~1.0)
dx = (ch[playe[/url].true_X - x1*16)/32.0;
dy = (ch[playe[/url].true_Y - y1*16)/16.0;
dz = (mapData.fieldHigh[y2][x2] - mapData.fieldHigh[y1][x1]) /(ch[playe[/url].true_X/16*ch[playe[/url].true_X/16 + ch[playe[/url].true_Y/16*ch[playe[/url].true_Y/16);
//描画位置の更新
int cx = dx < 0.5 ? x1 : x2;
int cy = dy < 0.5 ? y1 : y2;
int cz = dz < 0.5 ? z1 : z2;
if( cx == x && cy == y ){
charaDrawMain(px + dx*32 , py - dy*16 -48 , cz -1 , player , ch[playe[/url].type);
// 描画座標x、描画座標y、プレイヤーの高さ、キャラ番号(プレイヤー)、キャラタイプ(プレイヤー)
}
Re:クォータービューの描画順位
Posted: 2009年7月09日(木) 19:15
by ねこ
>クロウさん
1.dx,dy,dzはfabsをかけて絶対値で考える
題名通り、移動先と移動元との減算でどっちが奥かの考慮がないので、
dx = fabs(dx);とかかけてください
2.downが2個ある?
なんかif文にrightが無くてdownが2個あります。
今回アドバイスしてるのは「描画順」なので、描画位置がおかしいのはまた別の問題になります。
Re:クォータービューの描画順位
Posted: 2009年7月10日(金) 02:05
by クロウ
「移動している最中を描画しても描画順がずれない方法」を質問していたのに質問の内容がずれていました申し訳ありません。
直してみましたが、やはり断続的に描画されてしまいます。
おそらく、cx,cyだけだと断続的にしか描画しないので、dx,dyで移動中の描画位置を補正しているのだと思いますが、途中までは移動してくれています。しかし、cx,cyがx2,y2に切り替わった瞬間、それ以降は無視されて移動先の座標に飛んでしまっています。
dx,dyを切り替わった瞬間には切り替わる瞬間の一フレーム前の座標を考慮して
dx = abs(x2 - x1) - dx;
dy = abs(y2 - y1) - dy;
となるようにしてみましたが、やはり切り替わった瞬間に移動先の座標に飛んでいき、うまくいきませんでした。
Re:クォータービューの描画順位
Posted: 2009年7月10日(金) 09:35
by ねこ
>クロウさん
えっと、まずdx,dy,dz,cx,cy,czは「描画順のため」に求めているという認識を気持ち多めに持って下さい。
そのまま併用してもいいのですが、座標の逆補正が必要になるため「描画は別」という感じで。
問題点は恐らく
charaDrawMain( px + [color=red>dx[/color] * 32 , py - [color=red>dy[/color] * 16 -48 , [color=red>cz[/color] -1 , player , ch[playe[/url].type);
この赤文字の変数が「描画順のため」に求めた値であって、描画時に使っちゃいけません。
px,pyは現在座標に現在移動量を加算した座標が入っているのではないのでしょうか?
最初の投稿内容にあった
charaDrawMain(px , py -48 , mapData.fieldHigh[y][x] -1 , i , ch.type );//プレイヤーを描画
この処理で「描画順以外」は正常に描画されていたのならこれで良いのだと思いますが、
描画関数の先が分からないのでこれ以上はこちらも分からないですね。
Re:クォータービューの描画順位
Posted: 2009年7月10日(金) 10:56
by クロウ
ねこさん>
うまく伝わっていなかったようですみません。
最初の投稿内容の時点ではpx,pyは
px = hx-(y*32)+(x*32) + scroll_X(99);
py = hy+(y*16)+(x*16) + scroll_Y(99/*適当な値を入れている*/);
キャラの描画座標というよりは「画面内のマップチップの描画位置」であって、px,pyの中のx,yはfor文の変数そのままで、これ自体には移動中の座標が入っていないわけです。
scroll_X,scroll_Yはチップもプレイヤーもまとめて画面内をスクロールさせていますので、ほぼ移動中の座標とは関係がありません。。
charaDrawMain(px , py -48 , mapData.fieldHigh[y][x] -1 , i , ch.type );//プレイヤーを描画
の中身はいろんな場合のエフェクト処理が詰まっているんですが、基本的には
受け取った値をプレイヤー画像の描画として
DrawGraph( px , py - (mapData.fieldHigh[y][x] - 1)*16 , /*プレイヤー画像*/ , TRUE);
//mapData.fieldHigh[y][x] -1としているのはマップチップを一段のみ積んだ状態がマップデータ上では1であるためマップチップ描画ではこの場合2段積まれてしまうためです。
にそのまま移しているだけとなっています。
この状態では「移動前、移動後のみを描画する状態での正しい描画順」で描画されていまして、
「移動中も含めた場合、つまり
charaDrawMain( px + dx * 32 , py - dy * 16 -48 , cz -1 , player , ch[playe[/url].type);
のような状態で描画すると、右下方向と左下方向に進むとき、キャラクターの下半身ががマップチップの下に隠れてしまう」という状態となっています。
Re:クォータービューの描画順位
Posted: 2009年7月10日(金) 11:21
by ねこ
なるほどpx,pyがマップ位置で、後ろの加算が移動量って事ですね。
現状のバグというのはdx等は移動間0.0⇒1.0と変化していくため
0.0~0.5(移動元状態)の間はpx,pyが正常なのですが、
0.5~1.0(移動先状態)の間はpx,pyが移動先を基準としたマップ位置になっています。
そのため、移動先マップから移動量を加算した位置にずれて描画されているわけです。
if( dx < 0.5 && dy < 0.5 )
charaDrawMain( px + dx * 32 , py - dy * 16 - 48 , cz -1 , player , ch[playe[/url].type);
else
charaDrawMain( px - ( 1.0 - dx ) * 32 , py + ( 1.0 - dy ) * 16 -48 , cz -1 , player , ch[playe[/url].type);
上記のように変えてみてください。ひとまず移動中に突然ワープするような感じにはならないはずです。
Re:クォータービューの描画順位
Posted: 2009年7月10日(金) 23:37
by クロウ
ねこさん>
とりあえず、突然ワープする感じにはならなくなりました。
まだ描画位置がおかしい等のバグはありますが、これは自力で対処できそうです。
ありがとうございました。