マップ情報を格納する上での合理性

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

マップ情報を格納する上での合理性

#1

投稿記事 by 土門 » 6年前

今、二次元配列に格納したマップ情報から、
その要素要素の値に対して、あとで画像や当たり判定等を割り当てている
プログラムを書いています。
が、途中、この考え方が熟練者のプログラマから見て
どの程度合理的であるアルゴリズムかどうか知りたくなりました。
もしかしたら自分はそうとう面倒なことをしているんじゃないか?、と
不安になりましたので相談させて下さい。

ネットで調べるとMAP制作において大体が
二次元配列に格納したMAPの値(数字)を確認して
画像を表示したり、当たり判定を行ったりしていますよね。

ただ、自分は、MAP制作において、
ひとマスひとマスをオブジェクトとして存在させて、
そのクラスの中で座標、当たり判定の種類、使用する画像等の
情報を持たせることを考えました。
いわば、敵を作る状況と同じです。

そうしたのは、自分が慣れている、という理由が大半で
作るのが簡単だからです。
それにオブジェクトとして存在させると、
そのブロックに対していろいろなギミックを加えることが出来ますよね。
耐久力の変数を作って、壊れるブロックにするとか、
点滅フラグを作ってて、点滅するブロックにするとか。

でも、作りながら、それなりに広いマップのゲームの場合
(ここでは二次元配列[1000][1000]でマップを作る話で進めます)
マップ情報の二次元配列の要素の数字から判断して
画像表示や当たり判定を淡々と行う方が
メモリを食わないんじゃないか?と思い始めました。

自分の作り方だと、二次元配列の値を読みながら
ひとつひとつをブロックオブジェクトとして考え、
newでインスタンス化させて格納していきます。

ゲームはスクロールするタイプのもので、
画面はカメラに制御されており、
[1000][1000]の二次元配列に格納していたとしても
表示させるのはカメラのフレーム内のものに限定させるつもりですが
毎回インスタンス化させて[1000][1000]に格納させていることに
変わりはないので[1000][1000]にはすべてオブジェクトが
詰まっているはずですよね?
それって、容量的にはどうなんでしょうか?

毎回、UpdetaやDraw関数のところで
その要素内のオブジェクトの種類IDやチップNoを確認して
当たり判定や画像表示をさせるのと、
ただ単に毎回、2ケタ程度の値だけが入ってる二次元配列を
UpdetaやDraw関数のところで読ませて、その数値で判断させるのとで

どちらが容量を食わず、いや、ゲームのMAPを作る上で合理的なのでしょうか。
このふたつのやり方で考えられるメリット、デメリットを教えて頂ければ嬉しいです。

また、オブジェクトとして格納させるのは、
構造体として格納するのも同じですよね?
容量に変わりは出るでしょうか?

ちなみに、オブジェクトの中では
画像を読み込んだり、格納したりはしていません。
マップチップ自体はゲームステージのクラスのコンストラクタにて読み込ませていて、
オブジェクト内のIDでどれを使うかを判断、表示させています。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: マップ情報を格納する上での合理性

#2

投稿記事 by softya(ソフト屋) » 6年前

マップチップ1個をオブジェクトする必要性は置いておいて、メモリ容量は気にする必要はないレベルかと思いますが計算する癖は欲しいですね。
ただ、1000x1000のオブジェクトのnew/deleteの時間は結構掛かるかと思います。

一番気に成るのはマップのデータの持ち方です。
市販のゲームとかだとパーツが非常に複雑な情報を持っています。一例をご紹介します。
アニメーション情報だったり、当たり判定、ダメージ床など(書かれている壊れるや点滅も)、これらはアトリビュート(付加情報・属性)と言う考えでコンパクトに情報を表すことができます。つまり、パーツ番号ではな無くアトリビュート番号をマップ配列に書くと言う方法です。
アトリビュートはこれも構造体の配列で、様々な情報が構造体の情報として格納されています。アトリビュート番号でこれにアクセスします。
これらの情報は全てマップエディタでファイルデータとして作成すると言うのがプロ的な作り方の一つの方法です。
あくまで一例なので他にも方法はあります。

それと私はマップをオブジェクトにして、マップパーツ単位のオブジェクトは生成しないと思いますが考え方次第なのでどちらを選択するかは自由です。
マップが前景・背景など複数のレイヤーに分かれていても生成するか?とか考えるとすごい数に成るんじゃ!って不安はありますね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

土門

Re: マップ情報を格納する上での合理性

#3

投稿記事 by 土門 » 6年前

回答ありがとうございます。

>メモリ容量は気にする必要はないレベル

少し脱線しますが、聞いてもらえますか?
以前DXライブラリで作ったゲームがありまして
それはシューティングゲームなのですが
その自機の弾は少し複雑で、そのために弾は
弾をコンテナとしたlistで管理しておりました。
つまり、撃つたびにインスタンス化されてlistに格納されていくわけです。
そのゲームはファミコン風に作っており、画像自体の容量は大したことありませんが
画像はコンテナごとに読み込ませて保持させておりました。

で、ここが特殊なのですが、その弾は打ち損じたあと画面に残る、といったものでして、
ゲーム画面内に撃ち損じた弾がどんどん溜まっていくゲームでした。
するとどうでしょう。
連打してたら、2分もしないうちに画面が重くなりました。
fpsの数値を表示しながらやってみると、
どんどん下がっていったのです。
そこで、画像のせいだと思い、撃ち損じた弾がしばらくすると消える、
という風に変えました。すると当然のごとく、
ゲームをいつまで遊ぼうとfpsの数値は一定となりました。

以上のことがあってから、なにかと怖くなってしまったんです。
ファミコン風な画像でもすぐ表示限界が来るんだな、と。

なので、 softya(ソフト屋) さんのこの言葉は
やはり、コンテナごとに画像を保持していないデータの場合ですか?


>それと私はマップをオブジェクトにして、
>マップパーツ単位のオブジェクトは生成しないと思います

softya(ソフト屋) さんならどうされますか?
複雑な構造体をマップ情報として格納した二次元配列を
読んでいろいろされるのでしょうか?
参考にお聞かせ願えたらと思いますが

アバター
usao
記事: 1565
登録日時: 6年前

Re: マップ情報を格納する上での合理性

#4

投稿記事 by usao » 6年前

考えている「ギミック」が存在する箇所というのが
マップ全体に対してどの程度存在する想定なのかによって違うと思います.

仮に,全体のうち5割とか8割とかのマスが,複雑かつ場所ごとに異なる多種多様なギミックが配置されるようであれば,
ギミックの処理内容を表すようなオブジェクトの2次元配列を持つ方が楽なこともあるかもしれません.
しかし,ごく普通のRPGとかSLGみたいなのの「マップ」を考えると,おそらく
ほとんどの場所は「地形の種類を表すID値」くらいがあれば十分で,必要なデータは全てそこからたどれるはずです.
極少数のギミックのためのオブジェクトは そういったマップとは別に管理すれば済むはずで,
ほとんど存在しないそれらのために 余分な(使わない)データを大量に保持する,という状態には,自分だったらしません.

どうしてもマップを表す2次元配列上にてそれらのオブジェクトの存在を管理しなければならないとしても,
マップの各マスを表すデータは
{
地形種類ID
このマスに存在するギミックを表すインタフェースクラス型ポインタ(ほとんどの場合NULL)
}
みたいな程度で十分じゃないでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: マップ情報を格納する上での合理性

#5

投稿記事 by softya(ソフト屋) » 6年前

画像ハンドルを複数持つのはDirectXのコスト上無視できない容量や負荷がかかると思います。
出来るだけ画像は大きな塊でハンドルは少なく、DrawRectGraphなどで全体画像のパーツ一部分だけ使うようにすると無駄がなくなります。
それと、シングルトンな画像管理クラスなどで管理してできるだけ自分が画像ハンドル・画像オブジェクトを持たないようにします。

>複雑な構造体をマップ情報として格納した二次元配列を
>読んでいろいろされるのでしょうか?
>参考にお聞かせ願えたらと思いますが

マップ管理オブジェクトが管理するvector配列でマップ情報を持つでしょうね。
マップ管理オブジェクトが全てを管理するので、メソッドで処理するだけにするでしょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: マップ情報を格納する上での合理性

#6

投稿記事 by ISLe » 6年前

わたしならマップを二次元配列ひとつで表現しようとはしないですね。

土門さんは、マップチップひとつひとつをいわば敵と同じようにしたわけですよね。

わたしが実装する場合は以下のようにします。
一例です。

二次元配列のマップをひとつのオブジェクトとして扱います。
各要素はイメージ番号と、通過できるかできないかといったゲーム全体を通して共通で最低限の属性を持たせます。

壊れるブロックは、いわば、ひとつの敵です。
マップの上に居て、マップといっしょにスクロールさせることで背景にとけ込ませます。
普通の敵と同じで攻撃されるとヒビが入ったりといったイメージの変化があり最終的には壊れて消滅します。
マップの上に載っていた壊れるブロックが消滅すると、二次元配列のマップのイメージが見えるようになります。
壊れるブロックが消滅する際には、二次元配列のマップの該当位置の属性を通過可能に書き換えることで通過できるようになります。

壊れるブロックが壊れるところは二次元配列のマップのイメージ番号を書き換えていく方法もあります。
その場合は、壊れるブロック自体は姿を持ちません。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: マップ情報を格納する上での合理性

#7

投稿記事 by ISLe » 6年前

例えば、マップの東西南北にそれぞれ塔が建っていて、どの塔からでも攻略が可能、攻略した塔は崩落して二度は入れない、というゲームがあったとします。
中断データから再開して、崩落した塔のパターンを復元する際、背景はキャンバスのように書き換えられるほうが都合が良いです。

土門

Re: マップ情報を格納する上での合理性

#8

投稿記事 by 土門 » 6年前

皆さんの意見をもとに色々試行錯誤しまして、
やはりマップ情報だけの二次元配列でいくことにします。
壊れたり、なにかしらギミックを組み込むものについては
敵などと同じオブジェクトとして作ろうと思います。
ありがとうございました。

閉鎖

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