アクションゲームのマップとキャラクターの当たり判定について

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

アクションゲームのマップとキャラクターの当たり判定について

#1

投稿記事 by 野口 » 11年前

プログラムを勉強しており、少しづつかけるようになってきたので、
アクションゲームを作ろうとしております。
(イメージとしてはチャリ走などのシンプルなものです)

また今回はビット演算がよくわからないので、
当たり判定をビット演算で実装しようと考えております。

マップの自動生成っぽいもの+スクロール処理はできたのですが
キャラクターの移動系の処理が壊滅的にできません・・・。
色々と試してみたのですが、何かができると何かがダメになったりしてしまいました・・・。

①当たり判定をリセット
②ジャンプ判定
③移動
④当たり判定(あたっていたら前の座標に戻す)
⑤前の座標を保存

みたいな処理をしております。
こちらだと、当たり判定が来た1フレームずれる?感じになってしまうのと
地面とあたっても引きづられたりしてしまいます。

宜しければで構いませんのでアドバイスなど頂けないでしょうか。

コード:

// マップ関連
#define MAP_SIZE    32
#define MAP_WIDTH   20
#define MAP_HEIGHT  8
#define TABLE_MAX   3

#define CHARACTER_WIDTH     32
#define CHARACTER_HEIGHT    32

// 当たり判定用
#define DIR_NONE    0x0000
#define DIR_UP      0x0001
#define DIR_DOWN    0x0002
#define DIR_RIGHT   0x0004
#define DIR_LEFT    0x0008
#define DIR_SOME    0x0016  // どれかに当たったら

typedef struct{
    float Scroll[2];
    TIMER Time;
}OBJECT_GAME;

static OBJECT_GAME Obj;

// レベルデザイン用
typedef struct{
    int Time;
    int Pattern[LEVEL_DESIGN_PATTERN_MAX];
}LEVEL_DESIGN;

// レベルデザイン用
static LEVEL_DESIGN Level[LEVEL_DESIGN_MAX] = {
    
    { 60*0,     { 0,1,2,2,0 } },
    { 60*40,    { 1,2,0,2,1 } },
    { 60*120,    { 0,0,0,0,0 } },
    { 60*130,    { 0,0,0,0,0 } },
    { 60*140,    { 0,0,0,0,0 } }
    
};

static int tblMapMaster[TABLE_MAX][MAP_HEIGHT][MAP_WIDTH] = {
    
    // MAP_1
    {

        { 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,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,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,0,0,0,0 },
        { 1,1,1,0,0, 0,0,0,1,1, 1,1,1,0,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,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 }
        
    },
    
    // MAP_2
    {
        
        { 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,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,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,0,0,0,0 },
        { 2,1,1,0,0, 0,0,0,1,1, 1,1,1,0,0, 0,0,0,1,1 },
        { 2,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
        { 2,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 }
        
    },
 
    
    // MAP_3
    {

        { 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,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,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },
        
        { 3,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },
        { 3,1,1,0,0, 0,0,0,1,1, 1,1,1,0,0, 0,0,0,1,1 },
        { 3,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
        { 3,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 }
        
    }
    
};

static int tblMap[2][MAP_HEIGHT][MAP_WIDTH];

class PLAYER{
public:

    bool Flag;
    float Px, Py, Dx, Dy, Ox, Oy;
    unsigned int Dir;
    
    void Init();
    void Loop();
    void HitCheck( float scroll[] );

};

void PLAYER::Init(){
    
    this->Dir = DIR_NONE;
    this->Flag = false;
    this->Px = 0.0f;
    this->Py = 0.0f;
    this->Dx = 0.0f;
    this->Dy = 3.0f;
    this->Ox = 0.0f;
    this->Oy = 0.0f;

}

void PLAYER::Loop(){
    
    //this->Dx = 0;
    //this->Dy = 0;
    this->Dir = DIR_NONE;

    if( System.touch.trgFlag ){
        this->Dy = -8.0f;
    }
    
    this->Dy += 0.22f;
    //if( this->Dy <= 0.0f ) this->Dy = 0.0f;
    
    // 移動場所
    this->Px += this->Dx;
    this->Py += this->Dy;
    
    // 当たり判定
    this->HitCheck( Obj.Scroll );
    
    // 下方向が当たってたら
    if( ( this->Dir & DIR_DOWN ) ){
        this->Dy = 0.0f;
        this->Py = this->Oy;
    }
    
    // 右方向
    //Log( @"%d", ( this->Dir & DIR_RIGHT ) );
    if( ( this->Dir & DIR_RIGHT ) ){
        Log( @"くるときがある" );
        //this->Dx = -3.0f;
    }else{
        this->Dx = 0.0f;
    }
    
    // 前のフレームを保存
    if( !( this->Dir & DIR_RIGHT ) || !( this->Dir & DIR_LEFT ) ) this->Ox = this->Px;
    if( !( this->Dir & DIR_DOWN ) || !( this->Dir & DIR_UP ) ) this->Oy = this->Py;
    

    /*
    // 右方向が当たってたら
    if( ( this->Dir & DIR_RIGHT ) ){
        this->Px -= 3;
    }
    */
    
    
    
    
    if( this->Py >= 960 ) this->Py = 200;
    if( this->Px <= 0 ) this->Px = 400;
    
    /*
    this->Dir = this->Dir | DIR_LEFT;
    if( System.touch.trgFlag ) this->Dir = this->Dir | DIR_UP;
    */
    
}

void PLAYER::HitCheck( float scroll[] ){

    for(int y=0; y<MAP_HEIGHT; y++){
        for(int x=0; x<MAP_WIDTH; x++){
            
            for(int tbl=0; tbl<2; tbl++){

                int px1 = ( x*MAP_SIZE ) + ( MAP_SIZE/2 ) + scroll[tbl];
                int py1 = ( y*MAP_SIZE ) + ( MAP_SIZE/2 );
                
                int diff = 10;
                
                if( tblMap[tbl][y][x] == 1 || tblMap[tbl][y][x] == 2 || tblMap[tbl][y][x] == 3 ){
                    
                    // 何かに当たってる
                    if( this->Px-CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py-CHARACTER_HEIGHT/2 < py1+MAP_SIZE/2 && this->Py+CHARACTER_HEIGHT/2 > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_SOME;
                    }
                    
                    // キャラクターから下方向が当たってる
                    if( this->Px-CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py+CHARACTER_HEIGHT/2 < py1+MAP_SIZE/2 && this->Py+CHARACTER_HEIGHT/2 > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_DOWN;
                    }
                    
                    // キャラクターから上方向が当たってる
                    if( this->Px-CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py-CHARACTER_HEIGHT/2 < py1+MAP_SIZE/2 && this->Py-CHARACTER_HEIGHT/2 > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_UP;
                    }
                    
                    // キャラクターから右方向が当たってる
                    if( this->Px+CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py-CHARACTER_HEIGHT/2+diff < py1+MAP_SIZE/2 && this->Py+CHARACTER_HEIGHT/2-diff > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_RIGHT;
                        this->Dx = -3.0f;
                        NSLog( @"aaa" );
                    }
                    
                    // キャラクターから左方向が当たってる
                    if( this->Px-CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px-CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py-CHARACTER_HEIGHT/2+diff < py1+MAP_SIZE/2 && this->Py+CHARACTER_HEIGHT/2-diff > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_LEFT;
                    }

                }
                
            }
        }
    }

}


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

Re: アクションゲームのマップとキャラクターの当たり判定について

#2

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

コードの全容がないので試せないのですが、scrollの果たしている役割が良く分かりません。
それとこのコードはC++/CLIで.NetFrameWork用でしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

野口

Re: アクションゲームのマップとキャラクターの当たり判定について

#3

投稿記事 by 野口 » 11年前

大変失礼しました!
Mac上でopenGLを勉強しており、c++でコードを書いております。
同じサイズの配列が二つあり、横に並べて表示しております。
スクロールの値はそれの表示をずらすためようになります。

画面端まで行ったら値を戻すという処理を別部分でしております。

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

Re: アクションゲームのマップとキャラクターの当たり判定について

#4

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

当たり判定でスクロール値は必要ないと思います。
スクロール値は表示の時だけで良いのではないでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

野口

Re: アクションゲームのマップとキャラクターの当たり判定について

#5

投稿記事 by 野口 » 11年前

何度もご回答ありがとうございます!
関係しております全ソースを添付させて頂きますね。
Loop()とDraw()をゲーム中60フレームまわしております。

描画で座標をずらしており、あたり判定を行う際に
スクロールの値が必要かと思っておりました。

キャラクターが各方向の壁に当たった時は以下のようにしたいと考えております。
(○キャラ ■壁)

○■ → 画面左に引きづられる


■ → 落ちないようにする


○  → 頭をぶつけたかんじ

■○ → それ以上左に食い込まないようにする。

わかりにくくてすみません・・・。イメージ的にはこんな感じです。

コード:


// マップ関連
#define MAP_SIZE    32
#define MAP_WIDTH   20
#define MAP_HEIGHT  8
#define TABLE_MAX   3

#define CHARACTER_WIDTH     32
#define CHARACTER_HEIGHT    32

#define LEVEL_DESIGN_MAX 5
#define LEVEL_DESIGN_PATTERN_MAX 5

// 当たり判定用
#define DIR_NONE    0x0000
#define DIR_UP      0x0001
#define DIR_DOWN    0x0002
#define DIR_RIGHT   0x0004
#define DIR_LEFT    0x0008
#define DIR_SOME    0x0016  // どれかに当たったら

typedef struct{
    float Scroll[2];
    TIMER Time;
}OBJECT_GAME;

static OBJECT_GAME Obj;

// レベルデザイン用
typedef struct{
    int Time;
    int Pattern[LEVEL_DESIGN_PATTERN_MAX];
}LEVEL_DESIGN;

// レベルデザイン用
static LEVEL_DESIGN Level[LEVEL_DESIGN_MAX] = {
    
    { 60*0,     { 0,1,2,2,0 } },
    { 60*40,    { 1,2,0,2,1 } },
    { 60*120,    { 0,0,0,0,0 } },
    { 60*130,    { 0,0,0,0,0 } },
    { 60*140,    { 0,0,0,0,0 } }
    
};

static int tblMapMaster[TABLE_MAX][MAP_HEIGHT][MAP_WIDTH] = {
    
    // MAP_1
    {

        { 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,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,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,0,0,0,0 },
        { 1,1,1,0,0, 0,0,0,1,1, 1,1,1,0,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,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 }
        
    },
    
    // MAP_2
    {
        
        { 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,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,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,0,0,0,0 },
        { 2,1,1,0,0, 0,0,0,1,1, 1,1,1,0,0, 0,0,0,1,1 },
        { 2,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
        { 2,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 }
        
    },
 
    
    // MAP_3
    {

        { 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,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,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },
        
        { 3,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },
        { 3,1,1,0,0, 0,0,0,1,1, 1,1,1,0,0, 0,0,0,1,1 },
        { 3,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
        { 3,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 }
        
    }
    
};

static int tblMap[2][MAP_HEIGHT][MAP_WIDTH];

int GetLebel( int time ){
    
    int level = 0;

    for(int i=0; i<LEVEL_DESIGN_MAX; i++){
        if( time >= Level[i].Time ) level = i;
    }
    
    return level;

};

class PLAYER{
public:

    bool Flag;
    float Px, Py, Dx, Dy, Ox, Oy;
    unsigned int Dir;
    
    void Init();
    void Loop();
    void HitCheck( float scroll[] );

};

void PLAYER::Init(){
    
    this->Dir = DIR_NONE;
    this->Flag = false;
    this->Px = 0.0f;
    this->Py = 0.0f;
    this->Dx = 0.0f;
    this->Dy = 3.0f;
    this->Ox = 0.0f;
    this->Oy = 0.0f;

}

void PLAYER::Loop(){
    
    //this->Dx = 0;
    //this->Dy = 0;
    this->Dir = DIR_NONE;

    if( System.touch.trgFlag ){
        this->Dy = -8.0f;
    }
    
    this->Dy += 0.22f;
    //if( this->Dy <= 0.0f ) this->Dy = 0.0f;
    
    // 移動場所
    this->Px += this->Dx;
    this->Py += this->Dy;
    
    // 当たり判定
    this->HitCheck( Obj.Scroll );
    
    // 下方向が当たってたら
    if( ( this->Dir & DIR_DOWN ) ){
        this->Dy = 0.0f;
        this->Py = this->Oy;
    }
    
    // 右方向
    //NSLog( @"%d", ( this->Dir & DIR_RIGHT ) );
    if( ( this->Dir & DIR_RIGHT ) ){
        NSLog( @"こないでー" );
        //this->Dx = -3.0f;
    }else{
        this->Dx = 0.0f;
    }
    
    // 前のフレームを保存
    if( !( this->Dir & DIR_RIGHT ) || !( this->Dir & DIR_LEFT ) ) this->Ox = this->Px;
    if( !( this->Dir & DIR_DOWN ) || !( this->Dir & DIR_UP ) ) this->Oy = this->Py;
    

    /*
    // 右方向が当たってたら
    if( ( this->Dir & DIR_RIGHT ) ){
        this->Px -= 3;
    }
    */
    
    
    
    
    if( this->Py >= 960 ) this->Py = 200;
    if( this->Px <= 0 ) this->Px = 400;
    
    /*
    this->Dir = this->Dir | DIR_LEFT;
    if( System.touch.trgFlag ) this->Dir = this->Dir | DIR_UP;

    NSLog( @"%d %d %d", ( this->Dir & DIR_RIGHT ), ( this->Dir & DIR_LEFT ), ( this->Dir & DIR_UP ) );
    */
    
}

/*
 bool MENU::TouchCheck( void ){
 
 int x = System.touchPos.x;
 int y = System.touchPos.y;
 
 int sx = ( this->Width * this->SizeX ) / 2;
 int sy = ( this->Height * this->SizeY ) / 2;
 
 if(x < this->Px+sx && x > this->Px-sx &&
 y < this->Py+sy && y > this->Py-sy ){
 return true;
 }else{
 return false;
 }
 
 }

 */

void PLAYER::HitCheck( float scroll[] ){

    for(int y=0; y<MAP_HEIGHT; y++){
        for(int x=0; x<MAP_WIDTH; x++){
            
            for(int tbl=0; tbl<2; tbl++){

                int px1 = ( x*MAP_SIZE ) + ( MAP_SIZE/2 ) + scroll[tbl];
                int py1 = ( y*MAP_SIZE ) + ( MAP_SIZE/2 );
                
                int diff = 10;
                
                if( tblMap[tbl][y][x] == 1 || tblMap[tbl][y][x] == 2 || tblMap[tbl][y][x] == 3 ){
                    
                    // 何かに当たってる
                    if( this->Px-CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py-CHARACTER_HEIGHT/2 < py1+MAP_SIZE/2 && this->Py+CHARACTER_HEIGHT/2 > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_SOME;
                    }
                    
                    // キャラクターから下方向が当たってる
                    if( this->Px-CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py+CHARACTER_HEIGHT/2 < py1+MAP_SIZE/2 && this->Py+CHARACTER_HEIGHT/2 > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_DOWN;
                    }
                    
                    // キャラクターから上方向が当たってる
                    if( this->Px-CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py-CHARACTER_HEIGHT/2 < py1+MAP_SIZE/2 && this->Py-CHARACTER_HEIGHT/2 > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_UP;
                    }
                    
                    // キャラクターから右方向が当たってる
                    if( this->Px+CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py-CHARACTER_HEIGHT/2+diff < py1+MAP_SIZE/2 && this->Py+CHARACTER_HEIGHT/2-diff > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_RIGHT;
                        this->Dx = -3.0f;
                        NSLog( @"aaa" );
                    }
                    
                    // キャラクターから左方向が当たってる
                    if( this->Px-CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px-CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py-CHARACTER_HEIGHT/2+diff < py1+MAP_SIZE/2 && this->Py+CHARACTER_HEIGHT/2-diff > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_LEFT;
                    }

                }
                
                /*
                if( col != 0xffffff ){
                    DrawBoxCenter( px, py, MAP_SIZE, MAP_SIZE, col, 255 );
                }
                */
                
            }
        }
    }

}



/*
class MAP{
public:
    int tblMapMaster[TABLE_MAX][MAP_HEIGHT][MAP_WIDTH];
    int tblMap[2][MAP_HEIGHT][MAP_WIDTH];
    
    void Init();
    void InitMap( int num, int tbl[] );
};
*/

// マップの初期化
void InitMap( int num, int ptn ){
    
    // エラー処理
    if( num != 0 && num != 1 ) return;
    if( ptn < 0 || ptn >= TABLE_MAX ) return;
    
    for(int y=0; y<MAP_HEIGHT; y++){
        for(int x=0; x<MAP_WIDTH; x++){
            tblMap[num][y][x] = tblMapMaster[ptn][y][x];
        }
    }

}

static PLAYER Play;

static void Init(){
    
    // 変数の初期化
    Obj.Scroll[0] = 0.0f;
    Obj.Scroll[1] = 640.0f;
    
    // タイマー関連
    Obj.Time.Init( TIMER_FRAME );
    Obj.Time.Start();
    //Obj.Time.LogFlag = true;
    
    // マップの初期化
    InitMap( 0, 0 );
    InitMap( 1, 1 );
    
    // プレイヤーの初期化
    Play.Init();
    Play.Px = 100;
    Play.Py = 200;

}

static void Loop(){
    
    // タイマー
    Obj.Time.Loop();
    
    int level = GetLebel( Obj.Time.Frame );
    //NSLog( @"%d", level );
    
    // スクロール処理
    Obj.Scroll[0] -= 3.0f;
    Obj.Scroll[1] -= 3.0f;
    
    if( Obj.Scroll[0] <= -640.0f ){
        int r = rand() % LEVEL_DESIGN_PATTERN_MAX;
        int ptn = Level[level].Pattern[r];
        InitMap( 0, ptn );
        Obj.Scroll[0] = Obj.Scroll[1] + 640.0f;
    }
    if( Obj.Scroll[1] <= -640.0f ){
        int r = rand() % LEVEL_DESIGN_PATTERN_MAX;
        int ptn = Level[level].Pattern[r];
        InitMap( 1, ptn );
        Obj.Scroll[1] = Obj.Scroll[0] + 640.0f;
    }
    
    // プレイヤーのループ
    Play.Loop();
    
    //if( Obj.Scroll[0] )

}

static void Draw(){
    
    // 背景の表示
    DrawTexture( 320, 480, texBack, 0, 0, 640, 960, 0xffffff, 255 );
    
    // マップの描画
    for(int y=0; y<MAP_HEIGHT; y++){
        for(int x=0; x<MAP_WIDTH; x++){
 
            int px = ( x*MAP_SIZE ) + ( MAP_SIZE/2 );
            int py = ( y*MAP_SIZE ) + ( MAP_SIZE/2 ) +500;
            
            for(int tbl=0; tbl<2; tbl++){
                
                int col = 0xffffff;
                if( tblMap[tbl][y][x] == 1 ) col = 0x000000;
                if( tblMap[tbl][y][x] == 2 ) col = 0xff0000;
                if( tblMap[tbl][y][x] == 3 ) col = 0x00ff00;
                
                if( col != 0xffffff ){
                    DrawBoxCenter( px+Obj.Scroll[tbl], py, MAP_SIZE, MAP_SIZE, col, 255 );
                }
                
            }
        }
    }
    
    DrawBoxCenter( Play.Px, Play.Py +500, CHARACTER_WIDTH, CHARACTER_HEIGHT, 0xffffff, 255 );
    
}


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

Re: アクションゲームのマップとキャラクターの当たり判定について

#6

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

後ほど試してみてお返事したいと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: アクションゲームのマップとキャラクターの当たり判定について

#7

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

このままのコードだと動かないので問題の確認が困難な状況です。
キャラ位置(this->Px,this->Py)は画面内の座標で、スクロール値を足さないと本当のマップ上の位置を表わさないとまでは把握出来ました。
今のところ1フレーム遅れる理由は不明です。

あと、これも良く分かりません。
○■ → 画面左に引きづられる → 何がどのような条件で引きずられるかも書いてください。
■○ → それ以上左に食い込まないようにする。 → 何が食い込むのでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: アクションゲームのマップとキャラクターの当たり判定について

#8

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

よく見たらNSLog( @"aaa" );とあるのでiPhoneですね。
私の所でMacがないので動作確認不能です。
動作確認しないレベルでの話になりますので、よろしくお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
Tatu
記事: 445
登録日時: 15年前
住所: 北海道

Re: アクションゲームのマップとキャラクターの当たり判定について

#9

投稿記事 by Tatu » 11年前

x,y座標両方を動かした後に
壁、床、天井を一気に判定するのではなく、

x座標を移動して壁の判定、
その後にy座標を移動して床や天井の判定をする
というように分けてはどうでしょうか。

野口

Re: アクションゲームのマップとキャラクターの当たり判定について

#10

投稿記事 by 野口 » 11年前

アドバイスありがとうございます!
同じ環境がない中、ソースを見て下さり助かります。

DXライブラリで動くサンプル版を作ってみました。
キャストなどしていないので警告が出てしまって申し訳ないです。

下記に添付させて頂きます。

http://www.dotup.org/uploda/www.dotup.o ... 9.zip.html
pass:123

なるほど・・・判定を一緒にやってるのが原因かもしれないのですね。
ちょっと弄ってみます!

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

Re: アクションゲームのマップとキャラクターの当たり判定について

#11

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

当たり判定を可視化してみました。
描画位置と判定位置が食い違っている様に見えます。
あわててやったので、間違いがあったらすいません。

コード:

#include <math.h>
#include "DxLib.h"
#include "Main.h"

#define MAP_SIZE    32
#define MAP_WIDTH   20
#define MAP_HEIGHT  8
#define TABLE_MAX   3
 
#define CHARACTER_WIDTH     32
#define CHARACTER_HEIGHT    32
 
#define LEVEL_DESIGN_MAX 5
#define LEVEL_DESIGN_PATTERN_MAX 5
 
// 当たり判定用
#define DIR_NONE    0x0000
#define DIR_UP      0x0001
#define DIR_DOWN    0x0002
#define DIR_RIGHT   0x0004
#define DIR_LEFT    0x0008
#define DIR_SOME    0x0016  // どれかに当たったら
 
typedef struct{
    float Scroll[2];
}OBJECT_GAME;

static OBJECT_GAME Obj;
 
// レベルデザイン用
typedef struct{
    int Time;
    int Pattern[LEVEL_DESIGN_PATTERN_MAX];
}LEVEL_DESIGN;
 
// レベルデザイン用
static LEVEL_DESIGN Level[LEVEL_DESIGN_MAX] = {
    
    { 60*0,     { 0,1,2,2,0 } },
    { 60*40,    { 1,2,0,2,1 } },
    { 60*120,    { 0,0,0,0,0 } },
    { 60*130,    { 0,0,0,0,0 } },
    { 60*140,    { 0,0,0,0,0 } }
    
};
 
static int tblMapMaster[TABLE_MAX][MAP_HEIGHT][MAP_WIDTH] = {
    
    // MAP_1
    {
 
        { 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,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,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,0,0,0,0 },
        { 1,1,1,0,0, 0,0,0,1,1, 1,1,1,0,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,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 }
        
    },
    
    // MAP_2
    {
        
        { 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,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,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,0,0,0,0 },
        { 2,1,1,0,0, 0,0,0,1,1, 1,1,1,0,0, 0,0,0,1,1 },
        { 2,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
        { 2,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 }
        
    },
 
    
    // MAP_3
    {
 
        { 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,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,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },
        
        { 3,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },
        { 3,1,1,0,0, 0,0,0,1,1, 1,1,1,0,0, 0,0,0,1,1 },
        { 3,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
        { 3,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 }
        
    }
    
};
 
static int tblMap[2][MAP_HEIGHT][MAP_WIDTH];
 
int GetLebel( int time ){
    
    int level = 0;
 
    for(int i=0; i<LEVEL_DESIGN_MAX; i++){
        if( time >= Level[i].Time ) level = i;
    }
    
    return level;
 
};
 
class PLAYER{
public:
 
    bool Flag;
    float Px, Py, Dx, Dy, Ox, Oy;
    unsigned int Dir;
    
    void Init();
    void Loop();
    void HitCheck( float scroll[] );
 
};


int bHit = 0;
int hitx1,hity1,hitx2,hity2;
void setHit( int x1,int y1,int x2,int y2 )
{
	bHit = 1;
	hitx1 = x1;
	hity1 = y1;
	hitx2 = x2;
	hity2 = y2;
}


void PLAYER::Init(){
    
    this->Dir = DIR_NONE;
    this->Flag = false;
    this->Px = 0.0f;
    this->Py = 0.0f;
    this->Dx = 0.0f;
    this->Dy = 3.0f;
    this->Ox = 0.0f;
    this->Oy = 0.0f;
 
}
 
void PLAYER::Loop(){
    
    //this->Dx = 0;
    //this->Dy = 0;
    this->Dir = DIR_NONE;
 
	if( Key[KEY_INPUT_RETURN].trgKey ){
        this->Dy = -8.0f;
    }
    
    this->Dy += 0.22f;
    //if( this->Dy <= 0.0f ) this->Dy = 0.0f;
    
    // 移動場所
    this->Px += this->Dx;
    this->Py += this->Dy;
    
    // 当たり判定
    this->HitCheck( Obj.Scroll );
    
    // 下方向が当たってたら
    if( ( this->Dir & DIR_DOWN ) ){
        this->Dy = 0.0f;
        this->Py = this->Oy;
    }
    
    // 右方向
    //NSLog( @"%d", ( this->Dir & DIR_RIGHT ) );
    if( ( this->Dir & DIR_RIGHT ) ){
        //this->Dx = -3.0f;
    }else{
        this->Dx = 0.0f;
    }
    
    // 前のフレームを保存
    if( !( this->Dir & DIR_RIGHT ) || !( this->Dir & DIR_LEFT ) ) this->Ox = this->Px;
    if( !( this->Dir & DIR_DOWN ) || !( this->Dir & DIR_UP ) ) this->Oy = this->Py;
    
 
    /*
    // 右方向が当たってたら
    if( ( this->Dir & DIR_RIGHT ) ){
        this->Px -= 3;
    }
	*/
    
    
    
    if( this->Py >= 960 ) this->Py = 200;
    if( this->Px <= 0 ) this->Px = 400;
    
    /*
    this->Dir = this->Dir | DIR_LEFT;
    if( System.touch.trgFlag ) this->Dir = this->Dir | DIR_UP;
 
    NSLog( @"%d %d %d", ( this->Dir & DIR_RIGHT ), ( this->Dir & DIR_LEFT ), ( this->Dir & DIR_UP ) );
    */
    
}
 
/*
 bool MENU::TouchCheck( void ){
 
 int x = System.touchPos.x;
 int y = System.touchPos.y;
 
 int sx = ( this->Width * this->SizeX ) / 2;
 int sy = ( this->Height * this->SizeY ) / 2;
 
 if(x < this->Px+sx && x > this->Px-sx &&
 y < this->Py+sy && y > this->Py-sy ){
 return true;
 }else{
 return false;
 }
 
 }
 
 */
 
void PLAYER::HitCheck( float scroll[] ){
 	
 	bHit = 0;
    for(int y=0; y<MAP_HEIGHT; y++){
        for(int x=0; x<MAP_WIDTH; x++){
            
            for(int tbl=0; tbl<2; tbl++){
 
                int px1 = ( x*MAP_SIZE ) + ( MAP_SIZE/2 ) + scroll[tbl];
                int py1 = ( y*MAP_SIZE ) + ( MAP_SIZE/2 );
                
                int diff = 10;
                
                if( tblMap[tbl][y][x] == 1 || tblMap[tbl][y][x] == 2 || tblMap[tbl][y][x] == 3 ){
                    
                    // 何かに当たってる
                    if( this->Px-CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py-CHARACTER_HEIGHT/2 < py1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_SOME;
                        setHit( this->Px-CHARACTER_WIDTH/2, this->Py-CHARACTER_HEIGHT/2, this->Px+CHARACTER_WIDTH/2, this->Py+CHARACTER_HEIGHT/2);
                    }
                    
                    // キャラクターから下方向が当たってる
                    if( this->Px-CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py+CHARACTER_HEIGHT/2 < py1+MAP_SIZE/2 && this->Py+CHARACTER_HEIGHT/2 > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_DOWN;
                        setHit( this->Px-CHARACTER_WIDTH/2, this->Py-CHARACTER_HEIGHT/2, this->Px+CHARACTER_WIDTH/2, this->Py+CHARACTER_HEIGHT/2);
                    }
                    
                    // キャラクターから上方向が当たってる
                    if( this->Px-CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py-CHARACTER_HEIGHT/2 < py1+MAP_SIZE/2 && this->Py-CHARACTER_HEIGHT/2 > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_UP;
                        setHit( this->Px-CHARACTER_WIDTH/2, this->Py-CHARACTER_HEIGHT/2, this->Px+CHARACTER_WIDTH/2, this->Py+CHARACTER_HEIGHT/2);
                    }
                    
                    // キャラクターから右方向が当たってる
                    if( this->Px+CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py-CHARACTER_HEIGHT/2+diff < py1+MAP_SIZE/2 && this->Py+CHARACTER_HEIGHT/2-diff > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_RIGHT;
                        this->Dx = -3.0f;
                        setHit( this->Px-CHARACTER_WIDTH/2, this->Py-CHARACTER_HEIGHT/2+diff, this->Px+CHARACTER_WIDTH/2, this->Py+CHARACTER_HEIGHT/2-diff);
                    }
                    
                    // キャラクターから左方向が当たってる
                    if( this->Px-CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px-CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py-CHARACTER_HEIGHT/2+diff < py1+MAP_SIZE/2 && this->Py+CHARACTER_HEIGHT/2-diff > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_LEFT;
                        setHit( this->Px-CHARACTER_WIDTH/2, this->Py-CHARACTER_HEIGHT/2+diff, this->Px+CHARACTER_WIDTH/2, this->Py+CHARACTER_HEIGHT/2-diff);
                    }
 
                }
                
                /*
                if( col != 0xffffff ){
                    DrawBoxCenter( px, py, MAP_SIZE, MAP_SIZE, col, 255 );
                }
                */
                
            }
        }
    }
 
}
 
 
 
/*
class MAP{
public:
    int tblMapMaster[TABLE_MAX][MAP_HEIGHT][MAP_WIDTH];
    int tblMap[2][MAP_HEIGHT][MAP_WIDTH];
    
    void Init();
    void InitMap( int num, int tbl[] );
};
*/
 
// マップの初期化
void InitMap( int num, int ptn ){
    
    // エラー処理
    if( num != 0 && num != 1 ) return;
    if( ptn < 0 || ptn >= TABLE_MAX ) return;
    
    for(int y=0; y<MAP_HEIGHT; y++){
        for(int x=0; x<MAP_WIDTH; x++){
            tblMap[num][y][x] = tblMapMaster[ptn][y][x];
        }
    }
 
}
 
static PLAYER Play;



static void Init(){

   // 変数の初期化
    Obj.Scroll[0] = 0.0f;
    Obj.Scroll[1] = 640.0f;
    
    // タイマー関連
    //Obj.Time.Init( TIMER_FRAME );
    //Obj.Time.Start();
    //Obj.Time.LogFlag = true;
    
    // マップの初期化
    InitMap( 0, 0 );
    InitMap( 1, 1 );
    
    // プレイヤーの初期化
    Play.Init();
    Play.Px = 100;
    Play.Py = 200;

} 

static void Loop(){

	int level = GetLebel( 0 );
    
	//NSLog( @"%d", level );
    
    // スクロール処理
    Obj.Scroll[0] -= 3.0f;
    Obj.Scroll[1] -= 3.0f;
    
    if( Obj.Scroll[0] <= -640.0f ){
        int r = rand() % LEVEL_DESIGN_PATTERN_MAX;
        int ptn = Level[level].Pattern[r];
        InitMap( 0, ptn );
        Obj.Scroll[0] = Obj.Scroll[1] + 640.0f;
    }
    if( Obj.Scroll[1] <= -640.0f ){
        int r = rand() % LEVEL_DESIGN_PATTERN_MAX;
        int ptn = Level[level].Pattern[r];
        InitMap( 1, ptn );
        Obj.Scroll[1] = Obj.Scroll[0] + 640.0f;
    }
    
    // プレイヤーのループ
    Play.Loop();
    
}

static void Draw(){


	DrawBox( 0, 0, 640, 960,  GetColor( 50,50,50 ), true );

	// マップの描画
    for(int y=0; y<MAP_HEIGHT; y++){
        for(int x=0; x<MAP_WIDTH; x++){
 
            int px = ( x*MAP_SIZE ) + ( MAP_SIZE/2 );
            int py = ( y*MAP_SIZE ) + ( MAP_SIZE/2 );
            
            for(int tbl=0; tbl<2; tbl++){
                
                int col = 0xffffff;
                if( tblMap[tbl][y][x] == 1 ) col = GetColor( 0,0,0 );
                if( tblMap[tbl][y][x] == 2 ) col = GetColor( 255,0,0 );
                if( tblMap[tbl][y][x] == 3 ) col = GetColor( 0,255,0 );
                col = GetColor( 0,0,0 );

				if( tblMap[tbl][y][x] != 0 ){
					DrawBox( px+Obj.Scroll[tbl], py,  px+Obj.Scroll[tbl]+MAP_SIZE, py+MAP_SIZE, col, true );
                } 
                //DrawBox( Obj.Scroll[tbl], 0,  100, 100, col, true );
                //if( col != 0xffffff ){
                //}
                
            }
        }
    }
    
    DrawBox( Play.Px, Play.Py, Play.Px+CHARACTER_WIDTH, Play.Py+CHARACTER_HEIGHT, GetColor( 255,255,255 ), true );
    
    if( bHit ) {
		DrawBox( hitx1,hity1 ,hitx2,hity2, GetColor( 255,0,0 ), false );
	}

}

static void Finish(){
	// 描画が終ったのでグラフィックをメモリ上から削除する
	 InitGraph();
	 InitFontToHandle();
}

const SceneFunc *GetSceneFunc_Game(){ 
    static const SceneFunc func = { &Init, &Loop, &Draw, &Finish }; 
    return &func; 
} 
//////////////////////////////////////////////////
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

野口

Re: アクションゲームのマップとキャラクターの当たり判定について

#12

投稿記事 by 野口 » 11年前

遅くなってしまい申し訳御座いません。
回答+ソースまで修正ありがとうございます!!

Xcode上だと描画を中心原点で、DXLib上では左上原点で
やってしまっているので、私の処理が若干変な動作しているかもしれません(汗)

今日一日、考えてみて少し近い所まで来たのですが、
自動的に辺り判定を取ってしまったり、埋まってしまったりと不具合が御座います。

右の壁と当たっているとジャンプができなかったりもします。
細かい不備を見てみたいのでスクロールをキー操作に切り替えております。

ここまでアクションゲームって難しいのですね・・・。
作れる人、尊敬します。。。

コード:

#include <math.h>
#include "DxLib.h"
#include "Main.h"

#pragma warning(disable:4244)

#define MAP_SIZE    32
#define MAP_WIDTH   20
#define MAP_HEIGHT  8
#define TABLE_MAX   3
 
#define CHARACTER_WIDTH     32
#define CHARACTER_HEIGHT    32
 
#define LEVEL_DESIGN_MAX 5
#define LEVEL_DESIGN_PATTERN_MAX 5
 
// 当たり判定用
#define DIR_NONE    0x0000
#define DIR_UP      0x0001
#define DIR_DOWN    0x0002
#define DIR_RIGHT   0x0004
#define DIR_LEFT    0x0008
#define DIR_SOME    0x0016  // どれかに当たったら
 
typedef struct{
    float Scroll[2];
}OBJECT_GAME;
 
static OBJECT_GAME Obj;
 
// レベルデザイン用
typedef struct{
    int Time;
    int Pattern[LEVEL_DESIGN_PATTERN_MAX];
}LEVEL_DESIGN;
 
// レベルデザイン用
static LEVEL_DESIGN Level[LEVEL_DESIGN_MAX] = {
    
    { 60*0,     { 0,1,2,2,0 } },
    { 60*40,    { 1,2,0,2,1 } },
    { 60*120,    { 0,0,0,0,0 } },
    { 60*130,    { 0,0,0,0,0 } },
    { 60*140,    { 0,0,0,0,0 } }
    
};
 
static int tblMapMaster[TABLE_MAX][MAP_HEIGHT][MAP_WIDTH] = {
    
    // MAP_1
    {
 
        { 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, 1,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,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, 0,0,0,0,0, 0,0,0,0,0 },
        { 1,1,1,0,0, 0,0,0,1,1, 1,1,1,0,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,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 }
        
    },
    
    // MAP_2
    {
        
        { 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,1,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,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,0,0,0,0, 0,0,0,0,0 },
        { 2,1,1,0,0, 0,0,0,1,1, 1,1,1,0,0, 0,0,0,1,1 },
        { 2,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
        { 2,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 }
        
    },
 
    
    // MAP_3
    {
 
        { 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,0,0,0, 0,0,0,0,0 },
        { 0,0,0,0,0, 0,0,0,0,0, 0,1,0,0,0, 0,0,0,0,0 },
        { 0,0,0,0,0, 0,1,0,0,0, 1,1,0,0,0, 0,0,0,0,0 },
        
        { 3,0,0,0,0, 0,0,0,0,1, 1,1,0,0,0, 0,0,0,0,0 },
        { 3,1,1,0,0, 0,0,0,1,1, 1,1,1,0,0, 0,0,0,1,1 },
        { 3,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
        { 3,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 }
        
    }
    
};
 
static int tblMap[2][MAP_HEIGHT][MAP_WIDTH];
 
int GetLebel( int time ){
    
    int level = 0;
 
    for(int i=0; i<LEVEL_DESIGN_MAX; i++){
        if( time >= Level[i].Time ) level = i;
    }
    
    return level;
 
};
 
class PLAYER{
public:
 
    bool Flag;
    float Px, Py, Dx, Dy, Ox, Oy;
    unsigned int Dir;
    
    void Init();
    void Loop();
    void HitCheck( float scroll[] );
 
};
 
 
int bHit = 0;
int hitx1,hity1,hitx2,hity2;
void setHit( int x1,int y1,int x2,int y2 )
{
    bHit = 1;
    hitx1 = x1;
    hity1 = y1;
    hitx2 = x2;
    hity2 = y2;
}
 
 
void PLAYER::Init(){
    
    this->Dir = DIR_NONE;
    this->Flag = false;
    this->Px = 0.0f;
    this->Py = 0.0f;
    this->Dx = 0.0f;
    this->Dy = 0.0f;
    this->Ox = 0.0f;
    this->Oy = 0.0f;
 
}
 
void PLAYER::Loop(){
    
    // 前のフレームを保存
	this->Ox = this->Px;
	this->Oy = this->Py;

	this->Dx = 0;
    //this->Dy = 0;
    this->Dir = DIR_NONE;
 
	if( Key[KEY_INPUT_SPACE].trgKey ){
        this->Dy = -8.0f;
    }
    
    this->Dy += 0.2f;
    //if( this->Dy <= 0.0f ) this->Dy = 0.0f;

	// 移動場所
    this->Px += this->Dx;
    this->Py += this->Dy;
    
    // 当たり判定
    this->HitCheck( Obj.Scroll );

    // 下方向が当たってたら
    if( ( this->Dir & DIR_DOWN ) ){
        this->Dy = 0.0f;
        this->Py = this->Oy;
    }
	
	if( ( this->Dir & DIR_UP ) ){
        this->Dy = 0.0f;
        this->Py = this->Oy;
    }
	
	if( ( this->Dir & DIR_RIGHT ) ){
        this->Dx = -3.0f;
    }
		
	if( ( this->Dir & DIR_LEFT ) ){
        this->Dx = 3.0f;
    }
	
    this->Px += this->Dx;


    // 右方向
	/*
    //NSLog( @"%d", ( this->Dir & DIR_RIGHT ) );
    if( ( this->Dir & DIR_RIGHT ) ){
        //this->Dx = -3.0f;
    }else{
        this->Dx = 0.0f;
    }
    
	*/
    
 
    /*
    // 右方向が当たってたら
    if( ( this->Dir & DIR_RIGHT ) ){
        this->Px -= 3;
    }
    */
    
    
    
    if( this->Py >= 960 ) this->Py = 200;
    if( this->Px <= 0 ) this->Px = 400;
    
    /*
    this->Dir = this->Dir | DIR_LEFT;
    if( System.touch.trgFlag ) this->Dir = this->Dir | DIR_UP;
 
    NSLog( @"%d %d %d", ( this->Dir & DIR_RIGHT ), ( this->Dir & DIR_LEFT ), ( this->Dir & DIR_UP ) );
    */
    
}
 
/*
 bool MENU::TouchCheck( void ){
 
 int x = System.touchPos.x;
 int y = System.touchPos.y;
 
 int sx = ( this->Width * this->SizeX ) / 2;
 int sy = ( this->Height * this->SizeY ) / 2;
 
 if(x < this->Px+sx && x > this->Px-sx &&
 y < this->Py+sy && y > this->Py-sy ){
 return true;
 }else{
 return false;
 }
 
 }
 
 */
 
void PLAYER::HitCheck( float scroll[] ){
    
    bHit = 0;
    for(int y=0; y<MAP_HEIGHT; y++){
        for(int x=0; x<MAP_WIDTH; x++){
            
            for(int tbl=0; tbl<2; tbl++){
 
                int px1 = ( x*MAP_SIZE ) + ( MAP_SIZE/2 ) + scroll[tbl];
                int py1 = ( y*MAP_SIZE ) + ( MAP_SIZE/2 );
                
                int diff = 10;
                
                if( tblMap[tbl][y][x] == 1 || tblMap[tbl][y][x] == 2 || tblMap[tbl][y][x] == 3 ){
                    
                    // 何かに当たってる
                    if( this->Px-CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py-CHARACTER_HEIGHT/2 < py1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_SOME;
                        setHit( this->Px-CHARACTER_WIDTH/2, this->Py-CHARACTER_HEIGHT/2, this->Px+CHARACTER_WIDTH/2, this->Py+CHARACTER_HEIGHT/2);
                    }
                    
                    // キャラクターから下方向が当たってる
                    if( this->Px-CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py+CHARACTER_HEIGHT/2 < py1+MAP_SIZE/2 && this->Py+CHARACTER_HEIGHT/2 > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_DOWN;
                        setHit( this->Px-CHARACTER_WIDTH/2, this->Py-CHARACTER_HEIGHT/2, this->Px+CHARACTER_WIDTH/2, this->Py+CHARACTER_HEIGHT/2);
                    }
                    
                    // キャラクターから上方向が当たってる
                    if( this->Px-CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py-CHARACTER_HEIGHT/2 < py1+MAP_SIZE/2 && this->Py-CHARACTER_HEIGHT/2 > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_UP;
                        setHit( this->Px-CHARACTER_WIDTH/2, this->Py-CHARACTER_HEIGHT/2, this->Px+CHARACTER_WIDTH/2, this->Py+CHARACTER_HEIGHT/2);
                    }
                    
                    // キャラクターから右方向が当たってる
                    if( this->Px+CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px+CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py-CHARACTER_HEIGHT/2+diff < py1+MAP_SIZE/2 && this->Py+CHARACTER_HEIGHT/2-diff > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_RIGHT;
                        //this->Dx = -3.0f;
                        setHit( this->Px-CHARACTER_WIDTH/2, this->Py-CHARACTER_HEIGHT/2+diff, this->Px+CHARACTER_WIDTH/2, this->Py+CHARACTER_HEIGHT/2-diff);
                    }
                    
                    // キャラクターから左方向が当たってる
                    if( this->Px-CHARACTER_WIDTH/2 < px1+MAP_SIZE/2 && this->Px-CHARACTER_WIDTH/2 > px1-MAP_SIZE/2 &&
                       this->Py-CHARACTER_HEIGHT/2+diff < py1+MAP_SIZE/2 && this->Py+CHARACTER_HEIGHT/2-diff > py1-MAP_SIZE/2 ){
                        this->Dir = this->Dir | DIR_LEFT;
                        setHit( this->Px-CHARACTER_WIDTH/2, this->Py-CHARACTER_HEIGHT/2+diff, this->Px+CHARACTER_WIDTH/2, this->Py+CHARACTER_HEIGHT/2-diff);
                    }
 
                }
                
                /*
                if( col != 0xffffff ){
                    DrawBoxCenter( px, py, MAP_SIZE, MAP_SIZE, col, 255 );
                }
                */
                
            }
        }
    }
 
}
 
 
 
/*
class MAP{
public:
    int tblMapMaster[TABLE_MAX][MAP_HEIGHT][MAP_WIDTH];
    int tblMap[2][MAP_HEIGHT][MAP_WIDTH];
    
    void Init();
    void InitMap( int num, int tbl[] );
};
*/
 
// マップの初期化
void InitMap( int num, int ptn ){
    
    // エラー処理
    if( num != 0 && num != 1 ) return;
    if( ptn < 0 || ptn >= TABLE_MAX ) return;
    
    for(int y=0; y<MAP_HEIGHT; y++){
        for(int x=0; x<MAP_WIDTH; x++){
            tblMap[num][y][x] = tblMapMaster[ptn][y][x];
        }
    }
 
}
 
static PLAYER Play;
 
 
 
static void Init(){
 
   // 変数の初期化
    Obj.Scroll[0] = 0.0f;
    Obj.Scroll[1] = 640.0f;
    
    // タイマー関連
    //Obj.Time.Init( TIMER_FRAME );
    //Obj.Time.Start();
    //Obj.Time.LogFlag = true;
    
    // マップの初期化
    InitMap( 0, 0 );
    InitMap( 1, 1 );
    
    // プレイヤーの初期化
    Play.Init();
    Play.Px = 100;
    Play.Py = 30;
 
} 
 
static void Loop(){
 
    int level = GetLebel( 0 );
    
    //NSLog( @"%d", level );
    
	if( Key[KEY_INPUT_RETURN].trgKey ){
	    Play.Init();
	    Play.Px = 100;
		Play.Py = 30;	
	}

	if( Key[KEY_INPUT_RIGHT].Flg ){
		// スクロール処理
		Obj.Scroll[0] -= 3.0f;
		Obj.Scroll[1] -= 3.0f;
	}else if( Key[KEY_INPUT_LEFT].Flg ){
		// スクロール処理
		Obj.Scroll[0] += 3.0f;
		Obj.Scroll[1] += 3.0f;
	}

    
    if( Obj.Scroll[0] <= -640.0f ){
        int r = rand() % LEVEL_DESIGN_PATTERN_MAX;
        int ptn = Level[level].Pattern[r];
        InitMap( 0, ptn );
        Obj.Scroll[0] = Obj.Scroll[1] + 640.0f;
    }
    if( Obj.Scroll[1] <= -640.0f ){
        int r = rand() % LEVEL_DESIGN_PATTERN_MAX;
        int ptn = Level[level].Pattern[r];
        InitMap( 1, ptn );
        Obj.Scroll[1] = Obj.Scroll[0] + 640.0f;
    }
    
    // プレイヤーのループ
    Play.Loop();
    
}
 
static void Draw(){
 
 
    DrawBox( 0, 0, 640, 960,  GetColor( 50,50,50 ), true );
 
    // マップの描画
    for(int y=0; y<MAP_HEIGHT; y++){
        for(int x=0; x<MAP_WIDTH; x++){
 
            int px = ( x*MAP_SIZE ) + ( MAP_SIZE/2 );
            int py = ( y*MAP_SIZE ) + ( MAP_SIZE/2 );
            
            for(int tbl=0; tbl<2; tbl++){
                
                int col = 0xffffff;
                if( tblMap[tbl][y][x] == 1 ) col = GetColor( 0,0,0 );
                if( tblMap[tbl][y][x] == 2 ) col = GetColor( 255,0,0 );
                if( tblMap[tbl][y][x] == 3 ) col = GetColor( 0,255,0 );
                col = GetColor( 0,0,0 );
 
                if( tblMap[tbl][y][x] != 0 ){
                    DrawBox( px+Obj.Scroll[tbl], py,  px+Obj.Scroll[tbl]+MAP_SIZE, py+MAP_SIZE, col, true );
                } 
                //DrawBox( Obj.Scroll[tbl], 0,  100, 100, col, true );
                //if( col != 0xffffff ){
                //}
                
            }
        }
    }
    
    DrawBox( Play.Px, Play.Py, Play.Px+CHARACTER_WIDTH, Play.Py+CHARACTER_HEIGHT, GetColor( 255,255,255 ), true );
    
    if( bHit ) {
        DrawBox( hitx1,hity1 ,hitx2,hity2, GetColor( 255,0,0 ), false );
    }
 
}
 
static void Finish(){
    // 描画が終ったのでグラフィックをメモリ上から削除する
     InitGraph();
     InitFontToHandle();
}
 
const SceneFunc *GetSceneFunc_Game(){ 
    static const SceneFunc func = { &Init, &Loop, &Draw, &Finish }; 
    return &func; 
} 
//////////////////////////////////////////////////

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

Re: アクションゲームのマップとキャラクターの当たり判定について

#13

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

時間がかかりそうなので、また後で確認します。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

野口

Re: アクションゲームのマップとキャラクターの当たり判定について

#14

投稿記事 by 野口 » 11年前

softya(ソフト屋)様

とんでもないです(汗)
アドバイス頂いてるだけでも非常にありがたいので・・・。
お手隙の際に、気が乗りましたらで構いませんので、見て頂けますと助かります!

アバター
Tatu
記事: 445
登録日時: 15年前
住所: 北海道

Re: アクションゲームのマップとキャラクターの当たり判定について

#15

投稿記事 by Tatu » 11年前

x座標に関する処理とy座標に関する処理を
分けてみるということについてはどうなりましたか?

野口

Re: アクションゲームのマップとキャラクターの当たり判定について

#16

投稿記事 by 野口 » 11年前

回答ありがとうございます!
一応、Loop内でY座標の判定をしてからX座標の
判定をしているのですが、こういうことではないのでしょうか。
間違ってたらすみません・・・。

アバター
Tatu
記事: 445
登録日時: 15年前
住所: 北海道

Re: アクションゲームのマップとキャラクターの当たり判定について

#17

投稿記事 by Tatu » 11年前

No:12のコードをみても
x,y両方の座標の移動
上下左右の当たりフラグ判定
x,y両方の当たりフラグ判定による移動
のように見えます。

x方向の座標の移動
左右の当たりフラグ判定
x方向の当たりフラグ判定による移動

y方向の座標の移動
上下の当たりフラグ判定
y方向の当たりフラグ判定による移動
というようにわけてはどうでしょうかということです。

閉鎖

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