ページ 1 / 1
遠近法
Posted: 2008年12月09日(火) 05:50
by えっと
プログラミング初心者ですが質問させて頂きます。
STGの背景のことなんですが、遠近法に従って画像をスクロールするやり方を教えてください。
奥のほうは縮小描画し、手前に来るにつれて、徐々に拡大されるようにしたいです。
(画像の大きさは描画される領域よりも充分に大きいです。)
コンパイラはVisualC++ 2008、ライブラリはDxライブラリです。
Re:遠近法
Posted: 2008年12月09日(火) 13:26
by Dixq (管理人)
まず、常にカウントアップしているカウンタを使って表現してみましょう。
今、「count」という、メイン関数のループで、1周に1度だけ毎回カウントアップされるカウンタがあったとします。
FPS60のゲームならcountは1/60秒に1度、カウントアップされていきます。
もし龍神録プログラミングの館をご覧になったことがあれば、同じなので、そちら参考にして下さい。
下に4つ簡単な問題を作っておきましたので解いてみて下さい。
1、countを使って、600カウントを1ループとし、0~599のカウントアップを繰り返す値をiCntに格納して下さい。
例
iCnt = count%1200 ;
2、iCntを使って、600カウントの時間で、1000ピクセル移動する速さで動く物体を描画するサンプルを書いて下さい(描画関数の座標部分だけでOK)
例
DrawGraph(0,iCnt,...);
3、600カウントの時間で、1000ピクセル移動する速さで動く物体を描画、
300カウントの時間で、1000ピクセル移動する速さで動く物体を描画 するサンプルを書いて下さい(上記同様)
4、640x480のサイズのウィンドウに640x480のサイズの画像をスクロール、例えば
DrawGraph(0,iCnt,...);
したのでは、スクロールするごとに上に隙間ができてしまいます。これを2枚座標をずらして描画することで、
描画されていない部分をなくして描画するサンプルを書いて下さい(上記同様)
これが4まで解ければ、ご自分のプログラムに応用できると思います。
あと、縮小描画するということですが、同じ画像をずらしてスクロールさせるのですか?
どのような画像かわかりませんが、かなり大きな画像になってしまい、メモリを食ってしまう恐れがあります。
例えば640x480のウィンドウに1/3描画して画面いっぱいに表示しようとしたら、9倍の面積の画像が必要です。
そこは、既に縮小した画像を用意したほうがいいかもしれません。
Re:遠近法
Posted: 2008年12月09日(火) 15:37
by えっと
1、
iCnt = count%600 ;
2、
DrawGraph(0,iCnt*1000/600,...);
3、
DrawGraph(0,iCnt*1000/600,...);
DrawGraph(0,iCnt*1000/300,...);
4、
1、のiCntでは出来なかったので、
iCnt = count%480;として、
DrawGraph(0,iCnt,...);
DrawGraph(0,iCnt-480,...);
これでいいんでしょうか?
画像の大きさをカウンタに連動させるには、
iCnt = count%480;
DrawRotaGraph(320,iCnt+240,3-iCnt*2/600,...);
DrawRotaGraph(320,iCnt+240-480,?
こうすると?(拡大率)の部分が書けなくなってくるし・・
やり方がわかりません・・。
Re:遠近法
Posted: 2008年12月09日(火) 15:55
by えっと
(訂正:下から5行目、DrawRotaGraph(...,3-iCnt*2/480,...)の間違いです。この書き方自体間違ってる可能性ありますが・・。)
Re:遠近法
Posted: 2008年12月09日(火) 16:03
by Dixq (管理人)
おぉ、いいですね。
ただ、
DrawGraph(0,iCnt*1000/600,...);
DrawGraph(0,iCnt*1000/300,...);
この部分は、例えば後者が「302」のような中途半端な数字の時出来ないので
int iCnt1 = count % 600;
int iCnt2 = count % 302;
DrawGraph(0,iCnt1*1000/600,...);
DrawGraph(0,iCnt2*1000/302,...);
こんな感じで変数分けた方がいいかもしれませんね。
お書きになった順番で計算すれば正確な値がきちんと出るはずです。
どちらがわかりやすいかは人によって違うでしょうけど、
DrawGraph(0, (int)(iCnt1/600.0 *1000) , ...);
iCnt1は0~599を繰り返す変数ですから、iCnt1/600.0こうすることでdouble型となり、
0<=○<1の範囲を変化する値となります。それに1000ピクセルをかけた方が理解しやすかったらこちらでもいいかもしれません。
もしお書きになったプログラムのほうがわかりやすければいちいちキャストする必要がない、その方法のほうが良いと思います。一応紹介だけしておきました。
あと、遠近法ということですが、もしかして、横スクロール、縦スクロールにおけるスクロールの速さを変え、階層わけして描画して奥行きを出す方法ではなく、
3次元空間を計算して描画する方法でしょうか?
もしよければここで公開している四聖龍神録Plusというゲームをみていただきたいのですが、
この1面の背景のように、スクロールの速さを変えて奥行きを出す方法か
メニューのExtraStageから選択できるPhantasmステージのように3次元空間を計算して物体の大きさを変化させる方法かどちらかあると思いますが、
どちらでしょうか?
Re:遠近法
Posted: 2008年12月09日(火) 16:55
by えっと
四聖龍神録Plusを見てみました。
なるほど、スクロールの速さを変えても奥行き感を表現できるのですね。
私がイメージしているのはまさにPhantasmステージのような3次元空間を利用するものです。
Re:遠近法
Posted: 2008年12月09日(火) 17:18
by Dixq (管理人)
DrawRotaGraphでも正確に計算することができれば可能かもしれませんが、
普通3D空間を表現するときは、3Dで描画する関数を使います。
DXライブラリは2D限定ライブラリですが、わずかに3Dで描画する関数も存在します。
例えば
http://homepage2.nifty.com/natupaji/DxL ... html#R3N22
この関数を使えば奥行きが表現出来ます。
ただこれは少々難しいです。
このサンプルを見ながら、変更しながら関数の使い方を学んでください。