ページ 1 / 1
Dxライブラリを使用した擬似3D縦スクールの方法
Posted: 2015年7月01日(水) 18:34
by ayapan
初めまして、ゲーム製作にあたり疑問な点があったので質問させてください。
一枚の画像を奥行きのあるように擬似的に3D表示したいのですが
その方法を調べてみても仕組みがいまいち理解できません。
このサイトに私が行いたいことが載っておりますが
肝心の方法が書いてなかったのでここで質問させていただきます。
http://homepage3.nifty.com/ae85fcmxs/02-info-ab4-3.html
この動作はラスタースクロールの応用という形でよいのでしょうか?
それとも別の方法をとっているのですか。
お教えください。
よろしくお願いします。
Re: Dxライブラリを使用した擬似3D縦スクールの方法
Posted: 2015年7月01日(水) 19:29
by usao
オフトピック
ぱっと見,単に射影変換しているだけに見える
Re: Dxライブラリを使用した擬似3D縦スクールの方法
Posted: 2015年7月02日(木) 12:06
by ayapan
usao様
回答ありがとうございます。
射影変換をDXライブラリで行う場合、
関数として存在するのでしょうか。
よろしくおねがいします。
Re: Dxライブラリを使用した擬似3D縦スクールの方法
Posted: 2015年7月02日(木) 13:06
by softya(ソフト屋)
射影変換を自分で計算する気がないなら、3Dにしてしまったほうが早いですよ。
擬似3Dに関しては
「龍神録プログラミングの館」
http://dixq.net/rp/
ここのサイトのコンテンツですが、57~59章3D背景を作ってみようを参考にされてはどうでしょう。
【補足】
> この動作はラスタースクロールの応用という形でよいのでしょうか?
ラスタースクロールは、昔のSFCやメガドライブなら有効な方法ですが現代的にはかえって面倒です。
Re: Dxライブラリを使用した擬似3D縦スクールの方法
Posted: 2015年7月02日(木) 19:01
by ISLe()
DrawModiGraphを使うと斜めに変形した四角形に描画できます。
変形したい部分を全部オフスクリーンにふつうに描画して、オフスクリーンを変形して描画するのが簡単です。
継ぎ目の問題も出ないので。
Re: Dxライブラリを使用した擬似3D縦スクールの方法
Posted: 2015年7月02日(木) 22:36
by ayapan
ISLe()様
回答ありがとうございます。
教えていただいた関数をつかい表示させることが出来ました。
しかし、これをループさせるためにはどうすればよいのでしょうか。
よろしくお願いします。
Re: Dxライブラリを使用した擬似3D縦スクールの方法
Posted: 2015年7月02日(木) 22:45
by softya(ソフト屋)
ISLe()さんの言うとおりに実装が出来たのなら、毎フレームオフスクリーンレンダリングでスクロールする画面をレンダリングするだけです。
つまり、オフスクリーンに通常の2Dのスクロール描画を行えばよいのです。ループをするのも、マップチップを使うのも自由自在です。
Re: Dxライブラリを使用した擬似3D縦スクールの方法
Posted: 2015年7月02日(木) 22:49
by ayapan
softya(ソフト屋) 様
回答ありがとうございます。
オフスクリーンレンタリングという難しい用語を調べても
分からなかったため再度質問してしまいました。
わかりやすく説明していただくことは可能でしょうか。
大変申し訳ございませんが、よろしくおねがいします。
Re: Dxライブラリを使用した擬似3D縦スクールの方法
Posted: 2015年7月02日(木) 22:58
by softya(ソフト屋)
オフスクリーン・レンダリングがわからないんですね?
そう書いて頂くと話は早いんです。
>しかし、これをループさせるためにはどうすればよいのでしょうか。
これでは、そう読み取れません。
オフスクリーンレンダリング(直接表示されない画面への描画)はMakeScreenを利用します。
http://homepage2.nifty.com/natupaji/DxL ... html#R3N25
サンプルでは、MakeScreen( 20, 20, FALSE ) で小さい画面に書いてますが、これを必要なサイズ640x480などにしてください。
Re: Dxライブラリを使用した擬似3D縦スクールの方法
Posted: 2015年7月02日(木) 23:35
by ayapan
softya(ソフト屋) 様
丁寧に回答していただきありがとうございます。
お教えいただいたリンク先を参考に考えましたが
私はいまいち理解することができませんでした。
上下キーで入力を与えると
ただ画像が移動するだけで上のほうは縮小されたままです。
オフスクリーンレンタルなどで解決できるのでしょうが
これ以上解決の糸口が見つかりません。
移動させるごとに拡大と縮小を行いたいです。
失礼ですが画面サイズ960*540の場合で
スクロールを行いたい場合どのような処理を行えば良いでしょうか。
お教えください。
よろしくお願いします。
Re: Dxライブラリを使用した擬似3D縦スクールの方法
Posted: 2015年7月02日(木) 23:41
by softya(ソフト屋)
DrawModiGraphの方を動かしたらダメですよ。
オフスクリーン側の画像を動かすんです。
// 作成した画像を描画対象にする
SetDrawScreen( handle ) ;
の後で描画する画像の方です。
> ただ画像が移動するだけで上のほうは縮小されたままです。
それはDrawModiGraphの正しい動作にしか思えません。
>オフスクリーンレンタル
無闇にややこしくなるので妙な略は避けてくださいね。
【補足】
この場合、一番実現が容易なのがオフスクリーンレンダリングなので使用しないと言う選択肢は考えられません。
他にも色々方法はあるのですが、もっと難易度が上がります。
とりあえず、普通の2Dのスクロールが出来ていることが前提となりますので、その上での応用と考えてください。
短い実験用のソースコードを投稿してもらうと回答がつきやすくなります。
Re: Dxライブラリを使用した擬似3D縦スクールの方法
Posted: 2015年7月02日(木) 23:55
by ayapan
softya(ソフト屋) 様
回答ありがとうございます。
まだ何も書いていないコードを載せます。
コード:
#include "DxLib.h"
// フォントカラー定義
#define WHITE GetColor(255,255,255)
#define GREEN GetColor( 0,255, 0)
// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// タイトルの設定
SetMainWindowText("test");
// ウィンドウモードに設定
ChangeWindowMode(TRUE);
// 画面サイズの決定
SetGraphMode(960, 540, 32);
// DXライブラリの初期化
if (DxLib_Init() == -1) return -1;
// 描画先を裏画面に設定
SetDrawScreen(DX_SCREEN_BACK);
int handle = MakeScreen(960, 540, FALSE);
int sample3 = LoadGraph("sample3.jpeg");
int upDown = 0;
// メインループ
while (ScreenFlip() == 0 && ProcessMessage() != -1 && ClearDrawScreen() != -1)
{
if (CheckHitKey(KEY_INPUT_DOWN) == 1) upDown++;
else if (CheckHitKey(KEY_INPUT_UP) == 1) upDown--;
DrawModiGraph(250, 0, 960 - 250, 0, 960, 540, 0, 540, sample3, FALSE);
DrawFormatString(50, 50, WHITE, "ようこそ、DXライブラリの世界へ");
}
// DXライブラリの終了処理
DxLib_End();
// プログラムの終了
return 0;
}
私のイメージとしては
画面一番下は端から端まで画像が表示されており
画面一番上はX座標が250~710の間だけで表示されるように
台形の形になっており上下キーを押下すると同じ画像が
先ほどの形を保ったまま永遠ループするような仕組みを作りたいと思っています。
(つまり、画像を下にスクロールすると画像の下側が上から出てくるように)
softya(ソフト屋) 様にたくさんお教えいただきましたがどこにどのような
処理を入れればいいのかが検討もつきません。
また、オフスクリーンレンタルは私の誤字です。
大変申し訳ございませんでした。
コードを挿入する場所をお教えいただけるでしょうか。
よろしくお願いします。
Re: Dxライブラリを使用した擬似3D縦スクールの方法
Posted: 2015年7月03日(金) 00:03
by softya(ソフト屋)
これだと2Dスクロールが実装できていないので、まずそちらを実装してください。
「龍神録プログラミングの館」
http://dixq.net/rp/20.html
これを見たほうがわかりやすいと思います。
それができたら、更にオフスクリーンレンダリングで改造します。
Re: Dxライブラリを使用した擬似3D縦スクールの方法
Posted: 2015年7月03日(金) 00:08
by ayapan
softya(ソフト屋) 様
回答ありがとうございます。
教えていただきましたURLのチュートリアルを
すべてこなしてもわからなかったら再び質問させていただきます。
初歩的な私にわざわざ付き合っていただきありがとうございます。
それではチュートリアルをこなしてみます。
Re: Dxライブラリを使用した擬似3D縦スクールの方法
Posted: 2015年7月03日(金) 18:37
by ISLe()
DrawModiGraphでオフスクリーンを台形に描画した場合、縦方向の奥行きは考慮されないので、スクロールすると上の方ほど速度が速く動いているように見えてしまうので、ダメでした。
質問にあるリンク先のように細かく変形したとしても、タイル単位では奥行きがないので不自然さを完全に排除することはできません。
奥行きを正しく表示するには、DrawBillboard3Dを使って、3D空間にオフスクリーンを描画する必要がありますね。
オフスクリーンに描画するところまでは共通なので、質問者さんはそのまま作業を続けて良いです。
DrawModiGraphだと奥行きがおかしいというサンプルコード。
► スポイラーを表示
コード:
#include "DxLib.h"
static int positive_remainder(int dividend, int divisor)
{
if (divisor <= 0) return 0; // エラー
if (dividend < 0) {
dividend = -(dividend + 1);
dividend %= divisor;
dividend = divisor - 1 - dividend;
}
else {
dividend %= divisor;
}
return dividend;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
ChangeWindowMode(TRUE);
if (DxLib_Init() != 0) return 0;
int screenWidth, screenHeight, Dummy;
GetScreenState(&screenWidth, &screenHeight, &Dummy);
int offscreenHandle = MakeScreen(screenWidth, screenHeight);
int imageHandle = LoadGraph("sample3.jpeg");
int imageWidth, imageHeight;
GetGraphSize(imageHandle, &imageWidth, &imageHeight);
int scrollX, scrollY;
scrollX = scrollY = 0;
while (ProcessMessage() == 0 && ScreenFlip() == 0 && ClearDrawScreen() == 0) {
if (offscreenHandle < 0 || imageHandle < 0) break;
if (CheckHitKey(KEY_INPUT_LEFT) == 1) scrollX++;
if (CheckHitKey(KEY_INPUT_RIGHT) == 1) scrollX--;
if (CheckHitKey(KEY_INPUT_UP) == 1) scrollY++;
if (CheckHitKey(KEY_INPUT_DOWN) == 1) scrollY--;
SetDrawScreen(offscreenHandle);
int offsetX, offsetY;
offsetX = positive_remainder(scrollX, imageWidth);
offsetY = positive_remainder(scrollY, imageHeight);
if (offsetX > 0) offsetX -= imageWidth;
if (offsetY > 0) offsetY -= imageHeight;
while (offsetY < screenHeight) {
int save_offsetX = offsetX;
while (offsetX < screenWidth) {
DrawGraph(offsetX, offsetY, imageHandle, FALSE);
offsetX += imageWidth;
}
offsetX = save_offsetX;
offsetY += imageHeight;
}
SetDrawScreen(DX_SCREEN_BACK);
DrawModiGraph(
0 + (screenWidth / 4), 0,
screenWidth - (screenWidth / 4), 0,
screenWidth, screenHeight,
0, screenHeight,
offscreenHandle, FALSE
);
}
DxLib_End();
return 0;
}