2Dマップのスクロール方法について

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

トピックに返信する


答えを正確にご入力ください。答えられるかどうかでスパムボットか否かを判定します。

BBCode: ON
[img]: ON
[flash]: OFF
[url]: ON
スマイリー: OFF

トピックのレビュー
   

展開ビュー トピックのレビュー: 2Dマップのスクロール方法について

Re: 2Dマップのスクロール方法について

#2

by usao » 8年前

> 参考にしたプログラミングサイト
には,その辺りの説明が無いのでしょうか?
オフトピック
個人的な素人考えですが,
・操作キャラクターの移動 と 表示範囲の移動 とは別々に扱った方が解りやすいように思う.
・少なくとも,ゲーム内容の世界での座標(単位不明) と 表示座標(ウィンドウのクライアント領域の座標で,単位はpixelかな) との間の座標変換を
 明示的に関数にでもした方が解りやすいように思う.

2Dマップのスクロール方法について

#1

by シュヨウ » 8年前

現在、2Dアクションゲームの製作を行いたいと思っているのですが、
ゲームマップを広くして、自機の移動に合わせてマップ画面をスクロールさせるプログラムを組みたいと考えています。
当初はウィンドウ内にマップ全体が収まる形の画面スクロールの必要がないプログラムを組んでおり、
それを改良する形で現在のプログラムを組んでいます。

参考にしたプログラミングサイトのマップスクロールの説明ソースではシンプルに二色のDrawBox関数を描画していたのですが、
こちらの描画するマップ座標値とマップチップの数を求めている部分の考え方がいまいち理解しきれずにいます。
※コメントアウトして下記ソース内に「サンプルプログラム参照ソース」という名で残しています

マップチップを用いた背景の自機移動に合わせたマップスクロールさせるプログラムについて、
画像描画の座標の考え方を助言いただけないでしょうか?

何か質問の聞き方でわかりづらい部分や誤った記述部分があったら申し訳ありませんが、よろしくお願いします。

コード:

#include "DxLib.h"

#define SCREEN_WIDTH 640
#define SCREEN_HIGHT 480
#define MAP_SIZE	32			// マップチップのドットサイズ
#define MAP_WIDTH	30			// マップの幅
#define MAP_HEIGHT	25			// マップの縦長さ

//構造体_自機
struct PlayerData
{
	int X, Y,img;
} Player;

int Key[256]; // キーが押されているフレーム数を格納する
// キーの入力状態を更新する
int gpUpdateKey(){
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る
	for (int i = 0; i<256; i++){
		if (tmpKey[i] != 0){ // i番のキーコードに対応するキーが押されていたら
			Key[i]++;     // 加算
		}
		else {              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
	return 0;
}
/*
enum GameState{

	TITLE,  // タイトル画面
	MAIN,   // ゲーム本編
	CLEAR,  // クリア画面
	OVER,   // ゲームオーバー画面

}; GameState status = MAIN;
*/

int chip[8];

int Handle01;//キャラクター描画差分01
int Handle02;//キャラクター描画差分02
int Handle03;//キャラクター描画差分03
int Handle04;//キャラクター描画差分04
//ゲームクリアアイテム
int memory = 0;
int memory_num = 0;

//ステージマップ
int Map[MAP_HEIGHT][MAP_WIDTH] = {
	{ 0, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
	{ 2, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 4, 4, 2, 4, 4, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 2, 4, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 1, 4, 1, 2, 4, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 4, 4, 2, 4, 1, 1, 1, 1, 1, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 2, 4, 2, 4, 4, 4, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 1, 4, 2, 2, 2, 2, 2, 2, 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 4, 4, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 2, 4, 2, 2, 2, 2, 2, 2, 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 1, 4, 2, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 2, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 1, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2 },
	{ 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 },
};

// マップとプレイヤーとスコアの描画関数
void GraphDraw(void){
	int j, i;

	/*サンプルプログラム参照ソース
	int MapDrawPointX, MapDrawPointY;		// 描画するマップ座標値
	int DrawMapChipNumX, DrawMapChipNumY;	// 描画するマップチップの数

	// 描画するマップチップの数をセット
	DrawMapChipNumX = 640 / MAP_SIZE + 1;
	DrawMapChipNumY = 480 / MAP_SIZE + 1;

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

	// マップを描く
	for (i = 0; i < DrawMapChipNumY; i++)
	{
		for (j = 0; j < DrawMapChipNumX; j++)
		{
			// 画面からはみ出た位置なら描画しない
			if (j + MapDrawPointX < 0 || i + MapDrawPointY < 0 ||
				j + MapDrawPointX >= MAP_WIDTH || i + MapDrawPointY >= MAP_HEIGHT) continue;

			// マップデータが0だったら四角を描画する
			if (MapData[i + MapDrawPointY][j + MapDrawPointX] == 0)
			{
				DrawBox(j * MAP_SIZE, i * MAP_SIZE,
					j * MAP_SIZE + MAP_SIZE, i * MAP_SIZE + MAP_SIZE,
					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 (i = 0; i < MAP_HEIGHT; i++) {
		for (j = 0; j < MAP_WIDTH; j++) {

			DrawGraph(j * MAP_SIZE, i * MAP_SIZE, chip[Map[i][j]], FALSE);
			if (memory >= 10){
				//アイテム一定数入手で扉解放
				Map[0][29] = 7;
			}
		}
	}
	//自機描画
	DrawGraph(Player.X * MAP_SIZE, Player.Y * MAP_SIZE, Player.img, TRUE);
	//DrawRotaGraph(Player.X * MAP_SIZE + 16, Player.Y * MAP_SIZE + 16, 1.0, 0.0, player, TRUE);描画方法別パターン
}

// キーの入力移動
void gpCalc(){

	int kx = Player.X, ky = Player.Y;
	//キーの入力操作
	if (Key[KEY_INPUT_RIGHT] >= 1){ // 右キーが押されていたら
		Player.img = Handle01;
		kx++;                       // 右へ移動
	}
	if (Key[KEY_INPUT_DOWN] >= 1){ // 下キーが押されていたら
		Player.img = Handle02;
		ky++;                       // 下へ移動
	}
	if (Key[KEY_INPUT_LEFT] >= 1){ // 左キーが押されていたら
		Player.img = Handle03;
		kx--;                       // 左へ移動
	}
	if (Key[KEY_INPUT_UP] >= 1){ // 上キーが押されていたら
		Player.img = Handle04;
		ky--;                       // 上へ移動
	}

	if (Map[ky][kx] == 4 || Map[ky][kx] == 5 || Map[ky][kx] == 7) {
		Player.X = kx;
		Player.Y = ky;
		//アイテム所得
		if (Map[Player.Y][Player.X] == 5) {
			Map[Player.Y][Player.X] = 4;
			memory += 1;
		}
	}

}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
	ChangeWindowMode(TRUE);
	DxLib_Init();
	SetDrawScreen(DX_SCREEN_BACK);

	SetGraphMode(SCREEN_WIDTH, SCREEN_HIGHT, 32);

	// プレイヤーの初期位置をセット
	Player.X = 2, Player.Y = 1;

	//自機描画
	Handle01 = LoadGraph("Graphics/主人公_右.png"); // 画像をロード
	Handle02 = LoadGraph("Graphics/主人公_前.png"); // 画像をロード
	Handle03 = LoadGraph("Graphics/主人公_左.png"); // 画像をロード
	Handle04 = LoadGraph("Graphics/主人公_後.png"); // 画像をロード
	Player.img = Handle02;
	
	//マップ描画
	LoadDivGraph("Graphics/45_libraly-map.png", 8, 4, 2, 32, 32, chip);

	for (int y = 0; y < 25; y++) {
		for (int x = 0; x < 30; x++) {
			if (Map[y][x] == 4) memory_num++;
		}
	}
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdateKey() == 0){

		gpCalc();
		GraphDraw();

		ScreenFlip();
		WaitTimer(100);
	}
	DxLib_End();
	return 0;
}


ページトップ