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");
}
}