ページ 1 / 1
画像の読み込み(LoadGraph)について
Posted: 2014年9月10日(水) 14:11
by 黒猫
こんにちは、再びお世話になります。
今回は画像の読み込みについてお聞きしたいことが2つあり、投稿しました。
1.LoadGraphの解放(DeleteGraph)
LoadGraphで生成したハンドルはDeleteGraphの関数で削除し、メモリを開放出来ますが、これは頻繁に使用するべきなのでしょうか?
例えば横スクロールアクションゲームを制作するとして、1面でのみ使用する画像は例え数枚だとしても1面終了後にDeleteGraphするべきですか?
現在制作しているゲームはそれほど多くの画像を使わないため、ゲーム起動時の初期化のときにすべての画像ハンドルを生成してしまおうと考えているのですが
これは設計としてあまり良くないことでしょうか?
2.効率的なLoadGraphする方法
例えば次の様なコードは正常に実行できると思います。
コード:
int hd[100];
hd[0] = LoadGraph("Graphic\\0.png");
hd[1] = LoadGraph("Graphic\\1.png");
hd[2] = LoadGraph("Graphic\\2.png");
hd[3] = LoadGraph("Graphic\\3.png");
…
hd[99] = LoadGraph("Graphic\\99.png");
ですがこのようなコードは明らかに無駄があるように思えます。
forやitoaを使って何とか出来ないかと試行錯誤してみたのですが、どうしたら良いのかがわかりません。
良い方法がありましたら教えて下さい。
Re: 画像の読み込み(LoadGraph)について
Posted: 2014年9月10日(水) 15:25
by namari
後半だけ。
LoadGraphはcharを読み込んでいるので,
コード:
char hoge[64];
for(i=0;i<100;i++){
sprintf(hoge,"Graphic\\%d.png",i);
hd[i]=LoadGraph(hoge);
}
こんな感じでしょうか。
Re: 画像の読み込み(LoadGraph)について
Posted: 2014年9月10日(水) 16:30
by Ketty
>1.LoadGraphの解放(DeleteGraph)
以下、個人的な思想なので、参考程度にどうぞ。
私は、基本的には、要らない画像(や音楽)はロードさせない、要らなくなった時点で破棄するという考えです。
理由は、メモリをなるべく占有したくないのが主です。
>これは設計としてあまり良くないことでしょうか?
悪いとは思いません。
例えば、ごくごく小さなゲームを作られるのであれば、実装を簡素化できるので有効なやり方だと思います。
一方で、画像枚数が増えたり、ゲームの規模が大きくなったり、今後の拡張を考えたときには、
そのやり方ではいずれ限界が来るようにも思います。
私の場合は、
シーン別に使う画像を分類して、シーンごとにロード&破棄しています。
ゲームの起動時については、なるべくパッと立ち上がってほしいので、必要最小限の画像(タイトルロゴとか全シーン共通のアイコンとか)しかロードさせないようにしています。
というわけで、
ご自身のスキルや、ゲームの仕様の範疇で、ユーザーフレンドリーなやり方であればいいと思います。
過去ログと合わせて、他の方の意見も参考にされるとよいですよ(^^)
>2.効率的なLoadGraphする方法
>forやitoaを使って何とか出来ないかと試行錯誤してみたのですが
文字列変換の部分が分からないのか、文字列の結合方法がわからないとか、
どこら辺が分からないのかを書かれるか、
あるいは試行錯誤の内容を具体的に書かれると、多くの人が回答しやすいと思います。
Re: 画像の読み込み(LoadGraph)について
Posted: 2014年9月10日(水) 17:18
by softya(ソフト屋)
2.はすでに書かれているので1.だけですが、プレイする側に支障がなかればどちらでも良いと思います。
[最初に読み込み]
メリット:リソース管理がシンプルになる。バグが少ない。
デメリット:起動が遅くなる。メモリ使用量が増える。
[随時に読み込み・解放]
メリット:起動が早くなる。メモリ使用量が最低限。
デメリット:リソース管理が複雑になる。バグが出やすい。
Re: 画像の読み込み(LoadGraph)について
Posted: 2014年9月10日(水) 22:54
by 黒猫
>>namariさん
なんと!ものすごく便利な関数があったのですね。
itoaやstrcat等でやたらめんどくさいことをしてました・・・。(しかも動作していない)
ありがとうございます。
>>Kettyさん、softyaさん
どちらでもプレイする側に問題がなければ設計上のミスとも言えないようですね。
使用する画像は少ないので起動時に一括ですべて読み込むようにしたいと思います。
ありがとうございました。
ちなみに下記のコードが私が考えていたコードです。
なんとも汚いコードですが、なぜダメなのか教えていただけたらと思います。
コード:
bool Load_Graphic(int max, char *filedr, int*gp_hd) {
char *filename;
char tmp[8];
char png[8] = ".png";
for (int i = 0; i < max; i++) {
itoa(i, tmp, 10);
strcat(filedr, tmp);
filename = strcat(filedr, png);
if ((gp_hd[i] = LoadGraph(filename)) == -1) {
return false;
}
}
return true;
}
Re: 画像の読み込み(LoadGraph)について
Posted: 2014年9月11日(木) 01:17
by Tatu
動作しなかったのは
引数の*filedrに文字列リテラルが書かれ、
(二重引用符"で囲まれた文字列のこと、特殊な領域に確保され、書き換え不可)
strcat(filedr,tmp);で文字列リテラルを書き換えようとしたためだと思います。
filename=strcat(filedr,png);
はfilenameにfiledrが代入されるだけです(どちらも文字列の位置を示すポインタ)
そのため、直後の関数のfilenameはfiledrと書いたのと同じ働きをします。
filedrの書き換えが可能だったとしても
ループの2回目でfiledrが指す文字列は"ディレクトリ/0.png1.png"となるでしょう。
回答のために書いたコード
► スポイラーを表示
コード:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
void Load_Graphic(int max, char *filedr) {
char *filename;
char tmp[8];
char png[8] = ".png";
for (int i = 0; i < max; i++) {
itoa(i, tmp, 10);
strcat(filedr, tmp);
filename = strcat(filedr, png);
printf("%s\n",filename);
}
}
*/
void Load_Graphic(int max, char *filedr) {
char filename[128];//領域を確保
char tmp[8];
char png[8] = ".png";
for (int i = 0; i < max; i++) {
//ディレクトリ名をコピー
strcpy(filename,filedr);
//画像ファイル名をくっつける
itoa(i, tmp, 10);
strcat(filename, tmp);
strcat(filename, png);
//結果の出力
printf("%s\n",filename);
}
}
int main(){
Load_Graphic(3,"data/img/");
return 0;
}
コンソールでの検証で画像の読み込みはできないので引数の*gp_hdは削除。
その代わり、filenameが示す文字列を表示するようにしています。
コメントアウトしたLoad_Graphicは元のコードに合わせて書いたもので
コメントアウトしていないLoad_Graphicはおそらくこんな感じにしようとしたのではないかと予想して書いたものです。
Re: 画像の読み込み(LoadGraph)について
Posted: 2014年9月11日(木) 09:18
by 黒猫
>>Tatuさん
言われて調べましたが、文字列リテラルというのは定数のようなものなのですね・・・。
全然知りませんでした。また一つ賢くなりました。
一旦受け取った内容をstrcpyでコピーして、その後ろにitoaとstrcatでファイル名を付ければうまくいくのですね。
スッキリしました。ありがとうございました。