1

楽しみのために HTML5 キャンバスを使用してゲームを作成しようとしていますが、重力のために 2 つのスプライト間の衝突を検出するのに問題があります。

Player クラスに tick() メソッドがあり、各ティックで、プレーヤーの x 座標と y 座標をそれぞれ速度 X と速度 Y でインクリメントします。次に、速度 Y に重力を追加します。次に、プレーヤーと、画面の下部に並んで配列に格納されている画面上のブロックとの間の衝突をチェックしたいと思います。

これはコードです:

Player.prototype.tick = function() {

    this.x += this.velocityX;
    this.y += this.velocityY;
    this.velocityY += GRAVITY;

    var blocks = world.getOnScreenBlocks();
    for (var i=0; i<blocks.length; i++) {
            //Check for collision of this object (Player) with blocks[i]
        }
    }
}

衝突検出を機能させるために数時間を費やしましたが、あきらめました。プレイヤーの座標と各ブロックの座標を比較して衝突を検出する方法は知っていますが、問題は衝突の場合の調整です。

ブロックの上部で衝突を検出した場合は、velocityY を 0 に設定して、プレーヤーの垂直方向の動きを停止させることができます。ただし、次のティックでは、GRAVITY が追加されるため、velocityY が増加し、衝突が再び検出され、プレイヤーは多くのティックの後にゆっくりとブロックを通過します。

衝突時にvelocityYを0に設定し、プレイヤーの位置をブロックの真上に固定すると、ブロックを押し下げようとする重力のためにブロックの上に立っている間に一定の衝突が検出されることを除いて、多少は機能します。

これは、ブロックの 4 つの側面すべてで衝突検出を取得するのに最も近いものです。

var blocks = world.getOnScreenBlocks();
for (var i=0; i<blocks.length; i++) {
    var block = blocks[i];
    var left1 = this.x;
    var left2 = block.getX();
    var right1 = this.x + this.sprite.getWidth();
    var right2 = block.getX() + block.getSprite().getWidth();
    var top1 = this.y - this.sprite.getHeight();
    var top2 = block.getY() - block.getSprite().getHeight();
    var bottom1 = this.y;
    var bottom2 = block.getY();

    //Check for collision at top
    if (this.velocityY > 0) {
        if (left1 < right2 && right1 > left2 && bottom1 >= top2 && bottom1 <= bottom2) {
            this.y = top2;
            this.velocityY = 0;
        }
    }

    //Check for collision at bottom
    else if (this.velocityY < 0) {
        if (left1 < right2 && right1 > left2 && top1 <= bottom2 && top1 >= top2) {
            this.y = bottom2 + this.sprite.getHeight();
            this.velocityY = 0;
        }
    }

    //Check for collision on right
    if (this.velocityX > 0) {
        if (top1 < bottom2 && bottom1 > top2 && right1 >= left2 && right1 <= right2) {
           this.x = left2 - this.sprite.getWidth();
            this.velocityX = 0;
        }
    }

    //Check or collision on left
    else if (this.velocityX < 0) {
       if (top1 < bottom2 && bottom1 > top2 && left1 <= right2 && left1 >= left2) {
            this.x = right2;
            this.velocityX = 0;
        }
    }
}

これは多少機能しますが、実際にはグリッチがあります。衝突が発生したときにスプライトの x 座標と y 座標を設定することは避けたいと思います。

また、衝突が検出されたが何も機能しない場合に重力を追加しないように、衝突のブール値を設定しようとしました。これを行うための標準的で適切な方法はありますか?助けてください。

また、より効率的にするために、プレイヤーが動いている場合にのみループを通過して衝突をチェックすることを本当に望んでいますが、重力のために速度 Y が常にゼロを超えるため、方法がわかりません。

ありがとう。

編集: 上記の 2 番目の例では、プレーヤーとブロックの x 座標と y 座標は、通常の左上隅ではなく、左下隅に基づいていることを含める必要があります。スプライトの高さが異なるためにこれを行い、スプライトの足が地面と衝突する下部で衝突を機能させたいと考えました。

4

0 に答える 0