マップデータの初期値を読み込んで画像を描画した後、敵などの画像を動かしたい。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
プログラマ見習い
記事: 44
登録日時: 2ヶ月前

マップデータの初期値を読み込んで画像を描画した後、敵などの画像を動かしたい。

#1

投稿記事 by プログラマ見習い » 2ヶ月前

 横スクロールアクションゲームを作っています。

 現在、二次元配列で、敵や壁などを含めたマップデータの初期値を作成した後、画像を描画する所までは出来ました。
 しかし、敵画像などの、動かしたい画像を動かす事が出来なくて行き詰っております。

 何らかの方法でマップデータを取り出す必要があるとまでは理解しているのですが、その方法が分からない状態です。

コード:


char map01no01[15][20]={

/*00*/{'0','0','0','0','0','1','1','1','0','0'/**/,'0','0','0','0','0','0','0','0','0','0'},
/*01*/{'0','0','0','0','0','0','0','0','0','0'/**/,'0','0','0','0','0','0','0','0','0','0'},
/*02*/{'0','0','0','0','0','0','0','0','A','0'/**/,'0','0','0','0','0','0','0','0','0','0'},
/*03*/{'0','0','0','0','0','0','0','0','0','0'/**/,'0','0','0','0','0','0','0','0','0','0'},
/*04*/{'0','0','0','0','0','0','0','0','0','0'/**/,'0','0','A','0','0','0','0','0','0','0'},
/*05*/{'0','0','0','0','0','A','0','0','0','0'/**/,'0','0','0','0','0','0','0','0','0','0'},
/*06*/{'0','0','0','0','0','0','0','0','A','0'/**/,'0','0','0','0','0','0','0','0','0','0'},
/*07*/{'0','0','0','0','0','0','0','0','0','0'/**/,'0','0','0','0','A','0','0','0','0','0'},
/*08*/{'0','0','0','0','0','0','0','0','0','0'/**/,'0','0','0','0','0','0','0','0','0','0'},
/*09*/{'0','0','0','0','0','0','0','0','0','0'/**/,'0','0','0','0','0','0','0','0','0','0'},
/*10*/{'0','0','0','0','0','A','0','0','0','0'/**/,'0','0','0','0','0','0','0','0','0','0'},
/*11*/{'0','0','0','0','0','0','0','0','A','0'/**/,'0','0','0','0','0','0','0','0','0','0'},
/*12*/{'0','0','0','0','0','0','0','0','1','0'/**/,'0','0','0','0','0','0','0','0','0','0'},
/*13*/{'0','0','0','0','0','0','0','1','1','0'/**/,'0','0','0','0','0','0','0','0','0','0'},
/*14*/{'1','1','1','1','1','1','1','1','1','1'/**/,'1','1','1','1','1','1','1','1','1','1'}

};



 //●マップの描画
void DrawMap(){

 for(int y=0;y<15;y++){
  for(int x=0;x<20;x++){

   int i=map01no01[y][x+1];//各キャラの初期位置を取得する。
 
   DrawGraph(x*32,y*32,mapdeta[i].ghandle,TRUE); //画像を描画

 //マップデータの初期値を抜き出す必要がある。
   map01no01[y][x+1]=0;

   }


  }
 }

}


 データを抜き出した後、「map01no01[y][x+1]=0;」で初期値を消す必要があると入門書で読んだのですが、その抜き出す方法が分からないので、「map01no01[y][x+1]=0;」を入力すると、当然、せっかく描画した画像が消えてしまう状態です。

 上記の2次元配列でマップデータの画像を描画した後、動かしたい画像を動かす方法が、どうしてもわからないので、手がかりを教えていただけないでしょうか。

プログラマ見習い
記事: 44
登録日時: 2ヶ月前

Re: マップデータの初期値を読み込んで画像を描画した後、敵などの画像を動かしたい。

#2

投稿記事 by プログラマ見習い » 2ヶ月前

追記。補足説明です。
'1''は壁や床などの障害物です。'A'は敵キャラクターです。'0'は何も表示しないです。とりあえず、'A'だけを動かしたいです。

littlestream
記事: 33
登録日時: 2年前

Re: マップデータの初期値を読み込んで画像を描画した後、敵などの画像を動かしたい。

#3

投稿記事 by littlestream » 2ヶ月前

一番わかりやすいのは、画像マップデータと敵のマップデータを分離させる事です。
少なくとも、char map01no01[2][15][20];として3次元配列にして、map01no01[0]に画像のマップデータ、
map01no01[1]に敵データとすることで回避できるはずです。もちろん、map01no01[1]には0を代入しないと
やり方によってはマップを描画するだけ敵が出てくるので0を代入すると良いと思います。

プログラマ見習い
記事: 44
登録日時: 2ヶ月前

Re: マップデータの初期値を読み込んで画像を描画した後、敵などの画像を動かしたい。

#4

投稿記事 by プログラマ見習い » 2ヶ月前

littlestreamさんへ。アドバイスありがとうございます。
しかし、マップデータから動かしたい画像の位置情報を取り出す事がどうしても出来ません。

 以下のソースコードでデータを取り出そうとしたのですが、画面起動と同時にすぐに消えてしまいました。
 データの取り出しが未だに出来ない状態です。

 以下のソースコードで修正するべき所を指摘して下されば幸いです。

コード:

 //●各マップデータを初期化して位置情報を取り出す
void InitMap(){

 for(int y=0;y<YHMAX;y++){
  for(int x=0;x<XWMAX;x++){
   for(int n=0;n<YHMAX*XWMAX;n++){

   int i=map01no01[y][x];

   switch(i){

   case '1':
   case 'A':

    md.num[n].x=x;
    md.num[n].y=y;
    md.num[n].type=i;

    map01no01[y][x]=0;

    break;

     } //switch(i)の最後

   } //for(int n=0;n<YHMAX*XHMAX;n++)の最後
  } //for(int x=0;x<XHMAX;x++)
 } //for(int y;y<YHMAX;y++)の最後

}

 //●キャラの描画
void DrawChara(){

 //for(int i=0;i<30;i++){
   for(int n=0;n<YHMAX*XWMAX;n++){


    int i=md.num[n].type;


    int tmpx=md.num[n].x;
    int tmpy=md.num[n].y;

    tmpx=md.num[n].x;
    tmpy=md.num[n].y;

    DrawGraph(md.num[n].x*32,md.num[n].y*32,ch[i].ghandle,TRUE);

   } //for(int n=0;n<YHMAX*XHMAX;n++)の最後
 //} //

} //void DrawChara();の最後


littlestream
記事: 33
登録日時: 2年前

Re: マップデータの初期値を読み込んで画像を描画した後、敵などの画像を動かしたい。

#5

投稿記事 by littlestream » 2ヶ月前

ちょっと衝撃というか複雑な感想を受けましたが
多分、ゲームプログラムに関してノウハウというか、定石を知らないのかもしれないな...
と思いました。が、基本さえ知ればどうってこともありません。

まず、マップデータの座標とキャラクターの座標は特に制約がない限り、一緒に扱う必要はないので
マップデータは1マスずつ、管理します。
つまりマップチップと呼ばれる大抵16ドットx16ドット、もしくは32x32ドット
(最近のコンシューマーゲーム機の2Dゲームの解像度はかなり高いので無視します)
で構成されており、スプライトと呼ばれるドット絵のキャラは移動単位が1ドットずつ動きます。

なので、ゲームプログラムは基本的にforループで回しても良いですが、無限ループが基本です。
それに加えてWindowsのプログラムはマルチタスクなので他にもプログラムを動かないとマズいので
WinMain関数の中に次のループを含ませます。

コード:

	
	int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hP,LPSTR lpC,int nC)
{
	static count=0;
	double angle=0;

	ChangeWindowMode(TRUE);			//ウィンドウモードで起動
	SetGraphMode(640,480,32);
	SetMainWindowText("NO TITLE -Developing-"); //ウィンドウのタイトル
	if(DxLib_Init() == -1) return (-1);	//DXライブラリ初期化
	
	//データ読み込み中と表示する
	DrawString( 0 , 0 , "データ読み込み中" , GetColor(255,255,255) );

	//各種変数の初期化など
	Init();
	
	//乱数の初期化
	srand((unsigned)GetTickCount());
	
	SetDrawScreen(DX_SCREEN_BACK);
	
	//メインループ
	while( ProcessMessage()==0 && CheckHitKey(KEY_INPUT_ESCAPE)==0){
		
		ProcessMessage();
		ClsDrawScreen();			//画面を初期化
		
		//ここに処理を書いていく

		ScreenFlip();				//フリップする
	}
	
	DxLib_End();	//DXライブラリ終了処理
	return (0);		//終了
}

とします。

littlestream
記事: 33
登録日時: 2年前

Re: マップデータの初期値を読み込んで画像を描画した後、敵などの画像を動かしたい。

#6

投稿記事 by littlestream » 2ヶ月前

実はきちんと変数が管理されているなら
マップデータと位置情報を一致させる必要はどこにも無いのですよ。
だから、まずプレイヤーキャラクターの座標の
変数を定義して代入して移動させるところまで作ってしまいましょう。
敵の位置はマップデータから読み込みたいならそれもありです。
その場合もマップデータと常に同期させる必要はどこにも無いです。
何故ならこの場合のマップデータはマップチップの
サイズで管理されているので常に同期すると1マスずつ動いてしまいます。

コード:

for(int y=0;y<15;y++)
  for(int x=0;x<20;x++)
     if(map01no01[1][y][x]=='A') {CreateEnemy(y,x);map01no01[1][y][x]=0;}

コード:

void CreateEnemy(int y,int x)
{
    for(敵の数だけ変数iをループ)
    {
        if(Enemy[i].flagが無いなら)
        {
            Enemy[i].x=x;
            Enemy[i].y=y;
            Enemy[i].flagをセット;
            break;
        }
    }
}

ただ、敵の位置はマップデータから読み取る以外にも
方法はあります。
スクロール量から取り出す方法やタイマーでフレーム数から読み取る方法などがあります。

スクロールはその後でも良いですが、このままのサイズだと恐らくはみ出てしまうので書くと

コード:

ScrollX=メインキャラクターのX座標-(スクリーンの幅/2);
ScrollY=メインキャラクターのY座標-(スクリーンの高さ/2);
int FstX=(ScrollX/マップチップのサイズ);int LstX=(ScrollX+スクリーンの幅)/マップチップのサイズ;
int FstY=(ScrollY/マップチップのサイズ);int LstY=(ScrollY+スクリーンの高さ)/マップチップのサイズ;

for(int y=FstY;y<LstY;y++)
{
    for(int x=FstX;<LstX;x++)
    {
          DrawMapChip(x-ScrollX,y-ScrollY,マップデータ[y][x]);
    }
}
そして、マップが上手く表示出来たら、キャラクターをスクロールする分だけ引いて描画します。
DrawGraph(x-ScrollX,y-ScrollY,Image,TRUE);
マップの後にキャラクターを描く理由は通常の背景が後ろに来る可能性が高いからです。もちろん、
スーファミレベルのゲームのように透過して前に背景を描いてリアリティを作るのもありです。

プログラマ見習い
記事: 44
登録日時: 2ヶ月前

Re: マップデータの初期値を読み込んで画像を描画した後、敵などの画像を動かしたい。

#7

投稿記事 by プログラマ見習い » 2ヶ月前

littlestreamさんへ。貴重なアドバイスをありがとうございます。いろいろ試させていただきます。

littlestream
記事: 33
登録日時: 2年前

Re: マップデータの初期値を読み込んで画像を描画した後、敵などの画像を動かしたい。

#8

投稿記事 by littlestream » 2ヶ月前

只今、某横スクロールアクションをリスペクトしたゲームのサンプルソースを
作っているのでよければ待っててください。

ただし、一週間こちらから連絡がなければそちらが待たなくても
良いと考えてください。

返信

“C言語何でも質問掲示板” へ戻る