首页 > 解决方案 > 球与弧、弧与弧的碰撞检测

问题描述

我正在用 JavaScript 制作一个乒乓球风格的游戏,其中桨是弯曲的。我已经在 2 个球之间发生了碰撞,但我似乎对球和弧线有问题。

我已经看过这个线程了:

圆弧球的碰撞检测

但我似乎无法让那里的答案对我有用。也许是因为我画的弧线不同。这是我的变量以及桨如何被绘制到画布上。当玩家按下一个键时,桨的角度会增加,因此它围绕玩家旋转。

如果有人可以提供帮助,我将不胜感激。

https://i.stack.imgur.com/kz0ZV.png

function Player(name, radius, innerColour, outerColour, x, y)
{
    this.prop = {
                    name:        name,
                    innerColour: innerColour,
                    outerColour: outerColour
                };

    this.phys = {
                    x:      x,
                    y:      y,
                    dx:     0,
                    dy:     0,
                    mass:   radius ** 3,
                    radius: radius

                };

    this.padd = {                                                                               
                    innerRadius: 65,                                                                              
                    outerRadius: 85,                                                                                
                    active:      true,                                                                               
                    startAngle:  225,                                                                              
                    centerAngle: 270,                                                                                
                    endAngle:    315,                                                                             
                    rotation:    false
                };

    this.draw = function()
    {
        var inR   = this.padd.innerRadius;
        var outR  = this.padd.outerRadius;

        var inC  = Math.sqrt((inR ** 2)  * 2);
        var outC = Math.sqrt((outR ** 2) * 2);

        var sAng = this.padd.startAngle;
        var cAng = this.padd.centerAngle;
        var eAng = this.padd.endAngle;

        //Draw paddle
        ctx.beginPath();
        ctx.moveTo(this.rotatePoint(inR,  sAng, "x"), this.rotatePoint(inR,  sAng, "y"));
        ctx.arcTo (this.rotatePoint(inC,  cAng, "x"), this.rotatePoint(inC,  cAng, "y"),                                                 
                   this.rotatePoint(inR,  eAng, "x"), this.rotatePoint(inR,  eAng, "y"), inR);
        ctx.lineTo(this.rotatePoint(outR, eAng, "x"), this.rotatePoint(outR, eAng, "y"))
        ctx.arcTo (this.rotatePoint(outC, cAng, "x"), this.rotatePoint(outC, cAng, "y"),                                                   
                   this.rotatePoint(outR, sAng, "x"), this.rotatePoint(outR, sAng, "y"), outR);
        ctx.lineTo(this.rotatePoint(inR,  sAng, "x"), this.rotatePoint(inR,  sAng, "y"));
        ctx.fillStyle = this.prop.outerColour;
        ctx.fill();
        ctx.closePath();
    };
    this.rotatePoint = function(radius, angle, axis)
    {
        var x = this.phys.x;
        var y = this.phys.y;

        var radians = angle * (Math.PI / 180.0);
        var x1      = x + radius;

        var newX = Math.cos(radians) * (x1 - x) + x;
        var newY = Math.sin(radians) * (x1 - x) + y;

        if (axis == "x")
        {
            return newX;
        }
        else if (axis == "y")
        {
            return newY;
        }
    };
}

编辑:对不起,我忘了添加我对碰撞代码的尝试。我每帧都运行它,但它似乎没有检测到它们何时发生碰撞。

objects 数组既是屏幕上的每个球,又是 2 名球员,而 player 数组只包含 2 名球员。

//Calculates events, speed and trajectory for paddle collisions
function paddleCollision()
{
    for (var obj in objects)
    {
        for (var player in players)
        {
            var sAng = players[player].padd.startAngle * (Math.PI / 180.0);
            var eAng = players[player].padd.endAngle   * (Math.PI / 180.0);

            var inR  = players[player].padd.innerRadius;
            var outR = players[player].padd.outerRadius;

            var ballR = objects[obj].phys.radius;

            var collides = false;

            var dX = objects[obj].phys.x - players[player].phys.x;
            var dY = objects[obj].phys.y - players[player].phys.y;

            var dist = Math.sqrt((dX ** 2) + (dY ** 2));
            var dir  = Math.atan2(dY, dX);

            var tanAng = Math.asin(ballR / dist);
            var dir0   = dir + tanAng;
            var dir1   = dir - tanAng;

            if (dist + ballR > inR && dist - ballR < outR)
            {
                var d  = dir  > sAng && dir  < eAng;
                var d0 = dir0 > sAng && dir0 < eAng;
                var d1 = dir1 > sAng && dir1 < eAng;

                if (d || d0 && d1)
                {
                    collides = true;
                }
                else if (d0 != d1)
                {
                    var x0 = players[player].phys.x + outR * Math.cos(sAng) - objects[obj].phys.x;
                    var y0 = players[player].phys.y + outR * Math.sin(sAng) - objects[obj].phys.y;

                    var x1 = players[player].phys.x + outR * Math.cos(eAng) - objects[obj].phys.x;
                    var y1 = players[player].phys.y + outR * Math.sin(eAng) - objects[obj].phys.y;

                    if ((x0 ** 2) + (y0 ** 2) < (ballR ** 2) || (x1 ** 2) + (y1 ** 2) < (ballR ** 2))
                    {
                        collides = true;
                    }
                }
            }
        }
    }

    if (collides)
    {
        console.log("HITTING");
    }
}

标签: javascriptmath2dcollision-detectiongame-physics

解决方案


这对我有用:

    function arcsCollision(first, second) {
    const dx = first.x - second.x;
    const dy = first.y - second.y;
    const distance = Math.sqrt(dx**2 + dy**2);
    return (
        distance
        <=
        (first.radius + second.radius + 0.1)
    );
}

function arcAndRectCollision(arc, rect) {

    return (
        arc.x - arc.radius < rect.x ||
        arc.x + arc.radius > rect.width ||
        arc.y - arc.radius < rect.y ||
        arc.y + arc.radius > rect.height
    );
}

您可以访问此网站了解更多信息。 https://spicyyoghurt.com/tutorials/html5-javascript-game-development/collision-detection-physics


推荐阅读