いつもお世話になります。
マップ表示についてソフト屋さん公開のRPG講座から学ばせてもらおうと試行錯誤したのですが、
初心者の私には、ソフト屋さんのサンプルプログラムでは既に構造体や関数にまとめられていて詳しく読み解くことができませんでしたので、質問させてください。
マップ表示について、機能単位毎に自力でプログラムを組立てていきたく、下記の3段階でまずはプログラムを理解したく思っています。
①マップ情報の読み込み (Platinumのfmfファイルの読み込み)
②マップ情報を変数へ引渡し
③変数を使ってマップを描画
しかし、次の2点が良く分かりません
【疑問1】
fmfファイル自体がよくわかりません
マップチップの配列情報が格納されていると思っているのですが、Platinumの説明書によると
{FMFファイルヘッダ (20 byte)}
+0 identifier [U4] // ファイル識別子 'FMF_' (0x5F464D46)
+4 size [U4] // ヘッダを除いたデータサイズ
+8 mapWidth [U4] // マップの横幅
+12 mapHeight [U4] // マップの縦幅
+16 chipHeight [U1] // パーツの横幅
+17 chipHeight [U1] // パーツの縦幅
+18 layerCount [U1] // レイヤー数
+19 bitCount [U1] // レイヤーデータのビットカウント(8/16)
とのことで、このデータからどうやってマップチップを描画するのか想像がつきません
【疑問2】
上記の3段階のプロセスだけで、とりあえずはマップ描画できるでしょうか?
(サンプルプログラムでは、初期化やメモリの確保等、たくさんのマップ管理処理があるので
まずは単純化したいのですが、初期化やメモリ確保等を除いても描画はできるでしょうか)
そこで、まずは疑問部分について教えて頂きたく、欲を言えば上記のように3段階でマップ描画する場合のプログラムの道しるべ的なものも教えて頂きたいと思っています。
よろしくお願いします。
ソフト屋さん公開のRPG講座マップ表示について
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: ソフト屋さん公開のRPG講座マップ表示について
すいません。お待たせしました疑問にお答えします。
【疑問1】
fmfは
[ヘッダ] 格納されているマップデータの情報
[マップデータのレイヤー0] ヘッダ情報の マップの横幅 * マップの縦幅 * レイヤーデータのビットカウント(8/16) / 8バイトのサイズ
[マップデータのレイヤー1] 同上
: ヘッダ情報のレイヤー数分続きます。
と言う形で格納されています。
これはバイナリエディタで直接データを見てもらったほうが分りやすいと思います。
「Stirlingの詳細情報 : Vector ソフトを探す!」
http://www.vector.co.jp/soft/win95/util/se079072.html
EASY-RPGの場合は、レイヤー0に地形データの画像番号、レイヤー1に当たり判定、レイヤー2にイベントを設定してあります。
このうちマップの描画はレイヤー0の情報を使って行います。
【疑問2】
まずマップ描画の仕組みを理解しているかで段階は変わると思います。
基本的なところから理解したいのであれば、配列にマップデータをセットする形での描画から始めれたほうが良いでしょう。
まず、地形データを用意して読みこんである事とします。
地形描画処理の実験専用プログラムをまず作りましょう。分かるところは飛ばしてください。
(1)fmfのフォーマットを真似て1次元配列で地形データを作って、地形画像を描画させてみます。配列で指定された番号の画像が表示されていることを確認して下さい。
縦サイズと横サイズは変数で定義してください。
(2)バイナリファイルの読み込みを理解します。fmfヘッダを読み込んで表示するプログラムを作成してください。読み込み先は構造体です。
(3)fmfの情報を元に各レイヤーを読み込むプログラムを作成してください。読み込まれたことはデバッガなどで確認します。
各レイヤーのメモリはmallocします。各レイヤー指すポインタ配列も出来ればmallocしてください。
(4) (1)の経験を活かして(3)のマップを描画します。
(5) さていよいよ仕上げです。キー入力でのマップスクロール(ドット単位)を実装してみましょう。
ただし、マップ外に出ないようにガードしてください。
とりあえず、分からな場合は気軽に聞いてくださいね。
【疑問1】
fmfは
[ヘッダ] 格納されているマップデータの情報
[マップデータのレイヤー0] ヘッダ情報の マップの横幅 * マップの縦幅 * レイヤーデータのビットカウント(8/16) / 8バイトのサイズ
[マップデータのレイヤー1] 同上
: ヘッダ情報のレイヤー数分続きます。
と言う形で格納されています。
これはバイナリエディタで直接データを見てもらったほうが分りやすいと思います。
「Stirlingの詳細情報 : Vector ソフトを探す!」
http://www.vector.co.jp/soft/win95/util/se079072.html
EASY-RPGの場合は、レイヤー0に地形データの画像番号、レイヤー1に当たり判定、レイヤー2にイベントを設定してあります。
このうちマップの描画はレイヤー0の情報を使って行います。
【疑問2】
まずマップ描画の仕組みを理解しているかで段階は変わると思います。
基本的なところから理解したいのであれば、配列にマップデータをセットする形での描画から始めれたほうが良いでしょう。
まず、地形データを用意して読みこんである事とします。
地形描画処理の実験専用プログラムをまず作りましょう。分かるところは飛ばしてください。
(1)fmfのフォーマットを真似て1次元配列で地形データを作って、地形画像を描画させてみます。配列で指定された番号の画像が表示されていることを確認して下さい。
縦サイズと横サイズは変数で定義してください。
(2)バイナリファイルの読み込みを理解します。fmfヘッダを読み込んで表示するプログラムを作成してください。読み込み先は構造体です。
(3)fmfの情報を元に各レイヤーを読み込むプログラムを作成してください。読み込まれたことはデバッガなどで確認します。
各レイヤーのメモリはmallocします。各レイヤー指すポインタ配列も出来ればmallocしてください。
(4) (1)の経験を活かして(3)のマップを描画します。
(5) さていよいよ仕上げです。キー入力でのマップスクロール(ドット単位)を実装してみましょう。
ただし、マップ外に出ないようにガードしてください。
とりあえず、分からな場合は気軽に聞いてくださいね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: ソフト屋さん公開のRPG講座マップ表示について
お時間頂いている上に急かすなんてとんでもありませんので、どうかご自身のペースでお付き合いお願いします
>(1)fmfのフォーマットを真似て1次元配列で地形データを作って、地形画像を描画させてみます。配列で指定された番号の画像が表示されていることを確認して下さい。
縦サイズと横サイズは変数で定義してください。
まずは上記に挑戦してみましたが、やはりfmfのフォーマットがよく理解できず、真似られたかどうかよく分かりません
自分なりの理解で次のようにプログラム作りましたが、上記の意図に合ってますでしょうか?
>(1)fmfのフォーマットを真似て1次元配列で地形データを作って、地形画像を描画させてみます。配列で指定された番号の画像が表示されていることを確認して下さい。
縦サイズと横サイズは変数で定義してください。
まずは上記に挑戦してみましたが、やはりfmfのフォーマットがよく理解できず、真似られたかどうかよく分かりません
自分なりの理解で次のようにプログラム作りましたが、上記の意図に合ってますでしょうか?
#include "DxLib.h"
char Key[256];
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理
SetDrawScreen( DX_SCREEN_BACK ); //裏画面に設定
int map[64],x,y,xi,yi;
LoadDivGraph( "data/map/town.png" , 64 , 8 , 8 , 32 , 32 , map ); //マップ画像を分割してmap配列に保存
int MapData[29] ={ //手打ちマップデータ
x = 5 , //マップ縦大きさ
y = 5 , //マップ横大きさ
xi = 32, //マップチップの縦大きさ
yi = 32, //マップチップの横大きさ
map[49] , map[48] , map[48] , map[48] , map[48] ,
map[48] , map[49] , map[48] , map[48] , map[48] ,
map[48] , map[48] , map[49] , map[48] , map[48] ,
map[48] , map[48] , map[48] , map[49] , map[48] ,
map[48] , map[48] , map[48] , map[48] , map[49] ,//マップチップの並び
};
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
//↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されていない
//ココに処理を書いていく
int n = 4; // 描画行う為の操作変数
for(int j=0 ; j<MapData[1] ; j++){
for(int i=0 ; i<MapData[0] ; i++){
DrawGraph( 0+MapData[2]*i, 0+MapData[3]*j , MapData[n], TRUE ) ;//画面左上から順にマップ描画
n++;
};
};
ScreenFlip();//裏画面を表画面に反映
}
DxLib_End();
return 0;
}
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: ソフト屋さん公開のRPG講座マップ表示について
fmfと食い違うであろう部分を修正しました。
それと問題点もコメントとして書き添えました(※マーク)。
コメントで詳しく書いていませんがLoadDivGraph()を使っている所で実際のゲームにしたときにマップ画像パーツが可変サイズである場合に問題が出ますので面倒になりますが使わないほうが良いかも知れません。例えばEASY-RPGではLoadGraph()で一枚画像として読み込んでDrawRectGraph()でパーツごとに描画してます。
ちなみにEASY-RPGのマップ画像パーツは最終版だと
bg.png 512 x 448
field.png 224 x 320
town.png 384 x 288
と可変サイズになっています。
それとプログラムを見て思ったのですが、構造体とか苦手ですか?
それなら、(1)と(2)の間に今のプログラムを構造体にまとめた物を書いてみましょう。出来るだけfmfフォーマットに近い書き方をしてください。
それと問題点もコメントとして書き添えました(※マーク)。
#include "DxLib.h"
char Key[256];
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理
SetDrawScreen( DX_SCREEN_BACK ); //裏画面に設定
int map[256],x,y,xi,yi; //←※最大個数を想定。
// ※配列に混ぜるのは止めましょう。出来れば構造体を定義してください。
x = 5 , //マップ縦大きさ
y = 5 , //マップ横大きさ
xi = 32, //マップチップの縦大きさ
yi = 32, //マップチップの横大きさ
// ※ちなみにtonw.pngは横12で縦9個のパーツが並んでいます。ここは画像ファイル毎に違うので本当は決め打ちできません。
LoadDivGraph( "data/map/town.png" , 12*9 , 12 , 9 , 32 , 32 , map ); //マップ画像を分割してmap配列に保存
// ※本物のfmfに近いものに書き換えました。
BYTE MapData[5*5] ={ //手打ちマップデータ ←※ 1バイトの配列がfmfの基本形式です。
1 , 48 , 48 , 48 , 48 ,
48 , 49 , 48 , 48 , 48 ,
48 , 48 , 49 , 48 , 48 ,
48 , 48 , 48 , 49 , 48 ,
48 , 48 , 48 , 48 , 1 ,//※マップチップの並び(画像パーツの番号が並んでいると考えてください)
};
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
//↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されていない
//ココに処理を書いていく
for(int j=0 ; j<y ; j++){
for(int i=0 ; i<x ; i++){
int n = y*j+i; // ※マップ配列の添字番号。後々の都合を考えて毎回計算に。
// ※ここでマップ配列からマップパーツ番号を拾い出してそれを更にmap[]でイメージ番号に変えて表示しています。
DrawGraph( 0+xi*i, 0+yi*j , map[MapData[n]], TRUE ) ;//画面左上から順にマップ描画
};
};
ScreenFlip();//裏画面を表画面に反映
}
DxLib_End();
return 0;
}
ちなみにEASY-RPGのマップ画像パーツは最終版だと
bg.png 512 x 448
field.png 224 x 320
town.png 384 x 288
と可変サイズになっています。
それとプログラムを見て思ったのですが、構造体とか苦手ですか?
それなら、(1)と(2)の間に今のプログラムを構造体にまとめた物を書いてみましょう。出来るだけfmfフォーマットに近い書き方をしてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: ソフト屋さん公開のRPG講座マップ表示について
・構造体でまとめる
・DrawRectGraph()で描画する
上2つを念頭において下記のようにプログラム直してみました。
仮想FMFファイル情報に、もっとマップ情報を集約しないといけないと感じているのですが、まだバイナリファイルの読み込みについて学習できていないので、もう少し学習してきます。
あと、town.pngを最終の384 x 288のものに差し替えました(今までeasyRPG003で配布されていたものを使っていました)
・DrawRectGraph()で描画する
上2つを念頭において下記のようにプログラム直してみました。
仮想FMFファイル情報に、もっとマップ情報を集約しないといけないと感じているのですが、まだバイナリファイルの読み込みについて学習できていないので、もう少し学習してきます。
あと、town.pngを最終の384 x 288のものに差し替えました(今までeasyRPG003で配布されていたものを使っていました)
#include "DxLib.h"
char Key[256];
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理
SetDrawScreen( DX_SCREEN_BACK ); //裏画面に設定
struct MapData{ //マップ情報の構造体
int x ; //マップ横大きさ
int y ; //マップ縦大きさ
int xi ; //マップチップの横大きさ
int yi ; //マップチップの縦大きさ
};
BYTE kasou_FMF[5*5] = { //仮想FMFファイル情報
72,60,60,60,60,
60,72,60,60,60,
60,60,72,60,60,
60,60,60,72,60,
60,60,60,60,72 //マップチップの並び
};
int mapchip = LoadGraph("data/map/town.png"); //マップチップのロード
int mapchip_x = 12; //マップチップの横の個数
int mapchip_y = 9; //マップチップの縦の個数
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
//↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されていない
//ココに処理を書いていく
struct MapData MD; //構造体を『MD』と定義
MD.x = 5;//↓ここから
MD.y = 5;
MD.xi = 32;
MD.yi = 32;//↑ここまで、本来はFMFファイルから読み取る??
for(int j=0 ; j<MD.x ; j++){
for(int i=0 ; i<MD.y ; i++){
int n = MD.y*j+i ; //マップ配列の添字番号
DrawRectGraph(//画面左上から順にマップ描画
0+MD.xi*i , 0+MD.yi*j , //描画する座標
0+MD.xi*(kasou_FMF[n]%mapchip_x) , 0+MD.yi*(kasou_FMF[n]/mapchip_x) , //描画元の座標
MD.xi , MD.yi , //描画元から切り取るサイズ
mapchip , TRUE , TRUE) ;
};
};
ScreenFlip();//裏画面を表画面に反映
}
DxLib_End();
return 0;
}
Re: ソフト屋さん公開のRPG講座マップ表示について
おひさしぶりです。ご教授頂けたおかげで、初期の疑問解決へ向けかなり前進してきました。
>(2)バイナリファイルの読み込みを理解します。fmfヘッダを読み込んで表示するプログラムを作成してください。読み込み先は構造体です。
>(3)fmfの情報を元に各レイヤーを読み込むプログラムを作成してください。読み込まれたことはデバッガなどで確認します。
各レイヤーのメモリはmallocします。各レイヤー指すポインタ配列も出来ればmallocしてください。
現在上記に取り組み中です。まずはFMFヘッダの読み込みはできました。
しかし、各レイヤーを読み込む部分で分からないことがあるので質問させてください。
(作成中のプログラムを下記に掲載します)
【質問1】
「各レイヤーを読み込む」プログラムが下記のプログラムで合ってるでしょうか?
【質問2】
上記の疑問1の回答が「合っている」場合、次の2つが分かりません
①MapData[ly]=allmapdata + (layerSize*ly)の意味する所がよく分かりません
②最終的に、マップを描画する為にマップチップの配列情報を手に入れなければいけないと思うのですが
この配列情報はどれになるのでしょうか
またFMFファイル読み込みの部分で、プログラムはできましたが、理屈が分からない部分があります。
【質問3】
fread関数について、ファイルから読み込むデータサイズを指定して情報を読み込みますが、例えばFMFファイルではヘッダとマップ情報のデータが混ざって読み込まれたりはしないのですか?
(例;「先頭から、ヘッダ20byte ,マップ情報80byte」 のファイルから80byte指定して読み込んだら、先頭から順にヘッダ20byte,マップ情報60byteの形で読み込まれない理由が分かりません)
【質問4】
fread関数について、本来配列にしか値を引き渡せないものと思っていたのですが、ポインタ演算子をつければ何故構造体にも結果的に値を引き渡せるようになるのでしょうか?
(この質問については、ポインタをまだ深く自習しておらず自力解決の余地もある気がするので、回答が手間でなければご回答お願いします)
お手数ですが宜しくお願いいたします。
>(2)バイナリファイルの読み込みを理解します。fmfヘッダを読み込んで表示するプログラムを作成してください。読み込み先は構造体です。
>(3)fmfの情報を元に各レイヤーを読み込むプログラムを作成してください。読み込まれたことはデバッガなどで確認します。
各レイヤーのメモリはmallocします。各レイヤー指すポインタ配列も出来ればmallocしてください。
現在上記に取り組み中です。まずはFMFヘッダの読み込みはできました。
しかし、各レイヤーを読み込む部分で分からないことがあるので質問させてください。
(作成中のプログラムを下記に掲載します)
【質問1】
「各レイヤーを読み込む」プログラムが下記のプログラムで合ってるでしょうか?
【質問2】
上記の疑問1の回答が「合っている」場合、次の2つが分かりません
①MapData[ly]=allmapdata + (layerSize*ly)の意味する所がよく分かりません
②最終的に、マップを描画する為にマップチップの配列情報を手に入れなければいけないと思うのですが
この配列情報はどれになるのでしょうか
またFMFファイル読み込みの部分で、プログラムはできましたが、理屈が分からない部分があります。
【質問3】
fread関数について、ファイルから読み込むデータサイズを指定して情報を読み込みますが、例えばFMFファイルではヘッダとマップ情報のデータが混ざって読み込まれたりはしないのですか?
(例;「先頭から、ヘッダ20byte ,マップ情報80byte」 のファイルから80byte指定して読み込んだら、先頭から順にヘッダ20byte,マップ情報60byteの形で読み込まれない理由が分かりません)
【質問4】
fread関数について、本来配列にしか値を引き渡せないものと思っていたのですが、ポインタ演算子をつければ何故構造体にも結果的に値を引き渡せるようになるのでしょうか?
(この質問については、ポインタをまだ深く自習しておらず自力解決の余地もある気がするので、回答が手間でなければご回答お願いします)
お手数ですが宜しくお願いいたします。
#include "DxLib.h"
#include <stdio.h>
char Key[256];
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理
SetDrawScreen( DX_SCREEN_BACK ); //裏画面に設定
struct FMF_HEADER{
DWORD dwIdentifier; // ファイル識別子 'FMF_'
DWORD dwSize; // ヘッダを除いたデータサイズ
DWORD dwWidth; // マップの横幅
DWORD dwHeight; // マップの高さ
BYTE byChipWidth; // マップチップ1つの幅(pixel)
BYTE byChipHeight; // マップチップ1つの高さ(pixel)
BYTE byLayerCount; // レイヤーの数
BYTE byBitCount; // レイヤデータのビットカウント
} ;
FMF_HEADER test; //FMFヘッダ構造体宣言
char *mapname = "data/map/town.fmf";
int White = GetColor( 255 , 255 , 255 );
//ココに処理を書いていく
FILE *fp; //ファイル処理
fp = fopen(mapname,"rb"); //FMFファイルを開く
fread( &test, sizeof test, 1, fp ); //FMFヘッダ読み込み
DrawFormatString( 0, 0, White , "%d %d %d %d %d %d %d %d" ,
test.dwIdentifier,
test.dwSize ,
test.dwWidth ,
test.dwHeight ,
test.byChipWidth ,
test.byChipHeight ,
test.byLayerCount ,
test.byBitCount);//FMFヘッダの読み込み確認
BYTE *allmapdata = (BYTE*)malloc( test.dwSize ); //全てのレイヤ合わせたマップデータ量のメモリ確保
fread( allmapdata, test.dwSize, 1, fp ); //全てのレイヤ分合わせたマップデータの読み込み
BYTE *MapData[3] ; //各レイヤー毎のマップデータ??(宣言)
int layerSize = test.dwSize / test.byLayerCount; //レイヤー1枚当りのデータ量計算
for( int ly=0 ; ly<3 ; ly++ ) {
if( ly < test.byLayerCount )
MapData[ly] = allmapdata + (layerSize*ly); //各レイヤーのマップ情報インプット??
else
MapData[ly] = NULL;//このレイヤーは存在しない。
}
fclose(fp); //ファイルを閉じる
ScreenFlip();//裏画面を表画面に反映
WaitKey() ;
DxLib_End();
return 0;
}
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: ソフト屋さん公開のRPG講座マップ表示について
マップが3レイヤー以内でbyBitCountが8限定なら、これで問題ないです。【質問1】
「各レイヤーを読み込む」プログラムが下記のプログラムで合ってるでしょうか?
byBitCountはplatinumでマップ新規作成の時にマップデータサイズに16ビットを選ぶと変わります。
【質問2】
上記の疑問1の回答が「合っている」場合、次の2つが分かりません
①MapData[ly]=allmapdata + (layerSize*ly)の意味する所がよく分かりません
MapData[ly]=allmapdata + (layerSize*ly)
各レイヤーの先頭ポインタを求める計算ですね。
MapDataはポインタ配列で、各レイヤーの先頭アドレスを格納します。
allmapdataがレイヤー全体の先頭ポインタでlayerSizeがレイヤー毎のサイズです。
こんな感じです。
[レーヤー0] ← MapData[0] と allmapdata は同じアドレスです。
↑
layerSize
↓
[レーヤー1] ← MapData[1]
↑
layerSize
↓
[レーヤー2] ← MapData[2]
↑
layerSize
↓
MapData[]がそれぞれのレイヤーのマップチップの配列情報を指しています。②最終的に、マップを描画する為にマップチップの配列情報を手に入れなければいけないと思うのですが
この配列情報はどれになるのでしょうか
例えば、レイヤー0の横3番目縦5番目のマップチップ情報は、
MapData[0][(5*test.dwHeight)+3]
で読み出すことが出来ます。
ただし、この例はtest.byBitCountが8の場合限定です。
[補足]3,5番目と書いてますが0から始まる番号です。なので、
*の位置のマップチップ情報です。0123
0
1
2
3
4
5 *
freadは指定サイズを読み込みますが、前に読み込んだ続きから読み込みます。【質問3】
fread関数について、ファイルから読み込むデータサイズを指定して情報を読み込みますが、例えばFMFファイルではヘッダとマップ情報のデータが混ざって読み込まれたりはしないのですか?
(例;「先頭から、ヘッダ20byte ,マップ情報80byte」 のファイルから80byte指定して読み込んだら、先頭から順にヘッダ20byte,マップ情報60byteの形で読み込まれない理由が分かりません)
このプログラムだとfreadで2回に分けてヘッダとレイヤーを読み込んでいます。
例で言えば、ヘッダ20バイトとマップ情報80バイトをそれぞれ読み込んでいると言う事です。
freadの第一パラメータは何のポインタでも受け付けます。【質問4】
fread関数について、本来配列にしか値を引き渡せないものと思っていたのですが、ポインタ演算子をつければ何故構造体にも結果的に値を引き渡せるようになるのでしょうか?
(この質問については、ポインタをまだ深く自習しておらず自力解決の余地もある気がするので、回答が手間でなければご回答お願いします)
ヘッダの定義上は第一パラメータはvoid*となっています。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: ソフト屋さん公開のRPG講座マップ表示について
長期間、音沙汰なく失礼致しました。
絵を描くことのモチベーションが上がり、絵のほうに浮気していました
本題ですが、適切なご指導のおかげで当初の疑問を解決することができました!!
(FMFファイルからマップを描写することができました)
マップチップファイルの縦横の個数が、元の画像状態ではなくPlatinumで読込んだ状態での個数
にしなければいけないことに気付くまで苦戦しました。
今回は、主にFMFファイルという中身が理解できない外部ファイルの読み取りで苦戦していたので
ここまでくればマップスクロールは数式を作るだけだと思うので自力でやってみます。
ご丁寧なご指導有難うございました。
絵を描くことのモチベーションが上がり、絵のほうに浮気していました
本題ですが、適切なご指導のおかげで当初の疑問を解決することができました!!
(FMFファイルからマップを描写することができました)
マップチップファイルの縦横の個数が、元の画像状態ではなくPlatinumで読込んだ状態での個数
にしなければいけないことに気付くまで苦戦しました。
今回は、主にFMFファイルという中身が理解できない外部ファイルの読み取りで苦戦していたので
ここまでくればマップスクロールは数式を作るだけだと思うので自力でやってみます。
ご丁寧なご指導有難うございました。
#include "DxLib.h"
#include <stdio.h>
char Key[256];
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理
SetDrawScreen( DX_SCREEN_BACK ); //裏画面に設定
struct FMF_HEADER{
DWORD dwIdentifier; // ファイル識別子 'FMF_'
DWORD dwSize; // ヘッダを除いたデータサイズ
DWORD dwWidth; // マップの横幅
DWORD dwHeight; // マップの高さ
BYTE byChipWidth; // マップチップ1つの幅(pixel)
BYTE byChipHeight; // マップチップ1つの高さ(pixel)
BYTE byLayerCount; // レイヤーの数
BYTE byBitCount; // レイヤデータのビットカウント
} ;
FMF_HEADER test; //FMFヘッダ構造体宣言 →test構造体
char *mapname = "data/map/town.fmf";
int White = GetColor( 255 , 255 , 255 );
FILE *fp; //ファイル処理
fp = fopen(mapname,"rb"); //FMFファイルを開く
fread( &test, sizeof test, 1, fp ); //FMFヘッダ読み込み
DrawFormatString( 0, 0, White , "%d %d %d %d %d %d %d %d" ,
test.dwIdentifier,
test.dwSize ,
test.dwWidth ,
test.dwHeight ,
test.byChipWidth ,
test.byChipHeight ,
test.byLayerCount ,
test.byBitCount);//FMFヘッダの読み込み確認
BYTE *allmapdata = (BYTE*)malloc( test.dwSize ); //全てのレイヤ合わせたマップデータ量のメモリ確保
fread( allmapdata, test.dwSize, 1, fp ); //全てのレイヤ分合わせたマップデータの読み込み
BYTE *MapData[3] ; //各レイヤー毎のマップデータ(ポインタ宣言)
int layerSize = test.dwSize / test.byLayerCount; //レイヤー1枚当りのデータ量計算
for( int ly=0 ; ly<3 ; ly++ ) {
if( ly < test.byLayerCount )
MapData[ly] = allmapdata + (layerSize*ly); //各レイヤーの先頭アドレス抽出
else
MapData[ly] = NULL;//このレイヤーは存在しない。
}
int mapchip = LoadGraph("data/map/town.jpg"); //マップチップのロード
int mapchip_x = 16; //マップチップの横の個数
int mapchip_y = 16; //マップチップの縦の個数
for(int j=0 ; j<test.dwHeight ; j++){
for(int i=0 ; i<test.dwWidth ; i++)
DrawRectGraph(//画面左上から順にマップ描画
0+test.byChipWidth*i , 0+test.byChipHeight*j , //描画する座標
0+test.byChipWidth*(MapData[0][j*test.dwHeight+i]%mapchip_x) , 0+test.byChipHeight*(MapData[0][j*test.dwHeight+i]/mapchip_x) , //描画元の座標
test.byChipWidth ,test.byChipHeight , //描画元から切り取るサイズ
mapchip , FALSE , FALSE) ;
};
fclose(fp); //ファイルを閉じる
ScreenFlip();//裏画面を表画面に反映
WaitKey() ;
DxLib_End();
return 0;
}