固定マップからの滑らかな脱出

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
きずなん

固定マップからの滑らかな脱出

#1

投稿記事 by きずなん » 14年前

現在2DRPG作成中です。環境はVisualC+2008です。
サンプルの紹介や色々とヒントをいただき、
   タイトル画面→マップ描画→その上にキャラ表示→・・・
というところまで出来ました。

次に、『そのマップである地点にキャラが到達すれば、そのマップから抜ける』処理をしたい状況です。
その方法として色々考えてみたのですがどうもうまくいくのがありません。
今やってる方法としては、まずint Hantei[縦][横]={ {1,0,0,・・・}}という感じで判定に数字をあてて、IsAbleToGoで0なら戻り値を0、1なら1、2なら2を返すようにしています。 0=通行可能、1=通行不可、2=脱出フラグ という割り当てです。これをwhileループの中の移動フラグをたてる構造の部分で、if( IsAbleToGo=2) break; という感じで、2ならwhileループから抜けるという風に組みました。
すると、例えば■が脱出点とし、|を壁とし、キャラが左から向かってると
|□
|■←
|□
この■の右端にふれた瞬間にループから抜けてしまうんです。
壁を無くしてそれぞれ右に1マスずらせばいい話のような気もしますが、毎回それをしてると不便だしマップの都合上、端をやはり脱出点にしたいです。
■の右端にふれた瞬間でなく、■の左端までいった後にwhileから抜けるようにするにはどうしたらいいでしょうか?
説明がヘタクソですいません。



ちなみにcodeはこんな感じです。

コード:

#include "DxLib.h"

#define MAP_SIZE	32			// マップチップ一つのドットサイズ
#define MAP_WIDTH	20			// マップの幅
#define MAP_HEIGHT	15			// マップの縦長さ

typedef struct{
        int x,y,img,muki,walking_flag;
}ch_t;


// マップデータ
int MapData[ MAP_HEIGHT ][ MAP_WIDTH ] =
{
	{ 19, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 38} ,
	{ 36, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 12, 0, 0, 0, 0, 16 } ,
	{ 36, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 12, 0, 21, 21, 21, 16 } ,
	{ 36, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 30, 0, 21, 21, 21, 16 } ,
	{ 36, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 12, 0, 21, 21, 21, 16 } ,
	{ 36, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 12, 0, 0, 0, 0, 16 } ,
	{ 36, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 12, 0, 0, 0, 0, 16 } ,
	{ 30, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 21, 0, 0, 12, 0, 0, 0, 0, 16 } ,
	{ 36, 0, 0, 0, 0, 0, 0, 13, 14, 0, 1, 0, 0, 0, 12, 0, 0, 0, 0, 16 } ,
	{ 36, 1, 0, 0, 0, 0, 0, 33, 34, 0, 1, 0, 0, 0, 12, 0, 0, 0, 0, 16 } ,
	{ 36, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 30, 0, 0, 0, 0, 16 } ,
	{ 36, 1, 0, 1, 9, 9, 0, 0, 1, 0, 1, 0, 0, 0, 12, 0, 0, 0, 0, 16 } ,
	{ 36, 1, 1, 1, 9, 9, 9, 9, 1, 0, 1, 2, 0, 0, 12, 0, 0, 0, 0, 16 } ,
	{ 36, 1, 0, 1, 9, 9, 9, 9, 1, 0, 1, 0, 0, 0, 12, 0, 0, 0, 0, 16 } ,
	{ 18, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 19} 
} ; 
//判定
int hantei[MAP_HEIGHT][ MAP_WIDTH ] = {
	{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 } ,
	{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } ,
	{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } ,
	{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } ,
	{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } ,
	{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } ,
	{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } ,
	{ 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } ,
	{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } ,
	{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } ,
	{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } ,
	{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } ,
	{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } ,
	{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } ,
	{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 } ,
};


int IsAbleToGo(int x,int y,int muki){//進めるかを判定する
        if(muki==0)//上向きなら
                if(hantei[y/32-1][x/32]==1)//進めるか判定
                        return 1;//エラー
        if(muki==1)//左向きなら
                if(hantei[y/32][x/32-1]==1)
                        return 1;
        if(muki==2)//下向きなら
                if(hantei[y/32+1][x/32]==1)
                        return 1;
        if(muki==3)//右向きなら
                if(hantei[y/32][x/32+1]==1)
                        return 1;

		if(muki==0)//上向きなら
                if(hantei[y/32-1][x/32]==2)
                        return 2;//出口フラグ
        if(muki==1)//左向きなら
                if(hantei[y/32][x/32-1]==2)
                        return 2;
        if(muki==2)//下向きなら
                if(hantei[y/32+1][x/32]==2)
                        return 2;
        if(muki==3)//右向きなら
                if(hantei[y/32][x/32+1]==2)
                        return 2;

        return 0;//正常
}

 
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
        
		char Key[256];
        ch_t ch;
		int i , j ,c=0 , image[16];
 
    if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化,初期化処理

		SetMainWindowText( "サンプルRPG" ) ; // タイトル変更


	int map[300];//300個の画像を格納
        LoadDivGraph( "画像/img15_3.png" , 300 , 20 , 15 , 32 , 32 , map ) ;//300個(20*15),32px

        ch.x    =320;
        ch.y    =224;
        ch.walking_flag=0;
        ch.muki=2;
 
        SetDrawScreen( DX_SCREEN_BACK ) ;                               //描画先を裏画面に設定
        LoadDivGraph( "画像/char.png" , 16 , 4 , 4 , 32 , 32 , image ) ;//キャラクタ画像を分割ロード

		int title00;
		title00 = LoadGraph( "画像/title.png" ); // タイトル画像をロード
 


	//タイトル画像の描画
	DrawGraph( 0, 0, title00, TRUE );
	// 文字列の描画
	DrawString( 250 , 150 , "Press 『Enter』 Key." , GetColor( 0 , 0 , 0 ) );

    while(!ProcessMessage() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_RETURN] && ScreenFlip()==0){
	}	//エンターでゲームスタート





    while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
            //メッセージ処理,画面クリア,キーボード入力状態取得,ESCで終了

			//マップ描画処理
			for( i = 0 ; i < MAP_HEIGHT ; i ++ )
				{
					for( j = 0 ; j < MAP_WIDTH ; j ++ )
						{
							int map_chip = MapData[ i ][ j ];
							DrawGraph( j*32 , i*32 , map[map_chip] , TRUE );
						}
				}
 

        if(ch.x%32==0 && ch.y%32==0){         //座標が32で割り切れたら入力可能
            ch.walking_flag=1;         //歩くフラグを立てる。
            if     ( Key[ KEY_INPUT_UP   ]  == 1 )  //上ボタンが押されたら
                    ch.muki=0;         //上向きフラグを立てる
            else if( Key[ KEY_INPUT_LEFT ]  == 1 )  //左ボタンが押されたら
                    ch.muki=1;         //左向きフラグを立てる
            else if( Key[ KEY_INPUT_DOWN ]  == 1 )  //下ボタンが押されたら
                    ch.muki=2;         //下向きフラグを立てる
            else if( Key[ KEY_INPUT_RIGHT]  == 1 )  //右ボタンが押されたら
                    ch.muki=3;         //右向きフラグを立てる
            else                                    //何のボタンも押されてなかったら
                    ch.walking_flag=0; //歩かないフラグを立てる
			if(ch.walking_flag==1)    //もし歩くなら
                if(IsAbleToGo(ch.x,ch.y,ch.muki)==1)//行き先が歩けないなら
                    ch.walking_flag=0;                  //歩かないフラグを立てる。
                if(IsAbleToGo(ch.x,ch.y,ch.muki)==2) break; //出口へついたら終了
		  }
 

        if(ch.walking_flag==1){        //歩くフラグが立っていたら
            if     (ch.muki==0)        //上向きならch.y座標を減らす
                    ch.y--;
            else if(ch.muki==1)        //左向きならch.x座標を減らす
                    ch.x--;
            else if(ch.muki==2)        //下向きならch.y座標を増やす
                    ch.y++;
            else if(ch.muki==3)        //右向きならch.x座標を増やす
                    ch.x++;
        }
 

        ch.img=image[(ch.x%32+ch.y%32)/8 + ch.muki*4];            //画像をセット
 
        DrawGraph( ch.x , ch.y , ch.img , TRUE ) ;//画像を描画
 
        ScreenFlip();//裏画面を表画面に反映

		}
	
	
    DxLib_End();
    return 0;
}

non
記事: 1097
登録日時: 15年前

Re: 固定マップからの滑らかな脱出

#2

投稿記事 by non » 14年前

mapと判定用の配列を、もう一回り大きくするのが一番簡単だと思います。
non

Ryo

Re: 固定マップからの滑らかな脱出

#3

投稿記事 by Ryo » 14年前

外に向かっていくときだけを考えるのなら
たとえば

コード:

       if(muki==0)//上向きなら
                if(hantei[ (y+32)/32-1][x/32]==2)
                        return 2;//出口フラグ
としてみるのはどうでしょう?

他にも、マップの端ではない場所に階段だとか、イベント発生の判定があるとか考えると

コード:

       if ( x%32 == 0  && y%32 == 0 )//どちらも32で割り切れる
       {
              //マップチップの中央にきたときの判定
       }
みたいな判定を先に入れてみるのはどうでしょう

Ryo

Re: 固定マップからの滑らかな脱出

#4

投稿記事 by Ryo » 14年前

ごめんなさい、上の書き込みの後半は勘違いです
IsAbleToGo()を呼び出す時点で、x、yともに割り切れる値になっていましたね。

IsAbleToGoは、移動先を調べる関数ですので、これとは別に、現在位置のフラグを調べる関数をつくり
位置変更後の165行目の位置に、その関数を呼ぶようにしたらどうでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 固定マップからの滑らかな脱出

#5

投稿記事 by softya(ソフト屋) » 14年前

nonさんの言うとおり一回り大きくするのが一番簡単です。
それと今後イベントやら情報が増えていくと思いますのでマップ作成ツールを自作するか汎用ツールの導入をお勧めします。

私が書いたRPG講座です。
ちょー簡単と書いてますが実際には本格RPG風超コンパクト版になってしまっています。
良かったら参考にして下さい。

「マイ 日記 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/blog.php?u=114&sd=a&c=2
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

きずなん

Re: 固定マップからの滑らかな脱出

#6

投稿記事 by きずなん » 14年前

返信ありがとうございます。
マップと判定の配列を一回り大きくするのが一番簡単でしたのでそうしました。
Ryoさんも考えていただきありがとうございました!
それからsoft屋さんのサイトも参考にさせていただきます。
みなさん本当にありがとうございましたm(__)m

閉鎖

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