このサイトのおかげで作り方の分からなかったゲームプログラミングに着手することができました。
ありがとうございます ^^
現在マリオ風横スクロールアクションのサンプルを作っているのですが、
プレイヤーとブロックの衝突判定がうまくいかずに困っています。
挙動がおかしいのは2箇所です。
①ブロックの斜め上から衝突すると横から進入しているのにブロックの上に乗ってしまう。
②ブロックを下から叩くとブロックのないところ(横一列に並ぶブロックの一番右側)まで移動させられる。
( 説明がヘタクソなのでアップローダーに実行ファイルとソースを添付しました。(汗) )
【key:act】
http://www1.axfc.net/uploader/He/so/252845
これらを修正するためにはどうすれば良いのでしょうか?
お力添えをお願いします。
以下が衝突判定のソースです。
================================================================================
--- Map.h ---
#define CHIP_SIZE 32 //マップチップのサイズ(キャラクター画像も32*32)
--- Charactor.h ---
#include "Map.h"
#define ACCEL_X 0.2 //X加速値
#define ACCEL_X_MAX 8.0 //X最大加速値
#define GRAVITY 0.2 //重力加速度
#define GRAVITY_MAX 10.0 //落下最大スピード
#define JAMP -6.0 //ジャンプによるY加速値
enum eDIR{//向き
eDIR_DOWN, eDIR_UP, eDIR_RIGHT, eDIR_LEFT,
};
struct rect_t{//矩形
int x,y,w,h;
};
//クラス定義
class Charactor{
int handle[16]; //画像ハンドル
int cnt; //カウンタ
double cx, cy; //座標
double vx, vy; //加速値
int dir; //向き
bool jump; //ジャンプフラグ
rect_t rect; //当たり範囲(例:cx + rect.x, cx + rect.w)
public:
void init(); //初期化
void input(); //入力処理
void collision(); //衝突処理
bool out(rect_t, int, int); //衝突判定
};
================================================================================
--- Charactor.cpp ---
//概要:初期化
void Charactor::init()
{
//キャラクターの判定領域(cx, cyから加算する値)
rect.x = 4;
rect.y = 2;
rect.w = 28;
rect.h = 32;
}
//概要:入力処理
void Charactor::input()
{
//キー入力あれこれ~~
//移動
vy += GRAVITY;
if(vy > GRAVITY_MAX) vy = GRAVITY_MAX;
cx += vx;
cy += vy;
collision(); //衝突処理
}
//概要:衝突処理
void Charactor::collision()
{
int x = ((int)cx + rect.x) / CHIP_SIZE;
int y = ((int)cy + rect.y) / CHIP_SIZE;
//座標取得
rect_t box = rect;
box.x += (int)cx; box.w += (int)cx;
box.y += (int)cy; box.h += (int)cy;
//位置補正(左右)
if(vx > 0.0){//右へ移動中
if(out(box, x+1, y)){ //壁との衝突
cx = x * CHIP_SIZE + rect.x; //位置調整
vx *= 0.0/*-0.8*/;
}
}
else{//左へ移動中
if(out(box, x, y)){ //壁との衝突
cx = (x+1) * CHIP_SIZE - rect.x; //位置調整
vx *= 0.0/*-0.8*/;
}
}
x = ((int)cx + rect.x) / CHIP_SIZE;
y = ((int)cy + rect.y) / CHIP_SIZE;
box = rect;
box.x += (int)cx; box.w += (int)cx;
box.y += (int)cy; box.h += (int)cy;
//位置補正(上下)
jump = true;
if(vy > 0.0){//下降中
if((out(box, x, y+1)) || (out(box, x+1, y+1))){ //地面と衝突
cy = (y-1) * CHIP_SIZE + rect.h; //位置調整
vy = 0.0;
jump = false;
}
}
else{//上昇中
if((out(box, x, y)) || (out(box, x+1, y))){ //天井と衝突
cy = (y+1) * CHIP_SIZE - rect.y; //位置調整
}
}
}
//概要:キャラとマップチップの衝突判定
bool Charactor::out(rect_t A, int _x, int _y)
{
if(Map::getMapChip(0, _x, _y) == 0) return(false); //マップチップが無ければ
if(Map::getMapChip(0, _x, _y) == 1){ //マップチップが壁なら
//マップチップ座標取得
rect_t B;
B.x = _x * CHIP_SIZE; B.y = _y * CHIP_SIZE;
B.w = B.x + CHIP_SIZE; B.h = B.y + CHIP_SIZE;
//矩形同士の当たり判定
if((A.x < B.w) && (B.x < A.w) && (A.y < B.h) && (B.y < A.h)){
return(true);
}
}
return(false);
}