トップページ > 過去ログ > 記事閲覧
MAPエディタの作成で
名前:K_T 日時: 2009/02/24 18:43

DxLibとC言語でゲームを作成しようと考えている初心者です。 現在STGを作成するにあたり、MAPエディタを作成しようと 考えていますが、何点か分からない事があるので、お願いします。 ・MAPのサイズは入力で指定されたサイズ(X = 50, Y = 100)を配列の動的確保で行う。 ・ファイルの形式は、TXTでもバイナリでもかまわない。 ・データの保存イメージは1行あたり  000100020003  000200010100  000101000200  の様な感じで、2文字で1セットにする。 上記のルールを踏まえて 1.(char *)malloc(・・・・)で確保した配列を   2文字1セットの形式で書き込みする方法。 2.保存したMAPデータを修正等で再度読み込む場合の   配列の大きさの確保の方法。 以上長文で申し訳ありませんが、回答お願いします。

Page: 1 |

Re: MAPエディタの作成で ( No.1 )
名前:K_T 日時:2009/02/24 18:46

追記です。 上記のルールでファイルの形式ですが、 これは現時点でTXT形式にするかバイナリ形式にするか 決まっていない為で、処理し易い方で回答をお願いできますでしょうか。
Re: MAPエディタの作成で ( No.2 )
名前: 日時:2009/02/25 13:01

とりあえず、 今作成しているソースが あるなら載せられませんか? > 000101000200 > の様な感じで、2文字で1セットにする ちょっと日本語の意味が分からないのですが、 00 01 01 00 02 00のようにして、 このセットが配列の要素1個に入るようにしたい?? 質問されているようなファイルを作る場合、 「行」を意識する必要があるなら、バイナリは 不向きでしょう。また、1行の最大数を固定に していますがはマップの大きさは入力値で 変わるのでは無いのですか? > 再度読み込む場合の配列の大きさの確保の方法。 いくつか方法があります。 ・読み込みと確保を逐次行うタイプ これは、はじめにある程度の領域を用意しておき、 足りなくなったらまた追加確保するという方法です ・メリットは拡張しやすい。 ・デメリットはメモリの断片化が起こりやすくなる ・保存する時にまず、全体のサイズを書き出し  そのサイズを確保してファイル内の情報を  すべて一括で読み出す。 ファイルの一番先頭にサイズを書いておきます。 読み込みを行う時は、そのサイズ分の領域を 動的に確保してから逐次読み込みを行う方法です。 メリットはメモリの複数回確保による断片化や 処理時間を軽減させることが可能。 デメリットは直接ファイルを編集するのが面倒 >処理し易い方で回答をお願いできますでしょうか。 上記のはあくまでも例であって、絶対そういた つくりにしないといけないわけではありません。 むしお、そういう部分は自分で決めないと、 人に作ってもらうと自分で改造したりできなく なってしまいます。 # 仕様くらいは自分で考えないと。。。
Re: MAPエディタの作成で ( No.3 )
名前:管理人 日時:2009/02/25 13:47

通さんがご返信をされていますが 私も大雑把なご返答をします とりあえずバイナリ形式で保存、読み込みする方法の一例をご説明します まず保存の仕方ですが、実行中は以下のような構造体にマップの情報が格納されているとします struct MAPDATA { int Width, Height ; // マップの横幅と縦幅 unsigned char *Data ; // 実際のマップのデータが格納されているメモリ領域へのポインタ } ; メンバ変数の Data が示すアドレスにはマップのデータが1チップ1バイトで格納されているとします 例:Width = 4, Height = 4 のマップデータの場合 Data が示すアドレスからの相対アドレス( 単位は byte ) ↓ 0 一番左上のチップの番号 1 一番左上から1つ右のチップの番号 2 一番左上から2つ右のチップの番号 3 一番左上から3つ右のチップの番号 4 一番左上から1つ下のチップの番号 5 一番左上から1つ下のチップの1つ右のチップの番号 6 一番左上から1つ下のチップの2つ右のチップの番号 7 一番左上から1つ下のチップの3つ右のチップの番号 8 一番左上から2つ下のチップの番号 9 一番左上から2つ下のチップの1つ右のチップの番号 10 一番左上から2つ下のチップの2つ右のチップの番号 11 一番左上から2つ下のチップの3つ右のチップの番号 12 一番左上から3つ下のチップの番号 13 一番左上から3つ下のチップの1つ右のチップの番号 14 一番左上から3つ下のチップの2つ右のチップの番号 15 一番左上から3つ下のチップの3つ右のチップの番号 このバッファにたとえば座標 x, y にチップ番号58を代入したいとしたら、以下のような式になります *( MAPDATA構造体.MapData + x + y * MAPDATA構造体.Width ) = 58 ; 保存する場合は fopen でバイナリ書き込みモードでファイルを開き、最初にマップの横幅と縦幅を出力します FILE *fp ; fp = fopen( "ファイル名", "wb" ) ; fwrite( &MAPDATA構造体.Width, sizeof( int ), 1, fp ) ; fwrite( &MAPDATA構造体.Height, sizeof( int ), 1, fp ) ; 次にマップデータを一度に書き込みます fwrite( MAPDATA構造体.MapData, MAPDATA構造体.Width * MAPDATA構造体.Height, 1, fp ) ; その後ファイルを閉じます fclose( fp ) ; 読み込む場合はファイルをバイナリ読み込みモードで開いた後 まずバッファのサイズを決定するためにマップの横幅と縦幅を読み込みます FILE *fp ; fp = fopen( "ファイル名", "rb" ) ; fread( &MAPDATA構造体.Width, sizeof( int ), 1, fp ) ; fread( &MAPDATA構造体.Height, sizeof( int ), 1, fp ) ; 横幅と縦幅がわかればバッファのサイズは決定するので、そのサイズのメモリを malloc で確保します MAPDATA構造体.MapData = ( char * )malloc( MAPDATA構造体.Width * MAPDATA構造体.Height ) ; 確保したメモリにマップデータを一度に読み込みます fread( MAPDATA構造体.MapData, MAPDATA構造体.Width * MAPDATA構造体.Height, 1, fp ) ; その後ファイルを閉じます fclose( fp ) ;
Re: MAPエディタの作成で ( No.4 )
名前:K_T 日時:2009/02/25 15:28

通様、管理人様回答ありがとうございます。 通様のご指摘にありましたが、言葉足らずですみませんでした。 >通様  00 01 02  このように配列の要素1つに対して、  2文字1セットの物を入れたいで間違いありません。  また、X = 50, Y = 100は、仮にその様に入力されたとして・・・と言うつもりでしたが、説明不足でした・・・。  ソースに関しては、紙に書いたり頭で考えてる内に  この問題で訳が分からなくなり、まだ実際の入力作業までは行っていないません。 >管理人様 構造体をfwrite関数で書き込むと、確かその内容がそっくり書き込まれて、 読み込みも同じ形式で読み込まれるんでしたね? Width, Heightは入力された各サイズの値を渡すのは何となく分かるのですが、 この場合のメンバ変数Dataが示すアドレスは、 予めmallocで確保した配列の先頭アドレスを渡せば良いのでしょうか?
横ですが ( No.5 )
名前:SooA 日時:2009/02/25 18:02

1の疑問はルールではなく何がやりたいのか書いた方が分かり易い思いますよ。 2バイト値(0〜65535)を扱いたいとか、 1バイト目、2バイト目をそれぞれ階層として扱いたいとか。 最後の疑問は構造体を一度にまるっと全て 読み込んでいません、 指定バイト分ずつ構造体の各変数に渡しています。 それが分かれば疑問は解けると思います。
Re: MAPエディタの作成で ( No.6 )
名前:K_T 日時:2009/02/25 18:44

SooA様回答ありがとうございます。 正直まだ初心者なので、バイトの理解が完全にできていませんが、 配列の1つの要素に01と入っているとして、 ・00〜49までを下層チップ ・50〜99までを上層チップ の様に使いたいのです。(今思えば、これなら無理に00とかにせずに、0〜49で良いですね・・・) 書き込みと読み込みに関しては、何となくですがわかってきました。 ありがとうございます。
Re: MAPエディタの作成で ( No.7 )
名前:SooA 日時:2009/02/26 05:11

取り合えず先に例を挙げた方が理解しやすいかと思ったので、 部分的にですが、こんな感じになる自分ならこうするといったものを 書いておきます。 一つ一つ追っていけば、データをどういう風に 読みに行ってるか分かると思います。 // 構造体の定義 struct MAPDATA { int Width; // 縦の幅 int Height; // 横の幅 int Fukasa; // マップが持つ階層 int Size; // 1つの層のサイズ(縦×横) unsigned char *Data; // マップデータ }; // 宣言例 MAPDATA tMap; // 初期設定例 tMap.Width = 64; // 縦の幅 tMap.Height = 64; // 横の幅 tMap.Fukasa = 3; // 最下、中間?、空中? tMap.Size = tMap.Width * tMap.Height; // メモリ確保の例 tMap.Data = (char*)malloc( tMap.Size * tMap.Fukasa ); // マップの描画例(実際には編集したい階層ごとの描画になると思います。) // X,Y は左上の座標、32*32の大きさのチップを11*11の範囲で描画 for( k=0; k<tMap.Fukasa, k++ ) { rd1 = tMap.Size * k; for( y=0; y<11, y++ ) { rd2 = rd1 + tMap.Width * ( Y+y ); for( x=0; x<11, x++ ) { T = tMap.Data[ rd2 + X+x ]; DrawGraph( x*32, y*32, GHandle[T], TRUE ); } } }
Re: MAPエディタの作成で ( No.8 )
名前:K_T 日時:2009/02/28 09:47

SooA様、回答頂いたのに返事遅れて、すみませんでした。 管理人様の読み書きのサンプルと、SooA様のサンプルで、だいぶ理解できました。 御二人のサンプルを合わせて考えると、 ・構造体(仮にSooA様の形式)を用意して、Fileに書き込む。 ・FileをOpen後、fread関数でx、y各サイズを最初に読み込む。 ・読み込んだサイズを元に、メンバ変数Dataに対して、  mallocで配列の動的確保を行う。(Fukasaを考慮していれば、Size * Fukasa) ・確保したData配列に対して、残りのMapDataを読み込む。 ・読み込んだDataを元に、後は画面に表示する。 上記の様な考え方でよろしいのでしょうか? P.S  自宅にネット環境が無い為、会社からこの書き込みをしております。  皆様の回答に対して、返事が遅くなりました事お詫びいたします。
Re: MAPエディタの作成で ( No.9 )
名前:管理人 日時:2009/02/28 13:43

良いと思います 一つだけ補足しますと、今回は1チップ辺りのデータサイズは unsigned char 型の変数一個分( 1バイト ) なので malloc で確保するメモリサイズは Width * Height ですが、1チップ辺りの データサイズが増えた場合は Width * Height * 1チップ辺りのデータサイズ となりますので もし情報量が増えた場合はご注意下さい
Re: MAPエディタの作成で ( No.10 )
名前:K_T 日時:2009/02/28 13:56

管理人様、回答及び補足ありがとうございます。 >データサイズが増えた場合は Width * Height * 1チップ辺りのデータサイズ となりますので 上記の部分なのですが、これは仮にチップのデータサイズがint型(2バイト?)の場合 tMap.Data = (int*)malloc(tMap.Width * tMap.Height * sizeof(int))になる これで良いのでしょうか? 理解力が乏しく、何度も申し訳ありませんが・・・
Re: MAPエディタの作成で ( No.11 )
名前:管理人 日時:2009/02/28 14:32

その通りです ちなみに Win32 環境では、各変数型のサイズは以下のようになっています char 1バイト short 2バイト int 4バイト float 4バイト double 8バイト
Re: MAPエディタの作成で ( No.12 )
名前:K_T 日時:2009/02/28 14:45

管理人様、回答ありがとうございます。 了解しました。 これでだいぶ先が見えてきました。(個々の処理はまだできてませんけど・・・) 自分でなるべく解決できるように、これからも勉強していきますが、 また手に負えない事がありましたら、よろしくお願いします。 いつかこちらのサイトの、「ユーザー作成のソフト」に載せて頂けるようにがんばります^^

Page: 1 |