アクションゲームにおけるマップについて

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

アクションゲームにおけるマップについて

#1

投稿記事 by さいとうもきち » 12年前

はじめまして。
DXライブラリで横スクロールアクションゲームを作成しています。
今のところ、一つのマップを二次元配列で定義し、そのマップとプレイヤーとの当たり判定まで実装出来ました。

今後マップを増やすとしたら、マップクラスを設計するほうがよいのかなと考えています。
しかし、具体的にどのようにマップクラスを設計すればよいのか分からずに困っています。
クラスについては、まだ初歩的なことを学習したばかりです。

以下に作成したコードを示します。

コード:

#include"DxLib.h"

#define WIDTH 640
#define HEIGHT 480
#define SIZE 32

/*******************
プレイヤークラス
*******************/
class Player{

private:
	int x;				//x座標
	int y;				//y座標
	int w;				//当たり判定の横幅を決定するパラメータ
	int h;				//当たり判定の縦幅を決定するパラメータ
	int offsetX;		//描画オフセット
	double dx;			//x座標の変化
	double dy;			//y座標の変化
	bool dir;			//向き
	bool accele;		//加速状態
	bool jump;			//ジャンプ状態

public:
	Player();			//コンストラクタ
	void Update();		//更新処理(仮)
	void Direction();	//方向決定処理
	void Accel();		//加速処理
	void Jump();		//ジャンプ処理
	void Fall();		//落下処理
	void Draw();		//描画処理
	void Show_Data();	//データ表示

	void Hit_Left_X();	//左側衝突時の処理
	void Hit_Right_X();	//右側衝突時の処理
	void Hit_Top_Y();	//上側衝突時の処理
	void Hit_Bottom_Y();//下側衝突時の処理

	int get_X(){return x;}							//x座標の値を取得
	int get_Y(){return y;}							//y座標の値を取得
	int get_Left_X(){return (x+w)/SIZE;}			//左側当たり判定のx座標を取得
	int get_Right_X(){return (x+SIZE-w-1)/SIZE;}	//右側当たり判定のx座標を取得
	int get_Top_Y(){return (y+h)/SIZE;}				//上側当たり判定のy座標を取得
	int get_Bottom_Y(){return (y+SIZE-h-1)/SIZE;}	//下側当たり判定のy座標を取得
	int get_Offset_X(){return offsetX;}
};

/*******************
キー入力状態を調べる
*******************/
static int Key_State[256];
void Keyboard_Update(){
	char Key[256];	
	GetHitKeyStateAll(Key);
	for(int i=0; i<256; i++){
		if(Key[i] != 0){
			Key_State[i]++;
		}
		else{
			Key_State[i] = 0;
		}
	}
}

/*******************
キー入力状態を返す
*******************/
int Keyboard_Get(int KeyCode){
	
	return Key_State[KeyCode];
}

/*******************
メイン関数
*******************/
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
	ChangeWindowMode(TRUE);
	SetWindowText("テスト中");
	DxLib_Init();
	SetDrawScreen(DX_SCREEN_BACK);

	//マップデータ
	int mapData[HEIGHT/SIZE][WIDTH/SIZE+4] = {
		{1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1},
		{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1},
		{1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1},
		{1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1},
		{1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
		{1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
		{1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1},
		{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1},
		{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1},
		{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1},
		{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1},
		{1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
		{1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 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, 1, 1, 1, 1},
	};

	//インスタンス生成
	Player player;

	/*********ここからメインループ*********/
	while(ProcessMessage()==0){

		Keyboard_Update();	
		player.Direction();	//方向決定処理
		player.Accel();		//加速処理

		//左側衝突時の処理
		if(mapData[player.get_Top_Y()][player.get_Left_X()]==1 || mapData[player.get_Bottom_Y()][player.get_Left_X()]==1){
			player.Hit_Left_X();
			DrawFormatString(0, 16*6, GetColor(255, 150, 0), "左側衝突");
		}

		//右側衝突時の処理
		if(mapData[player.get_Top_Y()][player.get_Right_X()]==1 || mapData[player.get_Bottom_Y()][player.get_Right_X()]==1){
			player.Hit_Right_X();
			DrawFormatString(0, 16*7, GetColor(255, 150, 0), "右側衝突");
		}

		player.Jump();	//ジャンプ処理

		//上側衝突時の処理
		if(mapData[player.get_Top_Y()][player.get_Left_X()]==1 || mapData[player.get_Top_Y()][player.get_Right_X()]==1){
			player.Hit_Top_Y();
			DrawFormatString(0, 16*8, GetColor(255, 150, 0), "上側衝突");
		}

		//下側衝突時の処理
		if(mapData[player.get_Bottom_Y()][player.get_Left_X()]==1 || mapData[player.get_Bottom_Y()][player.get_Right_X()]==1){
			player.Hit_Bottom_Y();
			DrawFormatString(0, 16*9, GetColor(255, 150, 0), "下側衝突");
		}

		/*描画処理*/
		for(int i=0; i<WIDTH/SIZE+4; i++){
			for(int j=0; j<HEIGHT/SIZE; j++){

				//ブロックの描画
				if(mapData[j][i]==1){
					
					//画面左端での描画
					if(player.get_Offset_X()<0){
						DrawBox(i*SIZE, j*SIZE, (i+1)*SIZE, (j+1)*SIZE, GetColor(50, 50, 50), FALSE);
					}

					//スクロール中の描画
					else{
						DrawBox(i*SIZE-player.get_Offset_X(), j*SIZE, (i+1)*SIZE-player.get_Offset_X(), (j+1)*SIZE, GetColor(50, 50, 50), FALSE);
					}
				}
			}
		}

		//プレイヤーの描画
		player.Draw();

		//プレイヤーデータ表示
		player.Show_Data();

		ScreenFlip();
		ClearDrawScreen();
	}
	/*********ここまでメインループ*********/
	
	DxLib_End();
	return 0;
}

/*******************
プレイヤーの初期化
*******************/
Player::Player(){
	x =5*32;
	y = 32*8;
	w = 8;
	h = 4;
	offsetX = x-WIDTH/2;
	dx = 0.0;
	dy = 0.0;
	dir = TRUE;
	accele = FALSE;
	jump = FALSE;
}

/*******************
プレイヤーの更新(仮)
*******************/
void Player::Update(){
}

/*******************
プレイヤーの方向
*******************/
void Player::Direction(){

	//右向き状態
	if(Keyboard_Get(KEY_INPUT_RIGHT)){
		dir = TRUE;
	}

	//左向き状態
	else if(Keyboard_Get(KEY_INPUT_LEFT)){
		dir = FALSE;
	}
}


/*******************
プレイヤーの加速
*******************/
void Player::Accel(){
	
	accele=FALSE;
	
	//右方向へ加速している状態
	if(Keyboard_Get(KEY_INPUT_RIGHT)){
		accele=TRUE;
		dx+=0.5;
		if(dx>=5.0){
			dx=5.0;
		}
	}

	//左方向への加速している状態
	else if(Keyboard_Get(KEY_INPUT_LEFT)){
		accele=TRUE;
		dx-=0.5;
		if(dx<=-5.0){
			dx=-5.0;
		}
	}
	
	//加速してない状態
	if(!accele){
		if(dir){
			dx-=0.2;
			if(dx<0){
				dx=0;
			}
		}
		else{
			dx+=0.2;
			if(dx>0){
				dx=0;
			}
		}
	}

	//座標更新
	x+=(int)dx;
	offsetX = x-WIDTH/2;
}

/*******************
プレイヤーのジャンプ
*******************/
void Player::Jump(){

	dy--;
	if(dy<=-20){
		dy=-20;
	}

	//ジャンプ状態
	if(!jump && Keyboard_Get(KEY_INPUT_Z)==1){
		dy=15.0;
		jump = TRUE;
	}

	//座標更新
	y-=(int)dy;
}

/***********************
プレイヤー左側衝突時の処理
***********************/
void Player::Hit_Left_X(){
	x=(x/SIZE+1)*SIZE-w;
	dx=0;
}							

/***********************
プレイヤー右側衝突時の処理
***********************/
void Player::Hit_Right_X(){
	x=(x/SIZE+1)*SIZE-SIZE+w;
	dx=0;
}

/***********************
プレイヤー上側衝突時の処理
***********************/
void Player::Hit_Top_Y(){
	y=(y/SIZE+1)*SIZE-h;
	dy=0;
}

/***********************
プレイヤー下側衝突時の処理
***********************/
void Player::Hit_Bottom_Y(){
	y=((y+SIZE+1)/SIZE)*SIZE-SIZE+h;
	dy=0;
	jump=FALSE;
}

/*******************
プレイヤーの描画
*******************/
void Player::Draw(){

	//画面左端での描画
	if(offsetX<0){
		DrawBox(x+w, y+h, x+SIZE-w, y+SIZE-h, GetColor(155, 0, 0), FALSE);
		DrawBox(x, y, x+SIZE, y+SIZE, GetColor(0, 155, 0), FALSE);
	}

	//スクロール中の描画
	else{
		DrawBox(x-offsetX+w, y+h, x-offsetX+SIZE-w, y+SIZE-h, GetColor(155, 0, 0), FALSE);
		DrawBox(x-offsetX, y, x-offsetX+SIZE, y+SIZE, GetColor(0, 155, 0), FALSE);
	}

}

/*******************
プレイヤーのデータ表示
*******************/
void Player::Show_Data(){
	DrawFormatString(0, 16*0, GetColor(0, 255, 255), "(x, y):(%d, %d)", x, y);
	DrawFormatString(0, 16*1, GetColor(0, 155, 255), "dx:%f", dx);
	DrawFormatString(0, 16*2, GetColor(0, 155, 255), "dy:%f", dy);
	DrawFormatString(0, 16*3, GetColor(0, 255, 155), "offsetX:%d", offsetX);

	if(accele){
		DrawFormatString(0, 16*4, GetColor(255, 0, 0), "accele");
	}
	else{
		DrawFormatString(0, 16*4, GetColor(55, 0, 0), "accele");
	}

	if(jump){
		DrawFormatString(0, 16*5, GetColor(255, 0, 255), "jump");
	}
	else{
		DrawFormatString(0, 16*5, GetColor(55, 0, 55), "jump");
	}
}
どうかアドバイスをよろしくお願いいたします。

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

Re: アクションゲームにおけるマップについて

#2

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

やたらpublicな関数があるのが気になりますが、一旦置いておいて。
マップもプレーヤー同様にクラスを作ります。最終的にはマップはファイルから読み込むほうが良いでしょう。
初期化、ロード、位置の更新、当たり判定、描画、終了の関数があれば良いんじゃないでしょうか。
呼び出しはPlayer同様にWinMainから呼ぶのがよろしいかと。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

さいとうもきち

Re: アクションゲームにおけるマップについて

#3

投稿記事 by さいとうもきち » 12年前

回答ありがとうございます。

クラス、というよりC言語についてまだまだ分からない点が数多くありますが、試行錯誤しつつ少しずつ慣れていきたいと思います。
今後も稚拙な質問を投稿することがあるかと思いますが、どうかよろしくお願いいたします。

閉鎖

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