简体   繁体   中英

Collision detection between ball and arc, and between arc and arc

I'm making a pong style game in JavaScript where the paddle is curved. I already have collision between 2 balls but I seem to be having trouble with the ball and arc.

I've looked at this thread already:

Collision detection of a ball with an arc

But I can't seem to make the answer there work for me. Perhaps because I draw the arc differently. Here's my variables as well as how the paddle is being drawn onto the canvas. When the player presses a key, the angles for the paddle are incremented so it revolves around the player.

If anyone can help I would appreciate it.

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;
        }
    };
}

Edit: Sorry I forgot to add my attempt at the collision code. I run it every frame but it doesn't seem to detect when they're colliding.

The objects array is both every ball on the screen and the 2 players, and the players array just contains the 2 players.

//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");
    }
}

This worked for me:

    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
    );
}

You can go to this website for more info. https://spicyyoghurt.com/tutorials/html5-javascript-game-development/collision-detection-physics

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM