マップスクロールをきれいにループできない

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

マップスクロールをきれいにループできない

#1

投稿記事 by leaf8429 » 10年前

いつもお世話になっております。
今回もいまいちうまくできないところがありますので,アドバイスをいただきたいと思います。
他の方による似たような質問が存在しますが,それとは別の問題と思われます)
マップスクロールのループを実装したかったので,このプログラム
を改変したのですが,
マップスクロール自体はループするのですが,右と下は滑らかに動くのに対し,
左と上に動かした場合は画面の左端および上端が「カクカクッ」といった感じの動きをしてしまいます。
ウィンドウ外の部分も描画するようにすれば良いのでしょうか?
(x:1~15,y:1~11をウィンドウに表示するとして,x:0~16,y:0~12を描画するようにする感じです)
先週に引き続いて質問をしてすみませんが,アドバイスをいただけるとありがたいです。
どうかよろしくお願いいたします。

ソース:(後でC#用に書き直します。)

コード:

#include "DxLib.h"

#define MAP_SIZE	48			// マップチップ一つのドットサイズ

#define MAP_WIDTH	20			// マップの幅
#define MAP_HEIGHT	16			// マップの縦長さ

#define MOVE_FRAME	6			// 移動にかけるフレーム数

// マップのデータ
int MapData[ MAP_HEIGHT ][ MAP_WIDTH ] =
{
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ,  0, 1, 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 } ,
	{ 0, 0, 1, 1, 1, 0, 0, 0, 0, 0 ,  1, 1, 0, 0, 0, 0, 0, 0, 1, 0 } ,
	{ 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 ,  1, 1, 1, 1, 1, 1, 0, 0, 1, 0 } ,
	{ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0 ,  0, 1, 0, 0, 0, 1, 0, 0, 1, 0 } ,
	{ 0, 1, 0, 0, 1, 0, 0, 1, 1, 0 ,  0, 1, 1, 1, 1, 1, 1, 0, 1, 0 } ,
	{ 0, 1, 0, 0, 1, 0, 0, 1, 1, 0 ,  0, 1, 1, 0, 0, 1, 1, 0, 1, 0 } ,
	{ 0, 1, 0, 0, 1, 0, 0, 1, 1, 0 ,  0, 1, 1, 0, 0, 1, 1, 0, 1, 0 } ,

	{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 ,  0, 1, 1, 0, 0, 1, 1, 0, 1, 0 } ,
	{ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0 ,  0, 1, 1, 0, 0, 1, 1, 0, 1, 0 } ,
	{ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0 ,  0, 1, 1, 0, 0, 1, 1, 0, 1, 0 } ,
	{ 0, 0, 0, 1, 1, 0, 0, 1, 0, 0 ,  0, 1, 1, 0, 0, 1, 1, 0, 1, 0 } ,
	{ 0, 1, 1, 1, 1, 0, 0, 1, 1, 1 ,  1, 1, 1, 0, 0, 1, 1, 0, 1, 0 } ,
	{ 0, 1, 1, 1, 1, 0, 0, 0, 0, 0 ,  0, 1, 0, 0, 0, 0, 0, 0, 1, 0 } ,
	{ 0, 1, 1, 1, 1, 0, 0, 0, 0, 1 ,  1, 1, 1, 1, 1, 1, 1, 1, 1, 0 } ,
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ,  0, 1, 0, 0, 0, 0, 0, 0, 0, 0 } ,
} ;
int View[13][17]={
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
};
// プレイヤーの位置
int PlayerX , PlayerY ;
int X=7,Y=5; //
bool loop=true;
// 移動しているかどうかのフラグ( 0:停止中  1:移動中 )
int Move ;

// 各方向に移動する量
int MoveX, MoveY ;

// 移動し始めてから何フレーム経過したかを保持する変数
int MoveCounter ;

// マップとプレイヤーの描画関数
void GraphDraw( int ScrollX, int ScrollY )
{
	int j , i ;
	int MapDrawPointX , MapDrawPointY ;		// 描画するマップ座標値
	int DrawMapChipNumX , DrawMapChipNumY ;	// 描画するマップチップの数

	// 描画するマップチップの数をセット
	DrawMapChipNumX = 17 ;
	DrawMapChipNumY = 13 ;

	// 画面左上に描画するマップ座標をセット
	MapDrawPointX = PlayerX - ( DrawMapChipNumX / 2 - 1 ) ;
	MapDrawPointY = PlayerY - ( DrawMapChipNumY / 2 - 1 ) ;

	// マップを描く
	for( i = -1 ; i < 12 ; i ++ ){
		for( j =-1 ; j < 16 ; j ++ ){
			// 画面からはみ出た位置なら描画しない
			// マップデータが0だったら四角を描画する
			if( View[i][j] == 0 ){
				DrawBox(j * MAP_SIZE + ScrollX,i * MAP_SIZE + ScrollY,
					j * MAP_SIZE + MAP_SIZE + ScrollX,	i * MAP_SIZE + MAP_SIZE + ScrollY,
					GetColor( 255 , 0 , 0 ) , TRUE ) ; 
			}
		}
	}

	// プレイヤーの描画
	DrawBox( ( PlayerX - MapDrawPointX ) * MAP_SIZE , ( PlayerY - MapDrawPointY ) * MAP_SIZE ,
		 ( PlayerX - MapDrawPointX + 1 ) * MAP_SIZE , ( PlayerY - MapDrawPointY + 1 ) * MAP_SIZE ,
			 GetColor( 255 , 255 , 255 ) , TRUE ) ;
	for(int b=0;b<13;b++){
		for(int a=0;a<17;a++){  View[b][a]=MapData[(PlayerY+MAP_HEIGHT+(b-5))%MAP_HEIGHT][(PlayerX+MAP_WIDTH+(a-7))%MAP_WIDTH];
		DrawFormatString(23+a*48,23+b*48,GetColor(0,255,255), "%d", View[b][a]);}
	}
}

// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
						 LPSTR lpCmdLine, int nCmdShow )
{
	int Key ;
	int a,b;
	int ScrollX, ScrollY ;

	SetGraphMode( 720 ,524, 16 ) ;
	ChangeWindowMode(TRUE);
	if( DxLib_Init() == -1 )	// DXライブラリ初期化処理
	{
		 return -1;				// エラーが起きたら直ちに終了
	}

	// 描画先画面を裏画面にする
	SetDrawScreen( DX_SCREEN_BACK ) ;

	// プレイヤーの初期位置をセット
	PlayerX = 2 ;
	PlayerY = 2 ;

	// 最初は停止中(0)にしておく
	Move = 0 ;
	for(b=0;b<11;b++){
		for(a=0;a<=15;a++){  View[b][a]=MapData[(PlayerY+MAP_HEIGHT+(b-5))%MAP_HEIGHT][(PlayerY+MAP_WIDTH+(a-7))%MAP_WIDTH];
		DrawFormatString(a*64,b*64,GetColor(0,0,255), "[%d]", View[b][a]);}
	}
	// ループ
	while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
	{
		// 画面を初期化
		ClearDrawScreen() ;

		// 移動中ではない場合キー入力を受け付ける
		if( Move == 0 ){
			// キー入力を得る
			Key = GetJoypadInputState( DX_INPUT_KEY_PAD1 ) ;

			// キー入力に応じてプレイヤーの座標を移動
			if( Key & PAD_INPUT_LEFT ) {  Move = 1 ; MoveX = -1 ; MoveY =  0 ; }
			if( Key & PAD_INPUT_RIGHT ){  Move = 1 ; MoveX =  1 ; MoveY =  0 ; }
			if( Key & PAD_INPUT_UP )   {  Move = 1 ; MoveX =  0 ; MoveY = -1 ; }
			if( Key & PAD_INPUT_DOWN ) {  Move = 1 ; MoveX =  0 ; MoveY =  1 ; }

			// 進入不可能なマップだった場合は移動できない
			if( Move == 1 ){
				if( View[ 5 + MoveY ][ 7+ MoveX ] == 0 ){Move = 0 ; }
				else{ MoveCounter = 0 ;}
			}

			// 停止中は画面のスクロールは行わない
			ScrollX = 0 ;
			ScrollY = 0 ;
		}

		// 移動中の場合は移動処理を行う
		if( Move == 1 ){
			MoveCounter ++ ;

			// 移動処理が終了したら停止中にする
			if( MoveCounter == MOVE_FRAME )
			{
				Move = 0 ;

				// プレイヤーの位置を変更する
				PlayerX =(PlayerX+(MAP_WIDTH+MoveX))% MAP_WIDTH ;
				PlayerY =(PlayerY+(MAP_HEIGHT+MoveY))% MAP_HEIGHT ;

				// 停止中は画面のスクロールは行わない
				ScrollX = 0 ;
				ScrollY = 0 ;
			}
			else
			{
				// 経過時間からスクロール量を算出する
				ScrollX = -( MoveX * MAP_SIZE * MoveCounter / MOVE_FRAME ) ;
				ScrollY = -( MoveY * MAP_SIZE * MoveCounter / MOVE_FRAME ) ;
			}
		}
		//ウィンドウ
	for(b=0;b<11;b++){
		for(a=0;a<=15;a++){  View[b][a]=MapData[(PlayerY+MAP_HEIGHT+(b-5))%MAP_HEIGHT][(PlayerX+MAP_WIDTH+(a-7))%MAP_WIDTH]; }
	}
		// マップとプレイヤーを描画
		GraphDraw( ScrollX, ScrollY ) ;

		// 裏画面の内容を表画面に映す
		ScreenFlip() ;
	}

	DxLib_End() ;				// DXライブラリ使用の終了処理

	return 0 ;					// ソフトの終了
}

leaf8429

自己解決しました。

#2

投稿記事 by leaf8429 » 10年前

以前投稿した人です。

書き込みをした後でもとにしたサンプルプログラムから作り直しをしたら,ちゃんとスクロールがループするようになりました。
添付したプログラムに間違いが結構ありました。

コード:

    for(b=0;b<11;b++){
        for(a=0;a<=15;a++){  
             View[b][a]=MapData[(PlayerY+MAP_HEIGHT+(b-5))%MAP_HEIGHT][(PlayerX+MAP_WIDTH+(a-7))%MAP_WIDTH];
        }
    }
(3か所)を,

コード:

 	for(a=0;a<13;a++){
		for(b=0;b<17;b++){
                      View[a][b]=MapData[(PlayerY+(a-6+MAP_HEIGHT))%MAP_HEIGHT][(PlayerX+(b-8+MAP_WIDTH))%MAP_WIDTH];
		}
	}
に,

コード:

    DrawMapChipNumX = 17 ;
    DrawMapChipNumY = 13 ;
を,

コード:

	DrawMapChipNumX = 720 / MAP_SIZE + 2 ;
	DrawMapChipNumY = 528 / MAP_SIZE + 2 ;
にしたらきれいに動くようになりました。(ウィンドウサイズも間違っていました)

自分のコードの間違いに気づかずに質問をしてしまい,お騒がせいたしました。失礼しました。

閉鎖

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