ページ 1 / 1
アクションゲームの設計において、どのタイミングに画像ファイルをメモリに入れるべきか
Posted: 2009年4月04日(土) 20:18
by けんたろうちゃん
現在、C++とDXライブラリを使用して、マリオやロックマンのようなアクションゲームを作成しています
アクションゲームでは場面によって様々な種類の敵やアイテムが出現しますね
今回の質問は、その「敵」や「アイテム」の画像をいつメモリに入れるべきかという質問です
龍神録プログラミングの館の方では「ステージの初めに、そのステージで使用する画像を全て読み込む」
という方法が使われています
それに対し、現在、自分が行おうとしている方法は以下のようです
//------------------------------------------
敵1が出現
↓
敵1クラスのコンストラクタで敵1の画像をメモリに読み込む
敵1が消滅
↓
敵1クラスのデストラクタで敵1の画像をメモリから削除する
//------------------------------------------------
この方法の利点は
・ステージごとに出現する敵に使用する画像を初めに読ませる必要がないため、
ステージの作成が非常に楽であること(どの敵を使用するか、あらかじめ決める必要がない)
予想される欠点としては
・いちいち敵出現イベントごとに、画像を読み込むため、速度が遅そう
・同じ種類の敵が出るとき、同じ画像をメモリに格納してしまい、余分にメモリを使用する
などがあると思われます
一体、どういった設計方法をとるべきでしょうか
ご教授おねがいします
ちなみに現在のクラス設計は以下のようです
//画像を読み込み、描画を行うクラス
class Graph{
protected:
int Grhandle[32] //格納されるイメージハンドルを示す変数
public:
load(char *FileName); //変数にグラフィックハンドルを保存する関数
del();//メモリの解放処理をする関数
draw();//描画
};
//敵、アイテムなどの抽象クラス
//これを継承させて、様々な敵やアイテムを作成する
class Object{
protected:
Graph graph;
public:
Object(){graph.load("画像.bmp");}//コンストラクタ(ここで画像読み込み)
~Object(){graph.del();}
run(); //敵の消滅判定とか移動とかの実行
};
注:これはイメージであって実際のコードは違います
Re:アクションゲームの設計において、どのタイミングに画像ファイルをメモリに入れるべきか
Posted: 2009年4月04日(土) 20:34
by yu
あらかじめどのような敵が出るかを調べて、
使う画像のみを始めにロードすればいいですかね?・・・
Re:アクションゲームの設計において、どのタイミングに画像ファイルをメモリに入れるべきか
Posted: 2009年4月04日(土) 20:37
by kazuoni
クラス設計は置いておいて・・・
自分はですが、ステージが始まる直前の「NOW LOADING」
のような時にでるであろう画像を読み込ませるが一番いいかと思います。
理由はけんたろうちゃんさんがおっしゃる通りです。
しかし、長所はそこにはないかのように思います。
ランダムに敵を出すなら、画像アドレスの入ったの配列から乱数で一つ取得すればことは足りるかと思います。
画像が数千などとなる場合はいろいろ考慮が必要かと思いますけど・・・。
Re:アクションゲームの設計において、どのタイミングに画像ファイルをメモリに入れるべきか
Posted: 2009年4月04日(土) 20:38
by けんたろうちゃん
yuさんおっしゃる方法がまさに龍神録プログラミングで使われている方法ですね
やはり処理速度が重要なゲームではそういう方法が良いのですかね?
Re:アクションゲームの設計において、どのタイミングに画像ファイルをメモリに入れるべきか
Posted: 2009年4月04日(土) 20:47
by yu
すみません。orz
説明不足ですね;
>どの敵を使用するか、あらかじめ決める
これを自動で行うということです。
たとえば敵の種類が複数あって、敵の出現が10匹に設定されていたら
10回ループを使って種類を調べ、被らなかった種類の番号を記憶して
その番号の画像だけをステージの最初にロードすればいいかなと言うことです・・・。
でも、今簡単に考えたので欠点があるかもしれません。orz
Re:アクションゲームの設計において、どのタイミングに画像ファイルをメモリに入れるべきか
Posted: 2009年4月04日(土) 20:50
by けんたろうちゃん
>>kazuoniさん
やはり、初めに使用する画像をメモリに読み込み、静的領域の変数にグラフィックハンドルを保存し、
その静的領域からの引数によって表示するという方法が良いですかね
Re:アクションゲームの設計において、どのタイミングに画像ファイルをメモリに入れるべきか
Posted: 2009年4月04日(土) 21:04
by SooA
yuさんが書かれている方法が最もベターかと思います。
特にアクションゲームではプレイ中のラグは
タブーですので最初に必要なデータを読み込んでおくほうが良いと思います。
yuさんの文章で感じは掴めると思うので途中で書くのやめました。
↓
パラメータ(体力、アイテム、使用イメージ 等 )と
出現データ( タイミング、座標、行動パターン 等 )の
データをそれぞれ用意します。
1、パラメータを読み込み
2、ステージ読み込み、
3、出現データを読み込み
4、出現データからそのステージで使用されている
キャラデータ&イメージをセットする
Re:アクションゲームの設計において、どのタイミングに画像ファイルをメモリに入れるべきか
Posted: 2009年4月04日(土) 21:20
by けんたろうちゃん
はい、その方法で実現しようと思います
ところで、少し違う質問なのですが、答えてもらえたらうれしいです
①DXライブラリのLoadGraph関数でint型変数にハンドルを渡しますよね
その「ハンドル保存用int型変数にグラフィクハンドルが入っていない」ことを調べることはできるのでしょうか?
②DXライブラリのDeleteGraph関数でLoadDivGraph関数で保存されたハンドルGrHandle[/url]を解放する場合、
int hoge[5];
LoadDivGraph("ほげ.bmp", 5, 5, 1, 32, 32, hoge);
for(int i=0; i<5; i++) DeleteGraph( hoge );
とするしかないのでしょうか?
これだと、あらかじめhogeに5つ入るということがわからないといけないという問題があります
STLを使って、制御するという方法は可能なのでしょうか?
Re:アクションゲームの設計において、どのタイミングに画像ファイルをメモリに入れるべきか
Posted: 2009年4月05日(日) 00:19
by fumi
①については、
ghandle = DeleteGraph( ghandle );
としておけばghandleには0(又は-1)が入るはずなので、それをチェックすれば良いと思います。
②については、私も同じようなことで悩んだことがありますが、STLのマップで対処しました。
std::map<const char *, int> imageMap
const char*は文字列キー(ロードするファイル名と同じにしておけば楽?)、intはghが入ります。
ただ、STLは格納するオブジェクトの数が増えると結構重くなるので、読み込む画像が多いなら
十分な大きさの配列を確保した方が無難な気がします。
Re:アクションゲームの設計において、どのタイミングに画像ファイルをメモリに入れるべきか
Posted: 2009年4月05日(日) 01:25
by Justy
>2 DeleteGraph関数でLoadDivGraph関数で保存されたハンドルGrHandle[/url]を解放する場合
>~とするしかないのでしょうか
配列を使うのなら、その配列の要素数を調べて forの条件文で使えばいいのではないでしょうか。
[color=#d0d0ff" face="monospace] for(int i=0; i<sizeof(hoge)/sizeof(int); i++) DeleteGraph( hoge );[/color]
まぁでもせっかく C++を使っているのですから、その配列は int型という生の値で扱うのではなく、
ハンドルの解放をデストラクタで行うテクスチャクラスにするのがベストかと思います。
□ fumiさん
>std::map<const char *, int> imageMap
その定義だと、使用上の制限としてどこかで文字列の実体を確保しておかなければ
ならなくなりませんか?
Re:アクションゲームの設計において、どのタイミングに画像ファイルをメモリに入れるべきか
Posted: 2009年4月05日(日) 08:37
by fumi
>>Justyさん
状況にもよると思いますが、
std::map<const char *, int>::iterator it;
int gh;
it = imageMap.find( "文字列" );
gh = it->second;
といった感じで使っていたので、文字列は特に確保しておく必要はなかったと思います。
Re:アクションゲームの設計において、どのタイミングに画像ファイルをメモリに入れるべきか
Posted: 2009年4月05日(日) 11:06
by Justy
>状況にもよると思いますが
そうなんですが、たとえば
[color=#d0d0ff" face="monospace]
typedef std::map<const char *, int> ImageMapType;
ImageMapType imageMap;
void LoadSceneTexture()
{
for(int n=0; n<100; ++n)
{
char fileName[0x10];
std::sprintf(fileName, "%s%02d.bmp", "image", n);
int grp = ::LoadGraph(fileName);
if(grp != -1)
imageMap.insert(ImageMapType::value_type(fileName, grp));
}
}
[/color]
のように挿入時に指定する名前がローカル変数だったりすると
関数を抜けた後は無効なポインタを保持することになるので、
使い方に制限があるのではないか、ということです。
(静的領域にとってしまえば問題はないですが)
Re:アクションゲームの設計において、どのタイミングに画像ファイルをメモリに入れるべきか
Posted: 2009年4月05日(日) 12:23
by けんたろうちゃん
>>fumiさん
mapを使う方法ですか
つまり、findを使って、文字列キーに対応するハンドルintを得て描画するということですよね(勘違いだったらすいません)
でも、素人考えかも知れませんが、描画するごとにfindすると、すごく処理が遅くなりそうな気がするのですけど・・・
実際に作ったわけではないので、違うかもしれませんが
>>Justyさん
>まぁでもせっかく C++を使っているのですから、その配列は int型という生の値で扱うのではなく、
>ハンドルの解放をデストラクタで行うテクスチャクラスにするのがベストかと思います。
すいませんここが理解できませんでした^^;
おそらくDXライブラリを使用しないで、描画部分を自作したほうが良いということかな?
まだまだ、自分の実力が不足しているようですね
一応解決済みにしておきます
Re:アクションゲームの設計において、どのタイミングに画像ファイルをメモリに入れるべきか
Posted: 2009年4月05日(日) 13:01
by fumi
解決になってるので、何か申し訳ないですが…
>>Justyさん
言われてみれば…その通りですね。
かなり危険なことをしていたことに気づかされましたorz
ご指摘ありがとうございます。
>>けんたろうちゃんさん
>描画するごとにfindすると、すごく処理が遅くなりそうな気がするのですけど
はい。やはり速度を気にするのであれば配列にしてしまうのが1番だと思います。
Re:アクションゲームの設計において、どのタイミングに画像ファイルをメモリに入れるべきか
Posted: 2009年4月05日(日) 16:48
by Justy
□ けんたろうちゃんさん
>おそらくDXライブラリを使用しないで、描画部分を自作したほうが良いということかな?
いえ、違います。
グラフィックハンドルを扱うクラスを作ります(仮に Textureクラスとしておきます)。
このクラスは int型のグラフィックハンドルを持ち、デストラクタでハンドルの解放を
行うようにします。
こういうクラスを作っておけば、 int hoge[5] だった配列は [color=sans-serif]Texture hoge[5][/font]
となり、解放そのものは Textureクラスが行うので明示的に DeleteGraph()を呼び出す
必要がなくなります。
□ fumiさん
>静的領域にとってしまえば問題はないですが
と書きましたが、見直したら問題大ありでした。
よく考えたら
[color=#d0d0ff" face="monospace]
imageMap.insert(ImageMapType::value_type("A", 0));
imageMap.find("A");
[/color]
一つめの "A"と二つ目の "A"が同じポインタである保証もないんですよね。
Re:アクションゲームの設計において、どのタイミングに画像ファイルをメモリに入れるべきか
Posted: 2009年4月05日(日) 19:00
by けんたろうちゃん
Textureクラスとはそういうことですか
まだまだ理解力が足りなくて、具体的なコードはかけませんが、少しだけ理解できたような気がします