ページ 11

マップのスクロールについて

Posted: 2013年9月21日(土) 15:11
by ぺぺろん
DXライブラリ初心者です。
貴重なスペースをお借りして初めて質問させていただきます。

現在、旧ゲームプログラミングの館の22章にあるプログラムを基に
スクロール機能を追加したいと考えていまして、
こちらの掲示板を色々と参考にさせていただきながら作業を行っていたのですが、
画面がスクロールするどころかキャラ自体まともに動かなくなってしまいました。

コード:


#include "DxLib.h"

#define SCREEN_WIDTH (640) // 画面の横幅
#define SCREEN_HEIGHT (480) // 画面の縦幅
#define MAP_PIXEL_WIDTH (1280)// マップの横幅
#define MAP_PIXEL_HEIGHT (480)// マップの縦幅
#define CHIP_SIZE (32) // 一つのチップのサイズ
#define MAP_WIDTH ( MAP_PIXEL_WIDTH / CHIP_SIZE) // マップの横幅
#define MAP_HEIGHT (MAP_PIXEL_HEIGHT / CHIP_SIZE) // マップの縦幅 
#define SPEED (1.0F) // キャラの移動スピード
 
typedef struct{
        int img,muki,walking_flag;
}ch_t;
 

int WINAPI WinMain( HINSTANCE, HINSTANCE,LPSTR, int){
        
        int image[16];
        char Key[256];
        ch_t ch;

		int PlX, PlY ; // プレイヤーの座標(中心座標)
		int camerax = 0, cameray = 0;//カメラの左上座標
		int charx = 0, chary = 0;//自キャラ位置
		int view_charx = 0, view_chary = 0;//自キャラの表示位置。この座標にdrawする。
		int h_image; //1280×480の背景用
		int MoveX = 0, MoveY = 0;

 
    if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理
 
        PlX    =320;
        PlY    =160;
        ch.walking_flag=0;
        ch.muki=3;
		
		 
        SetDrawScreen( DX_SCREEN_BACK ) ; //描画先を裏画面に設定

        LoadDivGraph( "画像/キャラクタ10.png" , 16 , 4 , 4 , 32 , 32 , image ) ;//キャラ画像を分割してimage配列に保存
		h_image = LoadGraph("画像/背景.png"); //背景画像をセット
		 
    while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
            //↑メッセージ処理        ↑画面をクリア         ↑キーボード入力状態取得       ↑ESCが押されると終了


        if(PlX%32==0 && PlY%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     (ch.muki==0)        //上向きならch.y座標を減らす
                    MoveY -= SPEED;
            else if(ch.muki==1)        //左向きならch.x座標を減らす
                    MoveX -= SPEED;
            else if(ch.muki==2)        //下向きならch.y座標を増やす
                    MoveY += SPEED;
            else if(ch.muki==3)        //右向きならch.x座標を増やす
                    MoveX += SPEED;
        }
 
		//自キャラの座標の代入
		charx = PlX + MoveX;
		chary = PlY + MoveY;
		//カメラ位置を計算
		camerax = charx - SCREEN_WIDTH/2;
		cameray = chary - SCREEN_HEIGHT/2;
		//左右の補正
		if( camerax < 0 ) camerax = 0;
			if( camerax > (MAP_PIXEL_WIDTH-SCREEN_WIDTH) ) camerax = (MAP_PIXEL_WIDTH-SCREEN_WIDTH);
		//上下の補正
		if( cameray < 0 ) cameray = 0;
			if( cameray > (MAP_PIXEL_HEIGHT-SCREEN_HEIGHT) ) cameray = (MAP_PIXEL_HEIGHT-SCREEN_HEIGHT);
		//画面内の位置を求める。
		view_charx = charx - camerax;
		view_chary = chary - cameray;

        ch.img=image[(view_charx%32)/8 + (view_chary%32)/8 + ch.muki*4];       //キャラ画像をセット
 
		DrawGraph(0, 0, h_image, TRUE); //背景画像を描画
		DrawGraph( view_charx , view_chary , ch.img , TRUE ) ;//キャラ画像を描画
 
        ScreenFlip();//裏画面を表画面に反映
    }
 
    DxLib_End();
    return 0;
}

以上がコードなのですが、
どのようにすればRPGの様にマップをスクロールさせることが出来るのでしょうか?

ご指導宜しくお願いします。

Re: マップのスクロールについて

Posted: 2013年9月21日(土) 16:09
by みけCAT
テストはしていませんが、
・MoveX、MoveYに加算や減算をするのではなく、直接代入する。ch.walking_flag!=1のときはMoveX=MoveY=0;とする
・無駄にcharx、charyという変数を使うのではなく、PlX、PlYの値を直接書き換え、カメラなどの位置の計算にもPlX、PlYを使う
こんな感じでしょうか?

Re: マップのスクロールについて

Posted: 2013年9月21日(土) 16:28
by みけCAT
テストしました。
・MoveX、MoveYはch.walking_flag!=1のときに限らず、速度を代入する前に0に初期化するべきのようです。
・背景の描画にもスクロールを反映した方が自然だと思います。
・操作キャラクターの画像の切り替えは、表示座標ではなく(スクロールを計算する前の)実座標で計算したほうが自然だと思います。
・負の数の剰余の仕様により、操作キャラクターがx/y座標が負の場所に行くと描画がおかしくなるので、対策をするべきです。

以上の修正をしたコードがこちらになります。

コード:

 
#include "DxLib.h"
 
#define SCREEN_WIDTH (640) // 画面の横幅
#define SCREEN_HEIGHT (480) // 画面の縦幅
#define MAP_PIXEL_WIDTH (1280)// マップの横幅
#define MAP_PIXEL_HEIGHT (480)// マップの縦幅
#define CHIP_SIZE (32) // 一つのチップのサイズ
#define MAP_WIDTH ( MAP_PIXEL_WIDTH / CHIP_SIZE) // マップの横幅
#define MAP_HEIGHT (MAP_PIXEL_HEIGHT / CHIP_SIZE) // マップの縦幅 
#define SPEED (1.0F) // キャラの移動スピード
 
typedef struct{
        int img,muki,walking_flag;
}ch_t;
 
 
int WINAPI WinMain( HINSTANCE, HINSTANCE,LPSTR, int){
        
        int image[16];
        char Key[256];
        ch_t ch;
 
        int PlX, PlY ; // プレイヤーの座標(中心座標)
        int camerax = 0, cameray = 0;//カメラの左上座標
        int charx = 0, chary = 0;//自キャラ位置
        int view_charx = 0, view_chary = 0;//自キャラの表示位置。この座標にdrawする。
        int h_image; //1280×480の背景用
        int MoveX = 0, MoveY = 0;
 
 
    if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理
 
        PlX    =320;
        PlY    =160;
        ch.walking_flag=0;
        ch.muki=3;
        
         
        SetDrawScreen( DX_SCREEN_BACK ) ; //描画先を裏画面に設定
 
        LoadDivGraph( "画像/キャラクタ10.png" , 16 , 4 , 4 , 32 , 32 , image ) ;//キャラ画像を分割してimage配列に保存
        h_image = LoadGraph("画像/背景.png"); //背景画像をセット
         
    while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
            //↑メッセージ処理        ↑画面をクリア         ↑キーボード入力状態取得       ↑ESCが押されると終了
 
 
        if(PlX%32==0 && PlY%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; //歩かないフラグを立てる
        }

        MoveX=MoveY=0; // added
        if(ch.walking_flag==1){        //歩くフラグが立っていたら
            if     (ch.muki==0)        //上向きならch.y座標を減らす
//                    MoveY -= SPEED;
                    MoveY = -SPEED;
            else if(ch.muki==1)        //左向きならch.x座標を減らす
//                    MoveX -= SPEED;
                    MoveX = -SPEED;
            else if(ch.muki==2)        //下向きならch.y座標を増やす
//                    MoveY += SPEED;
                    MoveY = SPEED;
            else if(ch.muki==3)        //右向きならch.x座標を増やす
//                    MoveX += SPEED;
                    MoveX = SPEED;
        }
 
        //自キャラの座標の代入
//        charx = PlX + MoveX;
        charx = (PlX += MoveX);
//        chary = PlY + MoveY;
        chary = (PlY += MoveY);
        //カメラ位置を計算
        camerax = charx - SCREEN_WIDTH/2;
        cameray = chary - SCREEN_HEIGHT/2;
        //左右の補正
        if( camerax < 0 ) camerax = 0;
            if( camerax > (MAP_PIXEL_WIDTH-SCREEN_WIDTH) ) camerax = (MAP_PIXEL_WIDTH-SCREEN_WIDTH);
        //上下の補正
        if( cameray < 0 ) cameray = 0;
            if( cameray > (MAP_PIXEL_HEIGHT-SCREEN_HEIGHT) ) cameray = (MAP_PIXEL_HEIGHT-SCREEN_HEIGHT);
        //画面内の位置を求める。
        view_charx = charx - camerax;
        view_chary = chary - cameray;
 
//        ch.img=image[(view_charx%32)/8 + (view_chary%32)/8 + ch.muki*4];       //キャラ画像をセット
        ch.img=image[((charx%32+32)%32)/8 + ((chary%32+32)%32)/8 + ch.muki*4];       //キャラ画像をセット
 
//        DrawGraph(0, 0, h_image, TRUE); //背景画像を描画
        DrawGraph(-camerax, -cameray, h_image, TRUE); //背景画像を描画
        DrawGraph( view_charx , view_chary , ch.img , TRUE ) ;//キャラ画像を描画
 
        ScreenFlip();//裏画面を表画面に反映
    }
 
    DxLib_End();
    return 0;
}

Re: マップのスクロールについて

Posted: 2013年9月21日(土) 16:56
by ぺぺろん
みけCAT様

ご指導いただき無事解決することができました!
またキャラ画像の切り替えについても非常に助かりました。

本当にありがとうございました。
添付いただいたファイルを参考にさせていただきもっと勉強します。

Re: マップのスクロールについて

Posted: 2013年9月21日(土) 22:11
by ISLe
過去ログには、画面の端に寄ったときにスクロールし始めるようにしたりとか、応用編のサンプルもいろいろありますよ。

Re: マップのスクロールについて

Posted: 2013年9月22日(日) 00:25
by ぺぺろん
ISLe様

情報ありがとうございます。
参考にしてみます。