「2DゲームにおけるZ座標」について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
KKXY

「2DゲームにおけるZ座標」について

#1

投稿記事 by KKXY » 16年前

C++で「2DゲームにおけるZ座標」のプログラムを作ることはできないでしょうか?
「2DゲームにおけるZ座標」と言われても多くの人がわからないとおもいますが、
画像の情報の中に「Z座標」という変数があり、その変数が大きければ大きいほど
画像が手前に表示されるというものです。
RPGツクールのRGSSをいじったことがある人なら、すぐわかると思いますが・・・・。
このサイトの中にあったDitectXにはこのZ座標の制御をしてないので、
自分でプログラムをつくって制御しようと思ったのですが・・・。
「後で描画されたものほど手前に表示される」ことわかりましたので、
描画する画像の情報の中にZ座標の変数を入れて、そのZ座標の変数で描画の順番を制御しようと
思ったのですが、どうやればいいのかまったくわかりません。
一体どうやって制御したいかと申しますとまず、画像の情報に「どれだけ拡大縮小して描画するのか」
「どんな色調にするのか」という情報を入れたいため、画像を扱うためのクラスを作り、そのクラスの
メンバー変数には画像と色調や拡大縮小率などの「その画像をどう描画するのか」といった情報が入っている
メンバー変数とその画像を描画するために特別に用意されたメンバー関数があります。
 で、問題なのがそのメンバー関数の呼び出しの順番の制御なのですが・・・・・。
その順番をどうやれば制御できるのかさっぱりわかりません。しかもその画像を扱うためのクラスが
二種類もあるのです。

なんか説明がごちゃごちゃしてすみません・・・。要するにRPGツクールのRGSSの機能をC++で
再現したいということでRPGツクールのRGSSのヘルプを見れば自分が言いたいことが
よくわかると思うのですが・・・・。
 後、管理人さん、前に呼び捨てにしてすみませんでした。

御津凪

Re:「2DゲームにおけるZ座標」について

#2

投稿記事 by 御津凪 » 16年前

Z 座標=描画の優先順位
とすれば、呼び出し順序の処理方法が見えてくると思います。

つまり、 Z 座標が大きい順から画像の描画を行えば、
Z 座標が小さい画像が手前に来るようになります。

描画リストを用意し、そのリストで Z 座標が大きい順でソートを行い、
そのリストで描画を行えば簡単に実装できると思います。

山崎

Re:「2DゲームにおけるZ座標」について

#3

投稿記事 by 山崎 » 16年前

おはようございます。

今私が作っているゲームが、まさにその「Z軸のある2Dゲーム」ですね。
御津凪さんのおっしゃるとおり、オブジェクトはZ軸の大きさの順に描画しています。
正確に言えばZの値が小さいものから順に描画しています、
私はZ軸は手前の方向が+になるように設計しています。

私の場合は、オブジェクトは線形リストで管理しています。
線形リストなら、要素の追加や削除に結構自由が利きますしね。
(STLのリストを使わず、自分で双方向リストを作ったので制御が大変でしたが)
1フレームごとに線形リストを先頭から読み込んでいって、
Zの値でソートします。
そうすれば、次のフレームでは線形リストの先頭から順に描画していくだけで
遠くのものは先に、手前のものは後に描画することができます。

遠くにあるものほど小さく描画するのなら、
オブジェクトの大きさ(高さ、幅)をZの値で割ればいいと思います。
そうすれば、近くのあるものは大きく、遠くのものは小さく描画されます。
基本は「大きさをZで割る」でいいと思いますが、
微調整しないと表示されるオブジェクトが小さすぎたり大きすぎたりするかもしれません。
そこは、何度もデバッグで確認して調整するしかないですね。
ただ、私のゲームは遠近法は使ってないですが…。

RPGツクールをやったことが無いのでそれに関してはちょっと何も言えないですね。

KKXY

Re:「2DゲームにおけるZ座標」について

#4

投稿記事 by KKXY » 16年前

>描画リストを用意し、そのリストで Z 座標が大きい順でソートを行い、
そのリストで描画を行えば簡単に実装できると思います。

そこまで考えたのですが
そのリストの作り方がどうもわからなくて・・・。

御津凪

Re:「2DゲームにおけるZ座標」について

#5

投稿記事 by 御津凪 » 16年前

突っ込んだ処理の説明をすると、

描画の順序を記憶するためのリストを準備し、
そのリストへ追加する時点で既にリストに追加されている描画情報から適切な位置に追加していくことで、
常にソートされたリストを構築することが出来ます。
ちなみに描画情報のデータは実際の描画クラスのインスタンスでも構いません。(前後関係が確認できるならOK)
そして、そのリストに登録されているデータを元に描画処理を行っていけば、求めている処理が出来ます。

山崎さんの仰るような、比較的処理の負荷の少ないリスト構造を扱う場合は比較的簡単ですし、
ここの掲示板では過去ログにはいくつかの話題に載っていますので、詳しいリストの構築方法はそちらを参考にしたほうが早いかもしれません。
(「線形リスト」や「双方向リスト」等で探すと引っかかりやすいです)

KKXY

Re:「2DゲームにおけるZ座標」について

#6

投稿記事 by KKXY » 16年前

すみません、言い方間違えました。
「リストそのもの」の作り方ではなく、「インスタンス」のリスト、
または「クラスのリスト」の作り方がわからないのです。

山崎

Re:「2DゲームにおけるZ座標」について

#7

投稿記事 by 山崎 » 16年前

リストの作り方、ですね。

とりあえずSTLコンテナのlistを使うことをお勧めします。
明確な理由が無い限り、自分で線形リストを0から実装する必要もないでしょう。
STLコンテナを使えば、最初から基本的な機能はそろっていますしね。

とりあえず、「STLコンテナ」とは何かご存知でしょうか?
ご存じないのならばこちらのサイトなどを読んでみるとよいでしょう。先頭のhは抜いてあります。
ttp://www.geocities.jp/ky_webid/cpp/library/003.html

例えば、class Aというクラスがあったとしましょう。
STLコンテナのlistを使ったとするならば、クラスAのインスタンスを格納するリストは
list<A> listA;
このように宣言するといいでしょう。listAというのはそのリストにつけた名前です。

・・・それとも、STLコンテナを使わず自分でリストを実装したい・・・とかでしょうか?

KKXY

Re:「2DゲームにおけるZ座標」について

#8

投稿記事 by KKXY » 16年前

>class Aというクラスがあったとしましょう。
STLコンテナのlistを使ったとするならば、クラスAのインスタンスを格納するリストは
list<A> listA;
このように宣言するといいでしょう。listAというのはそのリストにつけた名前です。

この方法でやってみた結果、描画クラスのリストを作ることができました。
後は描画リストをどうやって制御するのかということなのですが、そこでまた問題が
発生してしまいました。

それは描画クラスをどうやって描画リストに入れるかです。
一応、クラスを宣言する→宣言したクラスをリストにいれる、という方法で出来るのですが、
できれば宣言したと同時にクラスをリストの中に入れたいのです。
例にすると描画クラスAを宣言したときに、その時にはすでに描画リストにAというクラスが入っている
ということをしたいのです。

それと僕が2・3番目にした質問は「変数」のリストは宣言して作れても、
「クラス」のリストは宣言して作ることが出来ない、という
意味だったのですが・・・。説明不足だったのでしょうか・・・・。

御津凪

Re:「2DゲームにおけるZ座標」について

#9

投稿記事 by 御津凪 » 16年前

> できれば宣言したと同時にクラスをリストの中に入れたいのです。

(「宣言」ではなく「生成」なのでは?)

これは、コンストラクタの時にリストへ登録し、デストラクタが呼ばれたらリストから外す構造を持てば、
インスタンスが存在する間、必ずリストに追加されている状況を作れるはずです。
(ただし、リストが作られる前に描画クラスを生成することが出来なくなるので注意)

KKXY

Re:「2DゲームにおけるZ座標」について

#10

投稿記事 by KKXY » 16年前

>これは、コンストラクタの時にリストへ登録し、デストラクタが呼ばれたらリストから外す構造を持てば、
インスタンスが存在する間、必ずリストに追加されている状況を作れるはずです。
(ただし、リストが作られる前に描画クラスを生成することが出来なくなるので注意)

まさにその通りのことをやりたいのですがそのやり方がわからないのです・・・・。

それと「宣言」ではなく「生成」だったのですね。
間違いを指摘していだたいてありがとうございます。

御津凪

Re:「2DゲームにおけるZ座標」について

#11

投稿記事 by 御津凪 » 16年前

list<A*> g_list;
class A{
    A(){g_list.add(this);}
    ~A(){g_list.remove(this);}
};
こんな感じで出来ませんか?
(ちょっと変なコードですが)

KKXY

Re:「2DゲームにおけるZ座標」について

#12

投稿記事 by KKXY » 16年前

やってみたらlistの生成の所で"Aは定義されていない識別子です"というエラー文が出て無理でした・・・。
そこで
クラスAの基底クラスとなるクラスBを作る→クラスBのリストを作る
→クラスBを継承したクラスAを作り、そのコントラクタにg_list.push_front(this);の構文を、
デストラクタにg_list.remove(this);の構文を入れる。
とやったら出来ました。
ただ、listに入っているクラスのメンバー関数を呼び出す方法がわかりません。
そこがわかれば完成すると思うのですが・・・。
それと出来ればこれ以外の方法があったら教えてもらえますでしょうか。
ちなみにadd(this)にしたらエラーが出ました。自分が持っているコンパイラは
この命令をサポートしていないのでしょうか・・・・。
なお、使っているコンパイラはvisual C++ 2008です。

御津凪

Re:「2DゲームにおけるZ座標」について

#13

投稿記事 by 御津凪 » 16年前

リストへの追加(add)と削除(remove)としてわかりやすく記述したので、実際のSTLの list には無い命令です。

上記で書いたコードだと、

list<A*> g_list;

の前に、

class A;

を書いておくとエラーが消えるはずです。

あと、格納したリストのデータにアクセスするには、
list<A*>::iterator p = g_list.begin();
while( p != g_list.end() ) {
    (*p)->Draw();
    ++p;
}
といった感じで出来ますよ。
あと、適当な位置にデータを挿入するのも、この方法を使って insert すればできます。


> それと出来ればこれ以外の方法があったら教えてもらえますでしょうか。

となると、双方向リストを自分好みに作るか、プログラム側で描画順序を調整する(グループ分け等で)ぐらいになるかと思います。
後者の方は実装を注意すれば比較的簡単に実装できますが、グループ内の前後関係は維持できません。
しかし、それほど前後関係にこだわらないようなゲーム(ノベル系や2DのRPG系など)なら非常に有効です。

KKXY

Re:「2DゲームにおけるZ座標」について

#14

投稿記事 by KKXY » 16年前

やってみたら作ることができました。
皆さん、どうもありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る