#17
by プログラマ見習い » 4年前
質問者である自分が何をしたいについて改めて説明しなおします。
まずはmap0.txtの中身と、ソースコードを投稿します。
今回はちゃんとコピペしたので、画面が正常に表示されるはずです。
map0.txt
コード:
0000000000111111111100000000001111111111
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000AAA000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000AAA000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000111111111100000000001111111111
map0.txtを読み込んだもの
コード:
#include <DxLib.h>
#define MAPSIZE 32 //マップサイズを決めます。
#define HEIGHT 15 //Y座標の最大値を決めます
#define WIDTH 40 //X座標の最大値を決めます
//キャラクターの数の最大値を決めます。念のために多めにします。今回はマップデータの数に合わせます。
#define CHARA HEIGHT*WIDTH
//画像データの構造体を作ります。
//画像データは無理に配列やポインタで整理しようとすると、エラーやフリーズの原因になります。
struct ImageData{
int kabe01; //
int teki0A[2]; //
};
struct ImageData im; //
//各キャラクターのデータの構造体を作ります。
struct CharaData{
//int *ghandle; //アニメーションさせるために画像データハンドル。
//ポインタ設定をしたが、これが原因の一つでした。
char kind; //キャラクターの種類を格納。
int anime_pattern; //アニメパーン数
float x; //座標はfloatにします。
float y;
int body; //体力
};
struct CharaData charadata[CHARA]; //今回はcharadataと名づけます。
//キャラクターは複数出現させるので、配列内に各キャラクターの最大値CHMAXを格納します。
//struct CharaData im[2]; //画像を描画するための変数。
//or//struct CharaData im[CHARA]; //画像を描画するための変数。
//アニメーションカウンター用の変数を作ります。
unsigned int g_anime_counter=0;
//マップデータを作ります。
char mapdata[HEIGHT][WIDTH];
//メモ帳からマップデータを読み込み
void MapLoad(){
//各キャラクターのデータを初期化します。
ZeroMemory(charadata,sizeof(charadata));
char buf[1024];
sprintf_s(buf,1024,"media/map%d.txt",1); //ファイル名を用意する
int fp; //ファイルハンドル
fp=FileRead_open(buf); //ファイルを開く
//ファイル読み込みエラー処理
if(fp==NULL){
printfDx("ファイル読み込みエラー");
return;
}
/////////////////////////////ここから////////////////////////////
for(int y=0;y<HEIGHT;y++){
for(int x=0;x<WIDTH;x++){
FileRead_scanf(fp,"%s",mapdata[y][x]);
} //for(int x=0;x<WIDTH;x++)の最後
} //for(int y=0;y<HEIGHT;y++)の最後
/////////////////////////////ここまで////////////////////////////
FileRead_close(fp); //ファイルを閉じる
} //void MapLoad();の最後
//画像をロードする関数を作ります。
void Load(){
im.kabe01=LoadGraph("media/kabe01.jpg");
LoadDivGraph("media/teki0A.jpg",2,2,1,32,32,im.teki0A);
}
//初期化用の関数を作ります。
void Init(){
//キャラクターをカウントする変数を作ります。必要な変数の一つです。
//キャラクターをカウントする変数はローカル変数でも問題ありませんでした。
int counter=0;
for(int y=0;y<HEIGHT;y++){
for(int x=0;x<WIDTH;x++){
char c=mapdata[y][x];
//初期化してマップデータから、キャラクターのデータを取り出します。
//kindにマップデータを代入します。
//これも必要な変数の一つです。
charadata[counter].kind=c;
charadata[counter].x=(float)x*MAPSIZE;
charadata[counter].y=(float)y*MAPSIZE;
int charaValid=0;
//この変数を利用しないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
//Validは英語で「有効、根拠の確実な、確かな、正当な」などの意味です。
//キャラクターごとに異なるものはswicth文を使います。
switch(c){ //なお、ここにcounterを入れてしまうと、フリーズしてしまいました。
case '1':
charadata[counter].body=1;
charaValid=1; //case毎にcv=1;と代入します。
break;
case 'A':
charadata[counter].anime_pattern=2; //アニメーションさせる場合はここで代入します。
charadata[counter].body=1;
charaValid=1; //
break;
}
//このif文がないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
if(charaValid){
mapdata[y][x]='0'; //マップデータを'0'にする事で、データの取り出しは終わりです。
//ここでキャラクターの数を一つずつ増やしていきます。
counter++;
}
}
}
}
//描画と移動処理用の関数を作ります
void Move(){
for(int i=0;i<CHARA;i++){
char c=charadata[i].kind;
switch(c){
//ここにcharadata[i].kindではなくiを入れると、一つしか描画されませんでした。
//また、フリーズしてまった場合もあります。
case '1':
DrawGraph(charadata[i].x,charadata[i].y,im.kabe01,TRUE);
break;
case 'A':
int a=g_anime_counter/20%charadata[i].anime_pattern;
DrawGraph(charadata[i].x,charadata[i].y,im.teki0A[a],TRUE);
break;
}
//キャラクター単位で動かす方法でマップスクロールを行います。
charadata[i].x=charadata[i].x-1;
}
}
//WinMain関数の中に、先ほど作った関数を入れます。//Move();だけwhile内に入れます。
int WINAPI WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lpC,int nC){
if(ChangeWindowMode(TRUE)!=0) return -1; //ウィンドウモードの変更
if(DxLib_Init()!=0) return -1; //DXライブラリ初期化処理
if(SetDrawScreen(DX_SCREEN_BACK)!=0) return -1; //描画先を裏画面に設定
//ロードの関数は、ここではここに入れます。
MapLoad(); //マップデータのロード
Load(); //画像のロード
Init(); //初期化。//if(charaValid)に関するコードを書いていない時は、ここに置かないで、while文の中に置くと、適切に描画されません。
while(ProcessMessage()==0&&CheckHitKey(KEY_INPUT_ESCAPE)==0){
//メッセージ処理(XキーかAlt+F4キーが押されたら終了)
//ESCキーが押されたら終了
if(ClearDrawScreen()!=0) return -1; //裏画面を消す
//Init(); //初期化。//if(charaValid)に関するコードを書いていないでwhile文の中に初期化関数Init();置くと、適切に描画されません。
//この関数をそのままwhile文の中に入れてしまうと、一番最初の画像が消えてしまう。
Move(); //画像の描画と移動用の関数をここに置きます。
g_anime_counter++; //
if(ScreenFlip()!=0) return -1; //裏画面を表画面に反映
}
if(DxLib_End()!=0) return -1; //DXライブラリの終了処理
return 0; //ソフトの終了
}
次にvoid MapLoad(){}の中身をご覧ください。
以上のソースコードは、map0.txtからデータを読み込んで、マップデータに変換しているのですが、map0.txtは、ご覧の通り、カンマや空白などで区切られておらず、1ケタずつ読み込まれます。
以上の方法には、二つ問題があります。
第一に、以上のような1ケタずつ読み込んでいく方法だと、整数10個、アルファベット大文字26文字、小文字26文字で、合計62種類までのデータを読み込む事が出来ます。
しかし、もしも62種類よりも多くのデータを読み込みたい場合、2ケタの整数や文字を用意する必要があります。例えば100種類、200種類のデータを読み込みたい場合、00、01、AAなどのような整数や文字が必要であります、
第二に、カンマや空白などで区切られていないと、何行目の何列目かが分かり辛い、目で見ると目が痛くなってしまうと言う問題があります。そこで、カンマや空白などでデータを区切る事で、見えやすくする必要があります。
以上の理由から、私はカンマ区切りの文字を読み込む事と、2ケタの文字を読み込む事がしたいのです。
次に、2ケタずつカンマで区切って読み込んだソースコードを投稿します。
但し、ここではmap0.txtをmap1.txtに、void Init(){}とvoid Move(){}関数の中身の1とAを、それぞれ1とAに変更しただけです。
map1.txt
コード:
00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11,00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,AA,AA,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,AA,AA,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11,00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11
map1.txtを読み込んだもの
コード:
#include <DxLib.h>
#define MAPSIZE 32 //マップサイズを決めます。
#define HEIGHT 15 //Y座標の最大値を決めます
#define WIDTH 40 //X座標の最大値を決めます
//キャラクターの数の最大値を決めます。念のために多めにします。今回はマップデータの数に合わせます。
#define CHARA HEIGHT*WIDTH
//画像データの構造体を作ります。
//画像データは無理に配列やポインタで整理しようとすると、エラーやフリーズの原因になります。
struct ImageData{
int kabe01; //
int teki0A[2]; //
};
struct ImageData im; //
//各キャラクターのデータの構造体を作ります。
struct CharaData{
//int *ghandle; //アニメーションさせるために画像データハンドル。
//ポインタ設定をしたが、これが原因の一つでした。
char kind; //キャラクターの種類を格納。
int anime_pattern; //アニメパーン数
float x; //座標はfloatにします。
float y;
int body; //体力
};
struct CharaData charadata[CHARA]; //今回はcharadataと名づけます。
//キャラクターは複数出現させるので、配列内に各キャラクターの最大値CHMAXを格納します。
//struct CharaData im[2]; //画像を描画するための変数。
//or//struct CharaData im[CHARA]; //画像を描画するための変数。
//アニメーションカウンター用の変数を作ります。
unsigned int g_anime_counter=0;
//マップデータを作ります。
char mapdata[HEIGHT][WIDTH];
//メモ帳からマップデータを読み込み
void MapLoad(){
//各キャラクターのデータを初期化します。
ZeroMemory(charadata,sizeof(charadata));
char buf[1024];
sprintf_s(buf,1024,"media/map%d.txt",1); //ファイル名を用意する
int fp; //ファイルハンドル
fp=FileRead_open(buf); //ファイルを開く
//ファイル読み込みエラー処理
if(fp==NULL){
printfDx("ファイル読み込みエラー");
return;
}
/////////////////////////////ここから////////////////////////////
for(int y=0;y<HEIGHT;y++){
for(int x=0;x<WIDTH;x++){
FileRead_scanf(fp,"%s",mapdata[y][x]);
} //for(int x=0;x<WIDTH;x++)の最後
} //for(int y=0;y<HEIGHT;y++)の最後
/////////////////////////////ここまで////////////////////////////
FileRead_close(fp); //ファイルを閉じる
} //void MapLoad();の最後
//画像をロードする関数を作ります。
void Load(){
im.kabe01=LoadGraph("media/kabe01.jpg");
LoadDivGraph("media/teki0A.jpg",2,2,1,32,32,im.teki0A);
}
//初期化用の関数を作ります。
void Init(){
//キャラクターをカウントする変数を作ります。必要な変数の一つです。
//キャラクターをカウントする変数はローカル変数でも問題ありませんでした。
int counter=0;
for(int y=0;y<HEIGHT;y++){
for(int x=0;x<WIDTH;x++){
char c=mapdata[y][x];
//初期化してマップデータから、キャラクターのデータを取り出します。
//kindにマップデータを代入します。
//これも必要な変数の一つです。
charadata[counter].kind=c;
charadata[counter].x=(float)x*MAPSIZE;
charadata[counter].y=(float)y*MAPSIZE;
int charaValid=0;
//この変数を利用しないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
//Validは英語で「有効、根拠の確実な、確かな、正当な」などの意味です。
//キャラクターごとに異なるものはswicth文を使います。
switch(c){ //なお、ここにcounterを入れてしまうと、フリーズしてしまいました。
case '11':
charadata[counter].body=1;
charaValid=1; //case毎にcv=1;と代入します。
break;
case 'AA':
charadata[counter].anime_pattern=2; //アニメーションさせる場合はここで代入します。
charadata[counter].body=1;
charaValid=1; //
break;
}
//このif文がないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
if(charaValid){
mapdata[y][x]='0'; //マップデータを'0'にする事で、データの取り出しは終わりです。
//ここでキャラクターの数を一つずつ増やしていきます。
counter++;
}
}
}
}
//描画と移動処理用の関数を作ります
void Move(){
for(int i=0;i<CHARA;i++){
char c=charadata[i].kind;
switch(c){
//ここにcharadata[i].kindではなくiを入れると、一つしか描画されませんでした。
//また、フリーズしてまった場合もあります。
case '11':
DrawGraph(charadata[i].x,charadata[i].y,im.kabe01,TRUE);
break;
case 'AA':
int a=g_anime_counter/20%charadata[i].anime_pattern;
DrawGraph(charadata[i].x,charadata[i].y,im.teki0A[a],TRUE);
break;
}
//キャラクター単位で動かす方法でマップスクロールを行います。
charadata[i].x=charadata[i].x-1;
}
}
//WinMain関数の中に、先ほど作った関数を入れます。//Move();だけwhile内に入れます。
int WINAPI WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lpC,int nC){
if(ChangeWindowMode(TRUE)!=0) return -1; //ウィンドウモードの変更
if(DxLib_Init()!=0) return -1; //DXライブラリ初期化処理
if(SetDrawScreen(DX_SCREEN_BACK)!=0) return -1; //描画先を裏画面に設定
//ロードの関数は、ここではここに入れます。
MapLoad(); //マップデータのロード
Load(); //画像のロード
Init(); //初期化。//if(charaValid)に関するコードを書いていない時は、ここに置かないで、while文の中に置くと、適切に描画されません。
while(ProcessMessage()==0&&CheckHitKey(KEY_INPUT_ESCAPE)==0){
//メッセージ処理(XキーかAlt+F4キーが押されたら終了)
//ESCキーが押されたら終了
if(ClearDrawScreen()!=0) return -1; //裏画面を消す
//Init(); //初期化。//if(charaValid)に関するコードを書いていないでwhile文の中に初期化関数Init();置くと、適切に描画されません。
//この関数をそのままwhile文の中に入れてしまうと、一番最初の画像が消えてしまう。
Move(); //画像の描画と移動用の関数をここに置きます。
g_anime_counter++; //
if(ScreenFlip()!=0) return -1; //裏画面を表画面に反映
}
if(DxLib_End()!=0) return -1; //DXライブラリの終了処理
return 0; //ソフトの終了
}
以上のソースコードをコンパイルすると、真黒な画面が表示されるだけです。
修正するべき箇所は、void MapLoad(){}関数内の//ここから//、//ここまで//の間に囲まれている部分である事までは分かっているのですが、どのように修正すればよいかが解決出来ていないと言うのが現状です。
以下にvoid MapLoad{}を抜粋します。
コード:
//メモ帳からマップデータを読み込み
void MapLoad(){
//各キャラクターのデータを初期化します。
ZeroMemory(charadata,sizeof(charadata));
char buf[1024];
sprintf_s(buf,1024,"media/map%d.txt",1); //ファイル名を用意する
int fp; //ファイルハンドル
fp=FileRead_open(buf); //ファイルを開く
//ファイル読み込みエラー処理
if(fp==NULL){
printfDx("ファイル読み込みエラー");
return;
}
/////////////////////////////ここから////////////////////////////
for(int y=0;y<HEIGHT;y++){
for(int x=0;x<WIDTH;x++){
FileRead_scanf(fp,"%s",mapdata[y][x]);
} //for(int x=0;x<WIDTH;x++)の最後
} //for(int y=0;y<HEIGHT;y++)の最後
/////////////////////////////ここまで////////////////////////////
FileRead_close(fp); //ファイルを閉じる
} //void MapLoad();の最後
質問者である自分が何をしたいについて改めて説明しなおします。
まずはmap0.txtの中身と、ソースコードを投稿します。
今回はちゃんとコピペしたので、画面が正常に表示されるはずです。
map0.txt
[code]
0000000000111111111100000000001111111111
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000AAA000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000AAA000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000111111111100000000001111111111
[/code]
map0.txtを読み込んだもの
[code]
#include <DxLib.h>
#define MAPSIZE 32 //マップサイズを決めます。
#define HEIGHT 15 //Y座標の最大値を決めます
#define WIDTH 40 //X座標の最大値を決めます
//キャラクターの数の最大値を決めます。念のために多めにします。今回はマップデータの数に合わせます。
#define CHARA HEIGHT*WIDTH
//画像データの構造体を作ります。
//画像データは無理に配列やポインタで整理しようとすると、エラーやフリーズの原因になります。
struct ImageData{
int kabe01; //
int teki0A[2]; //
};
struct ImageData im; //
//各キャラクターのデータの構造体を作ります。
struct CharaData{
//int *ghandle; //アニメーションさせるために画像データハンドル。
//ポインタ設定をしたが、これが原因の一つでした。
char kind; //キャラクターの種類を格納。
int anime_pattern; //アニメパーン数
float x; //座標はfloatにします。
float y;
int body; //体力
};
struct CharaData charadata[CHARA]; //今回はcharadataと名づけます。
//キャラクターは複数出現させるので、配列内に各キャラクターの最大値CHMAXを格納します。
//struct CharaData im[2]; //画像を描画するための変数。
//or//struct CharaData im[CHARA]; //画像を描画するための変数。
//アニメーションカウンター用の変数を作ります。
unsigned int g_anime_counter=0;
//マップデータを作ります。
char mapdata[HEIGHT][WIDTH];
//メモ帳からマップデータを読み込み
void MapLoad(){
//各キャラクターのデータを初期化します。
ZeroMemory(charadata,sizeof(charadata));
char buf[1024];
sprintf_s(buf,1024,"media/map%d.txt",1); //ファイル名を用意する
int fp; //ファイルハンドル
fp=FileRead_open(buf); //ファイルを開く
//ファイル読み込みエラー処理
if(fp==NULL){
printfDx("ファイル読み込みエラー");
return;
}
/////////////////////////////ここから////////////////////////////
for(int y=0;y<HEIGHT;y++){
for(int x=0;x<WIDTH;x++){
FileRead_scanf(fp,"%s",mapdata[y][x]);
} //for(int x=0;x<WIDTH;x++)の最後
} //for(int y=0;y<HEIGHT;y++)の最後
/////////////////////////////ここまで////////////////////////////
FileRead_close(fp); //ファイルを閉じる
} //void MapLoad();の最後
//画像をロードする関数を作ります。
void Load(){
im.kabe01=LoadGraph("media/kabe01.jpg");
LoadDivGraph("media/teki0A.jpg",2,2,1,32,32,im.teki0A);
}
//初期化用の関数を作ります。
void Init(){
//キャラクターをカウントする変数を作ります。必要な変数の一つです。
//キャラクターをカウントする変数はローカル変数でも問題ありませんでした。
int counter=0;
for(int y=0;y<HEIGHT;y++){
for(int x=0;x<WIDTH;x++){
char c=mapdata[y][x];
//初期化してマップデータから、キャラクターのデータを取り出します。
//kindにマップデータを代入します。
//これも必要な変数の一つです。
charadata[counter].kind=c;
charadata[counter].x=(float)x*MAPSIZE;
charadata[counter].y=(float)y*MAPSIZE;
int charaValid=0;
//この変数を利用しないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
//Validは英語で「有効、根拠の確実な、確かな、正当な」などの意味です。
//キャラクターごとに異なるものはswicth文を使います。
switch(c){ //なお、ここにcounterを入れてしまうと、フリーズしてしまいました。
case '1':
charadata[counter].body=1;
charaValid=1; //case毎にcv=1;と代入します。
break;
case 'A':
charadata[counter].anime_pattern=2; //アニメーションさせる場合はここで代入します。
charadata[counter].body=1;
charaValid=1; //
break;
}
//このif文がないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
if(charaValid){
mapdata[y][x]='0'; //マップデータを'0'にする事で、データの取り出しは終わりです。
//ここでキャラクターの数を一つずつ増やしていきます。
counter++;
}
}
}
}
//描画と移動処理用の関数を作ります
void Move(){
for(int i=0;i<CHARA;i++){
char c=charadata[i].kind;
switch(c){
//ここにcharadata[i].kindではなくiを入れると、一つしか描画されませんでした。
//また、フリーズしてまった場合もあります。
case '1':
DrawGraph(charadata[i].x,charadata[i].y,im.kabe01,TRUE);
break;
case 'A':
int a=g_anime_counter/20%charadata[i].anime_pattern;
DrawGraph(charadata[i].x,charadata[i].y,im.teki0A[a],TRUE);
break;
}
//キャラクター単位で動かす方法でマップスクロールを行います。
charadata[i].x=charadata[i].x-1;
}
}
//WinMain関数の中に、先ほど作った関数を入れます。//Move();だけwhile内に入れます。
int WINAPI WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lpC,int nC){
if(ChangeWindowMode(TRUE)!=0) return -1; //ウィンドウモードの変更
if(DxLib_Init()!=0) return -1; //DXライブラリ初期化処理
if(SetDrawScreen(DX_SCREEN_BACK)!=0) return -1; //描画先を裏画面に設定
//ロードの関数は、ここではここに入れます。
MapLoad(); //マップデータのロード
Load(); //画像のロード
Init(); //初期化。//if(charaValid)に関するコードを書いていない時は、ここに置かないで、while文の中に置くと、適切に描画されません。
while(ProcessMessage()==0&&CheckHitKey(KEY_INPUT_ESCAPE)==0){
//メッセージ処理(XキーかAlt+F4キーが押されたら終了)
//ESCキーが押されたら終了
if(ClearDrawScreen()!=0) return -1; //裏画面を消す
//Init(); //初期化。//if(charaValid)に関するコードを書いていないでwhile文の中に初期化関数Init();置くと、適切に描画されません。
//この関数をそのままwhile文の中に入れてしまうと、一番最初の画像が消えてしまう。
Move(); //画像の描画と移動用の関数をここに置きます。
g_anime_counter++; //
if(ScreenFlip()!=0) return -1; //裏画面を表画面に反映
}
if(DxLib_End()!=0) return -1; //DXライブラリの終了処理
return 0; //ソフトの終了
}
[/code]
次にvoid MapLoad(){}の中身をご覧ください。
以上のソースコードは、map0.txtからデータを読み込んで、マップデータに変換しているのですが、map0.txtは、ご覧の通り、カンマや空白などで区切られておらず、1ケタずつ読み込まれます。
以上の方法には、二つ問題があります。
第一に、以上のような1ケタずつ読み込んでいく方法だと、整数10個、アルファベット大文字26文字、小文字26文字で、合計62種類までのデータを読み込む事が出来ます。
しかし、もしも62種類よりも多くのデータを読み込みたい場合、2ケタの整数や文字を用意する必要があります。例えば100種類、200種類のデータを読み込みたい場合、00、01、AAなどのような整数や文字が必要であります、
第二に、カンマや空白などで区切られていないと、何行目の何列目かが分かり辛い、目で見ると目が痛くなってしまうと言う問題があります。そこで、カンマや空白などでデータを区切る事で、見えやすくする必要があります。
以上の理由から、私はカンマ区切りの文字を読み込む事と、2ケタの文字を読み込む事がしたいのです。
次に、2ケタずつカンマで区切って読み込んだソースコードを投稿します。
但し、ここではmap0.txtをmap1.txtに、void Init(){}とvoid Move(){}関数の中身の1とAを、それぞれ1とAに変更しただけです。
map1.txt
[code]
00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11,00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,AA,AA,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,AA,AA,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11,00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11
[/code]
map1.txtを読み込んだもの
[code]
#include <DxLib.h>
#define MAPSIZE 32 //マップサイズを決めます。
#define HEIGHT 15 //Y座標の最大値を決めます
#define WIDTH 40 //X座標の最大値を決めます
//キャラクターの数の最大値を決めます。念のために多めにします。今回はマップデータの数に合わせます。
#define CHARA HEIGHT*WIDTH
//画像データの構造体を作ります。
//画像データは無理に配列やポインタで整理しようとすると、エラーやフリーズの原因になります。
struct ImageData{
int kabe01; //
int teki0A[2]; //
};
struct ImageData im; //
//各キャラクターのデータの構造体を作ります。
struct CharaData{
//int *ghandle; //アニメーションさせるために画像データハンドル。
//ポインタ設定をしたが、これが原因の一つでした。
char kind; //キャラクターの種類を格納。
int anime_pattern; //アニメパーン数
float x; //座標はfloatにします。
float y;
int body; //体力
};
struct CharaData charadata[CHARA]; //今回はcharadataと名づけます。
//キャラクターは複数出現させるので、配列内に各キャラクターの最大値CHMAXを格納します。
//struct CharaData im[2]; //画像を描画するための変数。
//or//struct CharaData im[CHARA]; //画像を描画するための変数。
//アニメーションカウンター用の変数を作ります。
unsigned int g_anime_counter=0;
//マップデータを作ります。
char mapdata[HEIGHT][WIDTH];
//メモ帳からマップデータを読み込み
void MapLoad(){
//各キャラクターのデータを初期化します。
ZeroMemory(charadata,sizeof(charadata));
char buf[1024];
sprintf_s(buf,1024,"media/map%d.txt",1); //ファイル名を用意する
int fp; //ファイルハンドル
fp=FileRead_open(buf); //ファイルを開く
//ファイル読み込みエラー処理
if(fp==NULL){
printfDx("ファイル読み込みエラー");
return;
}
/////////////////////////////ここから////////////////////////////
for(int y=0;y<HEIGHT;y++){
for(int x=0;x<WIDTH;x++){
FileRead_scanf(fp,"%s",mapdata[y][x]);
} //for(int x=0;x<WIDTH;x++)の最後
} //for(int y=0;y<HEIGHT;y++)の最後
/////////////////////////////ここまで////////////////////////////
FileRead_close(fp); //ファイルを閉じる
} //void MapLoad();の最後
//画像をロードする関数を作ります。
void Load(){
im.kabe01=LoadGraph("media/kabe01.jpg");
LoadDivGraph("media/teki0A.jpg",2,2,1,32,32,im.teki0A);
}
//初期化用の関数を作ります。
void Init(){
//キャラクターをカウントする変数を作ります。必要な変数の一つです。
//キャラクターをカウントする変数はローカル変数でも問題ありませんでした。
int counter=0;
for(int y=0;y<HEIGHT;y++){
for(int x=0;x<WIDTH;x++){
char c=mapdata[y][x];
//初期化してマップデータから、キャラクターのデータを取り出します。
//kindにマップデータを代入します。
//これも必要な変数の一つです。
charadata[counter].kind=c;
charadata[counter].x=(float)x*MAPSIZE;
charadata[counter].y=(float)y*MAPSIZE;
int charaValid=0;
//この変数を利用しないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
//Validは英語で「有効、根拠の確実な、確かな、正当な」などの意味です。
//キャラクターごとに異なるものはswicth文を使います。
switch(c){ //なお、ここにcounterを入れてしまうと、フリーズしてしまいました。
case '11':
charadata[counter].body=1;
charaValid=1; //case毎にcv=1;と代入します。
break;
case 'AA':
charadata[counter].anime_pattern=2; //アニメーションさせる場合はここで代入します。
charadata[counter].body=1;
charaValid=1; //
break;
}
//このif文がないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
if(charaValid){
mapdata[y][x]='0'; //マップデータを'0'にする事で、データの取り出しは終わりです。
//ここでキャラクターの数を一つずつ増やしていきます。
counter++;
}
}
}
}
//描画と移動処理用の関数を作ります
void Move(){
for(int i=0;i<CHARA;i++){
char c=charadata[i].kind;
switch(c){
//ここにcharadata[i].kindではなくiを入れると、一つしか描画されませんでした。
//また、フリーズしてまった場合もあります。
case '11':
DrawGraph(charadata[i].x,charadata[i].y,im.kabe01,TRUE);
break;
case 'AA':
int a=g_anime_counter/20%charadata[i].anime_pattern;
DrawGraph(charadata[i].x,charadata[i].y,im.teki0A[a],TRUE);
break;
}
//キャラクター単位で動かす方法でマップスクロールを行います。
charadata[i].x=charadata[i].x-1;
}
}
//WinMain関数の中に、先ほど作った関数を入れます。//Move();だけwhile内に入れます。
int WINAPI WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lpC,int nC){
if(ChangeWindowMode(TRUE)!=0) return -1; //ウィンドウモードの変更
if(DxLib_Init()!=0) return -1; //DXライブラリ初期化処理
if(SetDrawScreen(DX_SCREEN_BACK)!=0) return -1; //描画先を裏画面に設定
//ロードの関数は、ここではここに入れます。
MapLoad(); //マップデータのロード
Load(); //画像のロード
Init(); //初期化。//if(charaValid)に関するコードを書いていない時は、ここに置かないで、while文の中に置くと、適切に描画されません。
while(ProcessMessage()==0&&CheckHitKey(KEY_INPUT_ESCAPE)==0){
//メッセージ処理(XキーかAlt+F4キーが押されたら終了)
//ESCキーが押されたら終了
if(ClearDrawScreen()!=0) return -1; //裏画面を消す
//Init(); //初期化。//if(charaValid)に関するコードを書いていないでwhile文の中に初期化関数Init();置くと、適切に描画されません。
//この関数をそのままwhile文の中に入れてしまうと、一番最初の画像が消えてしまう。
Move(); //画像の描画と移動用の関数をここに置きます。
g_anime_counter++; //
if(ScreenFlip()!=0) return -1; //裏画面を表画面に反映
}
if(DxLib_End()!=0) return -1; //DXライブラリの終了処理
return 0; //ソフトの終了
}
[/code]
以上のソースコードをコンパイルすると、真黒な画面が表示されるだけです。
修正するべき箇所は、void MapLoad(){}関数内の//ここから//、//ここまで//の間に囲まれている部分である事までは分かっているのですが、どのように修正すればよいかが解決出来ていないと言うのが現状です。
以下にvoid MapLoad{}を抜粋します。
[code]
//メモ帳からマップデータを読み込み
void MapLoad(){
//各キャラクターのデータを初期化します。
ZeroMemory(charadata,sizeof(charadata));
char buf[1024];
sprintf_s(buf,1024,"media/map%d.txt",1); //ファイル名を用意する
int fp; //ファイルハンドル
fp=FileRead_open(buf); //ファイルを開く
//ファイル読み込みエラー処理
if(fp==NULL){
printfDx("ファイル読み込みエラー");
return;
}
/////////////////////////////ここから////////////////////////////
for(int y=0;y<HEIGHT;y++){
for(int x=0;x<WIDTH;x++){
FileRead_scanf(fp,"%s",mapdata[y][x]);
} //for(int x=0;x<WIDTH;x++)の最後
} //for(int y=0;y<HEIGHT;y++)の最後
/////////////////////////////ここまで////////////////////////////
FileRead_close(fp); //ファイルを閉じる
} //void MapLoad();の最後
[/code]