0

書いている小さな2Dゲームで衝突に問題があります。私は現在、プレイヤーキャラクターがブロックと衝突したかどうか、およびブロックのどちら側と衝突したかを調べたい関数に取り組んでいます。

現在、私は(psuedo-code)のようなものを持っています:

if(PLAYER_BOX IS WITHIN THE BLOCKS Y_RANGE)
{
    if(PLAYER_BOX_RIGHT_SIDE >= BLOCK_LEFT_SIDE && PLAYER_BOX_RIGHT_SIDE <= BLOCK_RIGHT_SIDE)
    {
        return LEFT;
    }
    else if(PLAYER_LEFT_SIDE <= BLOCK_RIGHT_SIDE && PLAYER_LEFT_SIDE >= BLOCK_LEFT_SIDE)
    {
        return RIGHT;
    }
}
else if(PLAYER_BOX IS WITHIN BLOCK X_RANGE)
{
    if(PLAYER_BOTTOM_SIDE >= BLOCK_TOP_SIDE && PLAYER_BOTTOM_SIDE <= BLOCK_BOTTOM_SIDE)
    {
        return ABOVE;
    }
    else if(PLAYER_TOP_SIDE <= BLOCK_BOTTOM_SIDE && PLAYER_TOP_SIDE >= BLOCK_TOP_SIDE)
    {
        return BELOW;
    }
 }

ここに論理エラーがありますか?または、コードに何か間違ったことを書いただけですか?

ABOVEコリジョンは機能しますが、横方向のコリジョンを認識すべき場合は認識しません。また、そうでない場合も認識します。

ゲームはスーパーマリオのクローンなので、横スクロールの2Dプラットフォーマーです。

4

2 に答える 2

2

問題は方向性だと思います。

本当にやりたいことは、最初に「プレーヤー」の方向を考慮してから、チェックを行うことです。

プレイヤーがどの方向に動いているのかわからない場合は、スプライトの動きの「速さ」に応じて、誤ヒットの数を取得できます。

たとえば、移動方向 (上下左右) がある場合、コードは次のようになります。

select movedir
(
   case up:
     //check if hitting bottom of box
     break;
   case down:
     //check if hitting top of box

    etc

}
于 2010-10-05T16:43:35.173 に答える
0

移動デルタを使用して計算を修正することを検討してください。

このようなもの(これも疑似):


// assuming player graphics are centered
player_right = player.x + player.width / 2;
player_left = player.x - player.width / 2;

player_top = player.y - player.height / 2;
player_bottom = player.y + player.height / 2;

// assuming block graphics are centered as well
block_right = box.x + box.width / 2;
...

// determine initial orientation
if (player_right  block_right) orientationX = 'right';

if (player_top  block_top) orientationY = 'top';

// calculate movement delta
delta.x = player.x * force.x - player.x;
delta.y = player.y * force.y - player.y;

// define a rect containing where your player WAS before moving, and where he WILL BE after moving
movementRect = new Rect(player_left, player_top, delta.x + player.width / 2, delta.y + player.height / 2);

// make sure you rect is using all positive values
normalize(movementRect);

if (movementRect.contains(new Point(block_top, block_left)) || movementRect.contains(new Point(block_right, block_bottom))) {

    // there was a collision, move the player back to the point of collision
    if (orientationX == 'left') player.x = block_right - player.width / 2;
    else if (orientationX == 'right') player.x = block_left + player.width / 2;

    if (orientationY == 'top') player.y = block_top - player.height / 2;
    else if (orientationY == 'bottom') player.y = block_bottom + player.height / 2;

    // you could also do some calculation here to see exactly how far the movementRect goes past the given block, and then use that to apply restitution (bounce back)

} else {

    // no collision, move the player
    player.x += delta.x;
    player.y += delta.y;

}

このアプローチは、プレーヤーが非常に速く動く場合に、はるかに優れた結果をもたらします。これは、プレーヤーが実際に衝突したかどうかではなく、衝突するかどうかを本質的に計算しているためです。

于 2010-10-07T16:01:59.557 に答える