マリオ風アクションゲームのブロックとの当たり判定

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

マリオ風アクションゲームのブロックとの当たり判定

#1

投稿記事 by KEYONN_ » 15年前

ネットカフェから書き込みです。
マリオ風横スクロールアクションゲームをC/C++で作成中なのですが、
ブロックとの当たり判定で思ったようにプレイヤーキャラが壁やブロックで止まらなかったり、
プレイヤーの位置が急に変わったりして困っています。
誰か助けてください。
当たり判定部分のソースを載せます。

typedef struct HITBG{
int x;
int y;
int width;
int height;
int kind;
}HITBG;

class CBG{
public:

HITBG HBG[14][16];

//void CBG::HitCheck()メンバ関数、引数にはプレイヤーキャラを入れる
void HitCheck(int &x,int &y,int width,int height)
{
int i,j;

for(i=0;i<14;i++)
{
for(j=0;j<16;j++)
{
if(HBG[j].kind!=5)//背景番号5番は空
{
if(y+height>=HBG[j].y &&
y<=HBG[j].y+32)//チップは32ドット
{
if(x+width>=HBG[j].x &&
x+width<=HBG[j].x)
{
//左に接触
x=HBG[j].x+width;
}
if(x<=HBG[j].x+32 &&
x>=HBG[j].x+32)
{
//右に接触
x=HBG[j].x;
}
if(x+width>=HBG[j].x &&
x<=HBG[i][j].x+32)
{
if(y+height>=HBG[i][j].y &&
y+height<HBG[i][j].y)
{
//下
y=HBG[i][j].y+height;
}
if(y>=HBG[i][j].y+32 &&
y<HBG[i][j].y+32)
{
//上
y=HBG[i][j].y-32;
if(HBG[i][j].kind==2)
{

}

}
}

}
}
}
}
}
};

CBG BG;

void Init()//DxLib_Init()後に呼ぶ関数
{
//省略
int i,j;

for(i=0;i<14;i++)
{
for(j=0;j<16;j++)
{
BG.HBG[i][j].kind=BGTbl[i][j];
BG.HBG[i][j].x=j*32;
BG.HBG[i][j].y=i*32;
BG.HBG[i][j].width=32;
BG.HBG[i][j].height=32;
}
}
} 画像

kazuoni

Re:マリオ風アクションゲームのブロックとの当たり判定

#2

投稿記事 by kazuoni » 15年前

一番は、実行できる環境を用意する事かと思いますが・・・

パッと見た感じですが

if(y+height>=HBG[j].y && y<=HBG[j].y+32)//チップは32ドット

if(y+height>=HBG[j].y && y+height<=HBG[j].y+32)//チップは32ドット

if(x+width>=HBG[j].x && x<=HBG[j].x+32)

if(x+width>=HBG[j].x && x+width<=HBG[j].x+32)


あと、
if(HBG[j].kind==2){
}

となっていますが、この条件の時は何もしなくていいのでしょうか?

ただ、コメントが最小限なので、なんとも言えないかと思います。

KEYONN_

Re:マリオ風アクションゲームのブロックとの当たり判定

#3

投稿記事 by KEYONN_ » 15年前

ソースと画像ファイルの入った圧縮ファイルをアップロードします。
どうか、よろしくお願いします。

KEYONN_

Re:マリオ風アクションゲームのブロックとの当たり判定

#4

投稿記事 by KEYONN_ » 15年前

>あと、
>if(HBG[j].kind==2){
>}
>となっていますが、この条件の時は何もしなくていいのでしょうか?
コインかハテナブロックの判定です。
まだ実装してません。
あと、背景の画像の関係でマップチップ番号を全体で+1しました。

KEYONN_

Re:マリオ風アクションゲームのブロックとの当たり判定

#5

投稿記事 by KEYONN_ » 15年前

//その1です

#include"DxLib.h"

#define CHIP_SIZE 32

enum object{DOKAN};

int ScrollX;
int ScrollY;
int BGTbl[14][16]={
5,5,5,5, 5,5,5,5, 5,5,5,5, 5,5,5,5,
5,5,5,5, 5,5,5,5, 5,5,5,5, 5,5,5,5,
5,5,5,5, 5,5,5,5, 5,5,5,5, 5,5,5,5,
5,5,5,5, 5,5,5,5, 5,5,5,5, 5,5,5,5,
5,5,5,5, 5,5,5,5, 5,5,5,5, 5,5,5,5,
5,5,5,5, 5,5,5,5, 5,5,5,5, 5,5,5,5,
5,5,5,5, 5,5,5,5, 5,5,5,5, 5,5,5,5,

5,5,5,5, 5,5,5,5, 5,5,5,5, 5,5,5,5,
5,5,5,5, 5,1,1,5, 5,5,5,5, 5,5,5,5,
1,1,5,1, 1,5,5,1, 1,1,1,1, 1,2,1,1,
5,5,5,5, 5,5,5,5, 5,5,5,5, 5,5,5,5,
5,5,5,5, 5,5,5,5, 5,5,5,5, 5,5,5,5,
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
};

typedef struct HITBG{
int x;
int y;
int width;
int height;
int kind;
}HITBG;

class CBG{
public:

//配列BGデータ
int num;
//BG番号
HITBG HBG[14][16];
int objectnum;
//オブジェクト番号

int table[16*14];
CBG()
{

}
~CBG()
{
//特になし
}
void DrawChip(int num,int x,int y)
{
DrawGraph(x,y,table[ num ],TRUE);
}
void DrawBG_Object(int x,int y,int objectnum)
{

}
void DrawBG()
{
int StartX=ScrollX/32,StartY=ScrollY/32;
int EndX=(ScrollX+512-1)/32,EndY=(ScrollY+448-1)/32;

for(int i=StartY;i<=EndY;i++)
{
for(int j=StartX;j<=EndX;j++)
{
DrawChip(BGTbl[j],j*32-ScrollX,i*32-ScrollY);

}
}
}
void HitCheck(int &x,int &y,int width,int height)
{
int i,j;

for(i=0;i<14;i++)
{
for(j=0;j<16;j++)
{
if(HBG[j].kind!=6)
{
if(y+height>=HBG[j].y &&
y+height<=HBG[j].y+32)
{
/*
if(x+width>=HBG[j].x &&
x+width<=HBG[j].x)
{
//左に接触
x=HBG[j].x+width;
}
if(x<=HBG[j].x+32 &&
x>=HBG[j].x+32)
{
//右に接触
x=HBG[j].x-32;
}
*/
if(x+width>=HBG[i][j].x &&
x+width<=HBG[i][j].x+32)
{
if(y+height>=HBG[i][j].y &&
y+height<HBG[i][j].y)
{
//下
y=HBG[i][j].y+height;
}
if(y>=HBG[i][j].y+32 &&
y<HBG[i][j].y+32)
{
//上
y=HBG[i][j].y-32;
if(HBG[i][j].kind==2)
{

}

}
}

}
}
}
}
}
};

CBG BG;

class Character{
public:
int GraphHandle;
float x,y;
int width,height;
void Show()
{
DrawGraph(x,y,GraphHandle,TRUE);
}
Character()
{
//特になし
}
Character(char str[/url])
{
GraphHandle=LoadGraph(str);
}
~Character()
{
//特になし
}
};

enum Dir{RIGHT,LEFT,UP,DOWN};
enum Kind{SMALL,BIG,FIRE};

KEYONN_

Re:マリオ風アクションゲームのブロックとの当たり判定

#6

投稿記事 by KEYONN_ » 15年前

//その2です。
class Mario : public Character{
public:
unsigned char kisuu;
bool muki;
int joutai;
int vx,vy;
unsigned char hosuu;
void Show()
{

hosuu=hosuu%2;
switch(joutai)
{
case SMALL:
DrawRectGraph(x,y,
hosuu*32, 0, 32, 32,
GraphHandle, TRUE, muki*1 ) ;

break;
case BIG:
DrawRectGraph(x,y,
0,32,64,64,
GraphHandle ,TRUE,muki*1);
break;
case FIRE:
DrawRectGraph(x,y,
0,64,64,64,
GraphHandle ,TRUE,muki*1);
break;
}
}
void Jump()
{
static bool jump=false;
float jump_speed = vx==2 ? -14.0: -20.0;
float jump_kasoku=1.0f;
float groundy=448-96;
float speed=0.2f;
if(!jump)
{

if(CheckHitKey(KEY_INPUT_X)){
jump=true;
vy=jump_speed;
}

}else{
vy+=jump_kasoku;
y+=vy;

if(vy>0 && y>=groundy){
jump=false;
y=groundy;
}

if(vy<0 && !CheckHitKey(KEY_INPUT_X)){
vy=0;
}
}

if(x<0) x=0;
if(x>512-1)x=512-1;

}
void SayuuMove()
{
if(CheckHitKey(KEY_INPUT_RIGHT))
{
if(CheckHitKey(KEY_INPUT_Z))
{
vx=5;
}else{
vx=2;
}
AutoMove(RIGHT,vx);
muki=RIGHT;
hosuu++;
}
if(CheckHitKey(KEY_INPUT_LEFT))
{
if(CheckHitKey(KEY_INPUT_Z))
{
vx=5;
}else{
vx=2;
}
AutoMove(LEFT,vx);
muki=LEFT;
hosuu++;
}
if(!CheckHitKey(KEY_INPUT_RIGHT) && !CheckHitKey(KEY_INPUT_LEFT))
{
hosuu=0;
}
}
void AutoMove(int muki,int speed)
{
switch(muki)
{
case RIGHT:
x+=speed;
break;
case LEFT:
x-=speed;
break;
case UP:
y-=speed;
break;
case DOWN:
y+=speed;
break;
}
}
Mario()
{
kisuu=3;
muki=RIGHT;
joutai=SMALL;
x=(512-32)/2;
y=448-96;
hosuu=0;
vx=2;
vy=0;
}
};

Mario P;

void Init()
{
P.GraphHandle=LoadGraph("./mario.png");
ScrollX=0;
ScrollY=0;
LoadDivGraph( "./BG.png" , 16*14 ,
16 , 14 ,
32 , 32 , BG.table ) ;

int i,j;

for(i=0;i<14;i++)
{
for(j=0;j<16;j++)
{
BGTbl[j]=BGTbl[j]+1;
BG.HBG[j].kind=BGTbl[j];
BG.HBG[j].x=j*32;
BG.HBG[j].y=i*32;
BG.HBG[j].width=32;
BG.HBG[j].height=32;
}
}
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hP,LPSTR lpC,int nC)
{

SetGraphMode(512,448,32);
ChangeWindowMode(TRUE) ;
SetMainWindowText("SuperMarioBrothers"); //ウィンドウのタイトル
if(DxLib_Init() == -1) return (-1); //DXライブラリ初期化

//データ読み込み中と表示する
DrawString( 0 , 0 , "データ読み込み中" , GetColor(255,255,255) );

//各種変数の初期化など
Init();
//乱数の初期化
srand((unsigned)GetTickCount());
//メインループ
while( ProcessMessage()==0 && CheckHitKey(KEY_INPUT_ESCAPE)==0){

ProcessMessage();
ClsDrawScreen(); //画面を初期化

BG.DrawBG();
P.SayuuMove();
P.Jump();
int a,b;
a=(int)P.x;
b=(int)P.y;
BG.HitCheck(a,b,32,32);
P.x=a;
P.y=b;
P.Show();

//DrawFormatString(0,40,GetColor(255,255,255),"angle=%f",angle);
//DrawFormatString(0,60,GetColor(255,255,255),"angle2=%f",angle2);

ScreenFlip(); //フリップする
}

DxLib_End(); //DXライブラリ終了処理
return (0); //終了
}

KEYONN_

Re:マリオ風アクションゲームのブロックとの当たり判定

#7

投稿記事 by KEYONN_ » 15年前

ネットカフェから書き込みです。
誰か分かる方いたら、よろしくお願いします。

wing

Re:マリオ風アクションゲームのブロックとの当たり判定

#8

投稿記事 by wing » 15年前

私は初心者なので適切なことは言えないですが、
ざっと見たところ、常にすべてのブロックのx、y座標で
当たり判定をしようとしているようですが、もっと
簡単でいいんじゃないでしょうか。

つまり、当たり判定専用の1と0のマップを作って、
キャラのX+vxがマップの1だったらvx=0とかです。

プログラミングのスタイルも違うし、HBGって何の略だらう
なんて考えるとサンプルを作るのが億劫になるので、
とりあえず、DXライブラリ置き場のサンプルプログラムの
「アクションゲームにおけるマップとの当たり判定基本」
を参考にしたらどうでしょうか。

あと過去のログにも似たような質問がたくさんあります。

KEYONN_

Re:マリオ風アクションゲームのブロックとの当たり判定

#9

投稿記事 by KEYONN_ » 15年前

ありがとうございます。wingさん、
解決しました。
下記のページを参考にしました。
http://hakuhin.jp/as/block.html#BLOCK_05t=

閉鎖

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