ページ 11

マップチップの坂道について

Posted: 2010年3月17日(水) 18:02
by KEYONN_
こんばんは、TKOZです。

数ヶ月前に同じような質問をしたのですが、スレッドが下がってしまったのと、
また作りたくなったので質問します。

マップチップ内の当たり判定で坂道を移動させているのですが、どうしても
下記のP点でAの坂道にはまってしまいます。
  P⊿←B □
 ⊿←A □□
□□□□□□

どうすれば自然に坂道を登る事が出来ますでしょうか?
アドバイスください。

あと、マップチップの番号が3のとき(右下り45度の坂)の時の判定が判定されるのですが、
地面にめり込んでしまいます。
これは何故なんでしょうか?

void Hit()
{
    int i,j;
    static int hitflag[100]={0};
    static int yy[100]={0};

    if(Map[(int)(Player.y+63)/32][(int)(Player.x+31)/32]==2)//Mapは2なら
    {
        //高さを計算
        int h = ((int)(Player.x+31)%32) * -1;
        
        if((Player.y+63) >= (Player.y+63)+h)
        {
            //1回しか代入しないようにする
            if(hitflag[0]==0)
            {
                yy[0] = Player.y;
            }
            //高さを加算する
            Player.y = yy[0] + h;
            //フラグを1にする(これは、他の処理で使用する)
            hitflag[0]=1;
        }
    }
    else if(Map[(int)(Player.y+63)/32][(int)(Player.x)/32]==3)//Mapは3なら
    {
        //高さを計算
        int h = ((int)(Player.x)%32);
        
        if((Player.y+63) <= (Player.y+63)+h)
        {
            //1回しか代入しないようにする
            if(hitflag[1]==0)
            {
                yy[1] = Player.y;
            }
            //高さを加算する
            Player.y = yy[1] + h;
            //フラグを1にする(これは、他の処理で使用する)
            hitflag[1]=1;
        }
    }
    else
    {
        hitflag[1]=0;
        hitflag[0]=0;
    }
    
    
    //DrawFormatString(0,0,GetColor(255,255,255),"height=%d",-1*mx);
}
画像

Re:マップチップの坂道について

Posted: 2010年3月17日(水) 18:09
by KEYONN_
ソースコードをアップします。
お願いします。

Re:マップチップの坂道について

Posted: 2010年3月17日(水) 22:45
by mera
ソースをしっかり読んでいないのではっきりとは言えませんが、
三角形は上に行く程幅がせまくなりますよね。
だから坂の上のほうでは三角形を素通りして次のブロックとあたり判定をするんではないかと。
今回のケースだと、隣のブロックも三角形なので、空中とのあたり判定になってしまって、
そのまま移動してしまうんだと思います。
解決策としては坂を構成する場合、三角形だけで作るのではなく、表面(?)だけ三角形で
中身は四角でびっしり埋めないとだめなんだと思います。

見当違いのことを言っているようでしたらすみません。

Re:マップチップの坂道について

Posted: 2010年3月18日(木) 16:29
by KEYONN_
meraさんへ

なんとなく分かりました。
チップの種類を細かく分ければいいんですね?
普通のまっすぐなチップは32ドットで、
坂道だけは1ドットずつのチップにすれば解決しそうです。

しかし、そのためのデータ構造が複雑化しそうですね。

さて、どうしますか…。

Re:マップチップの坂道について

Posted: 2010年3月18日(木) 17:06
by softya
すいません。アレ時間がなくてから検討できてません。

>坂道だけは1ドットずつのチップにすれば解決しそうです。

仮想的なものなので実際にチップ化する必要は無いと思いますが、とりあえず1ドット化を試してみてはどうでしょうか?現実にやると重いと思います。

>そのためのデータ構造が複雑化しそうですね。

グラフィックデータのカラーを直接使う手はありますね。速度を無視してあくまで実験という意味ですが。

Re:マップチップの坂道について

Posted: 2010年3月18日(木) 17:28
by mera
>TKOZさん
あ~すみません。わかりにくかったですね。
要は今

 ⊿
⊿⊿   となっているものを

 ⊿
⊿□

にするだけで大丈夫だと思います。

Re:マップチップの坂道について

Posted: 2010年3月18日(木) 18:23
by KEYONN_
問題は解決しました。まあ、まだ完全ではないですが…。
ソースコードを書きます。

ソースコードの中にサイト名「Javaでゲーム作りますが何か?」の中のコードを引用しています。
URLを下記に示します。
http://javagame.skr.jp/index.php?FrontPage#u1b27b69

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

typedef struct P{
    float x;
    float y;
    int width;
    int height;
    int jumpflag;
    float vx;
    float vy;
    bool onGround;
}P;

typedef struct SLOPE{
    int number;//番号
    int imagedata;//坂道データ
}SLOPE;
int ScreenHandle;

SLOPE Chip[6]={0};

class Point{
public:
    int x;
    int y;
    Point()
    {
        x=0;
        y=0;
    }
    Point(int xx,int yy)
    {
        x=xx;
        y=yy;
    }
};

P Player={0};

int Map[15][20]={
    {0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
    {0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
    {0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
    {0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
    {0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
    
    {0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
    {0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
    {0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
    {0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
    {0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
    
    {0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
    {0,0,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,3,0,4, 5,1,1,6,7, 0,0,0,0,0},
    {1,3,0,0,0, 2,1,1,3,0, 0,0,2,3,0, 0,2,3,0,1},
    {1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1}
};


int pixelsToTiles(double pixels)
{
    return (int)floor(pixels / 32);
}
int tilesToPixels(int tiles)
{
    return tiles * 32;
}
int CheckHit(int px,int py,int tx1,int ty1,int tx2,int ty2,int tx3,int ty3)
{
    HITRESULT_LINE a;
    
    a=HitCheck_Line_Triangle(VGet(px,py, 0 ), VGet(px,py,0), 
        VGet(tx1,ty1,0), VGet(tx2,ty2,0), VGet(tx3,ty3,0) ) ;
    if(a.HitFlag==1)
    {
        return 1;    
    }
    return 0;
}

void Init()
{
    Player.x= 320;
    Player.y = 0;
    Player.jumpflag = 1;
    Player.width = 32;
    Player.height = 64;
    Player.vx=1;
    Player.vy=1;

    int i,j,k;
    char str[100];
    
    ScreenHandle=MakeARGB8ColorSoftImage(640,480) ;

    for(i=0;i<6;i++)
    {
        Chip.number =i;
        sprintf(str,"./Data/%d.bmp",i);
        Chip.imagedata = LoadSoftImage(str) ;//0.bmpは右上45度
        //1.bmpは右下45度、2.bmpと3.bmpは右上30度、4.bmpと5.bmpは右下30度
    }
}

Point gettile(int xx,int yy)
{
        int newX = ceil(xx);
        int newY = ceil(yy);

        double fromX = min(Player.x, newX);
        double fromY = min(Player.y, newY);
        double toX = max(Player.x, newX);
        double toY = max(Player.y, newY);
        
        int fromTileX = pixelsToTiles(fromX);
        int fromTileY = pixelsToTiles(fromY);
        int toTileX = pixelsToTiles(toX + Player.width-1);
        int toTileY = pixelsToTiles(toY + Player.height - 1);

        // 衝突しているか調べる
        for (int x = fromTileX; x <= toTileX; x++) {
            for (int y = fromTileY; y <= toTileY; y++) {
                // 画面外は衝突
                if (x < 0 || x >= 20) {
                    return Point(x, y);
                }
                if (y < 0 || y >= 15) {
                    return Point(x, y);
                }
                // ブロックがあったら衝突
                if (Map[y][x] == 1) {
                    return Point(x, y);
                }
            }
        }
        
        return Point(-1,-1);
}
画像

Re:マップチップの坂道について

Posted: 2010年3月18日(木) 18:25
by KEYONN_
2/3です。(ソースコード)
void DrawMap()
{
    int i,j;
    FillSoftImage(ScreenHandle,0,0,0,0) ;
    for(i=0;i<15;i++)
    {
        for(j=0;j<20;j++)
        {
            if(Map[j]==1)
            {
                DrawBox(j*32 , i*32 , j*32+32 , i*32+32 ,
                    GetColor(255,255,255) , TRUE ) ;
            }
            if(Map[j]==2)
            {
                DrawTriangle( j*32, i*32+32, j*32+32, i*32+32,
                    j*32+32, i*32, GetColor(255,0,0) , TRUE ) ;
                BltSoftImage( 0, 0, 32, 32, Chip[0].imagedata , 
                    j*32, i*32, ScreenHandle ) ;

            }
            if(Map[j]==3)
            {
                DrawTriangle( j*32,i*32,j*32,i*32+32,
                    j*32+32,i*32+32,GetColor(0,255,0),TRUE);
                BltSoftImage( 0, 0, 32, 32, Chip[1].imagedata , 
                    j*32, i*32, ScreenHandle ) ;
            }
            if(Map[j]==4)
            {
                DrawTriangle(j*32,i*32+32,j*32+64,i*32,
                    j*32+64,i*32+32,GetColor(255,0,255),TRUE);
                BltSoftImage(0,0,32,32,Chip[2].imagedata ,
                    j*32,i*32,ScreenHandle);
            }
            if(Map[j]==5)
            {
                BltSoftImage(0,0,32,32,Chip[3].imagedata,
                    j*32,i*32,ScreenHandle);
            }
            if(Map[j]==6)
            {
                DrawTriangle(j*32,i*32+32,j*32+64,i*32+32,
                    j*32,i*32,GetColor(255,255,0),TRUE);
                BltSoftImage(0,0,32,32,Chip[4].imagedata ,
                    j*32,i*32,ScreenHandle);
            }
            if(Map[j]==7)
            {
                BltSoftImage(0,0,32,32,Chip[5].imagedata ,
                    j*32,i*32,ScreenHandle);
            }
        }
    }
}

int GetCol(int handle,int x,int y)
{
    int r,g,b,a;

    GetPixelSoftImage(handle,  x, y, &r, &g, &b, &a );
    return GetColor(r,g,b);
}

void Hit()
{
    
    
    if(GetCol(ScreenHandle,Player.x+31,Player.y+63)==GetColor(255,0,0))
    {
        Player.y-=3;
        Player.vy=0;
    }
    if(GetCol(ScreenHandle,Player.x,Player.y+63)==GetColor(255,0,0))
    {
        Player.y-=3;
        Player.vy=0;
    }


    
    
    
}

Re:マップチップの坂道について

Posted: 2010年3月18日(木) 18:26
by KEYONN_
3/3です。(終わり)
void DrawPlayer()
{
    static int prev=0;

    DrawBox(Player.x,Player.y,Player.x+Player.width ,Player.y+Player.height ,
        GetColor(0,0,255),TRUE);

    if(CheckHitKey(KEY_INPUT_RIGHT))
    {
        Player.vx+=0.2;
        if(Player.vx>2) Player.vx=2;
    }
    if(CheckHitKey(KEY_INPUT_LEFT))
    {
        Player.vx-=0.2;
        if(Player.vx<-2) Player.vx=-2;
    }
    if(!CheckHitKey(KEY_INPUT_RIGHT) && !CheckHitKey(KEY_INPUT_LEFT))
    {
        Player.vx=0;
    }
    Player.x+=Player.vx;
    if(!prev && CheckHitKey(KEY_INPUT_X))
    {
        Player.vy=-16;
        Player.jumpflag = 1;
        Player.onGround = false;
    }

    prev=(CheckHitKey(KEY_INPUT_X));

}

bool equal(Point a,Point b)
{
    if(a.x=b.x && a.y==b.y)
        return true;
    else
        return false;
}



void UpDate()
{
    // 重力で下向きに加速度がかかる
        Player.vy += 1;

        // x方向の当たり判定
        // 移動先座標を求める
        double newX = Player.x + Player.vx;
        // 移動先座標で衝突するタイルの位置を取得
        // x方向だけ考えるのでy座標は変化しないと仮定
        Point tile;
        
        tile = gettile(newX, Player.y);
        
        if (equal(tile,Point(-1,-1) )) {
            // 衝突するタイルがなければ移動
            Player.x = newX;
        } else {
            // 衝突するタイルがある場合
            if (Player.vx > 0) { // 右へ移動中なので右のブロックと衝突
                // ブロックにめりこむ or 隙間がないように位置調整
                Player.x = tilesToPixels(tile.x) - 32;//32→WIDTH
            } else if (Player.vx < 0) { // 左へ移動中なので左のブロックと衝突
                // 位置調整
                Player.x = tilesToPixels(tile.x + 1);
            }
            Player.vx = 0;
        }

        // y方向の当たり判定
        // 移動先座標を求める
        double newY = Player.y + Player.vy;
        // 移動先座標で衝突するタイルの位置を取得
        // y方向だけ考えるのでx座標は変化しないと仮定
            tile = gettile(Player.x, newY);
            
        if (equal(tile,Point(-1,-1))) {
            // 衝突するタイルがなければ移動
            Player.y = newY;
            // 衝突してないということは空中
            Player.onGround = false;
        } else {
            // 衝突するタイルがある場合
            if (Player.vy > 0) { // 下へ移動中なので下のブロックと衝突(着地)
                // 位置調整
                Player.y = tilesToPixels(tile.y) - 64;//32→HEIGHT
                // 着地したのでy方向速度を0に
                Player.vy = 0;
                // 着地
                Player.onGround = true;
            } else if (Player.vy < 0) { // 上へ移動中なので上のブロックと衝突(天井ごん!)
                // 位置調整
                Player.y = tilesToPixels(tile.y + 1);
                // 天井にぶつかったのでy方向速度を0に
                Player.vy = 0;
            }
        }
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hP,LPSTR lpC,int nC)
{
    
    SetGraphMode(640,480,32);
    ChangeWindowMode(TRUE) ;
    SetMainWindowText("斜め坂(当たり判定チェック)"); //ウィンドウのタイトル
    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();            //画面を初期化

        DrawMap();
        
        //DrawSoftImage( 0, 0, ScreenHandle ) ;

        DrawFormatString(0,0,GetColor(255,255,255),"Player.y=%d",Player.y);
        DrawPlayer();
        UpDate();
        Hit();
        

        ScreenFlip();                //フリップする
    }
    
    DxLib_End();    //DXライブラリ終了処理
    return (0);        //終了
}
画像

Re:マップチップの坂道について

Posted: 2010年3月18日(木) 18:38
by KEYONN_
softyaさんへ

>グラフィックデータのカラーを直接使う手はありますね。速度を無視してあくまで実験という意味ですが。
グラフィックデータ使いましたよ。その前のコードは、
typedef struct CHIP{
int kind;
int data[32][32];
}CHIP;
CHIP Chip[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,0,
  略(ry
},
{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,1,
 略(ry
};
とひたすら0と1の羅列が配列に代入されてました。(笑)


>meraさんへ
>要は今

 ⊿
⊿⊿   となっているものを

 ⊿
⊿□

>にするだけで大丈夫だと思います。

僕のアルゴリズムでは、それだけでは駄目みたいでした。
せっかくの助言ありがとうございます。

Re:マップチップの坂道について

Posted: 2010年3月20日(土) 12:59
by KEYONN_
今度、「14歳からはじめる C言語わくわくゲームプログラミング教室 Visual Studio 2008編」
という本を買うことにしました。
ベクトルでの坂道の実装に興味が沸いたからです。

それでは、みなさま、ありがとうございました。
解決にします。