弧线球的碰撞检测 [英] Collision detection of a ball with an arc

查看:97
本文介绍了弧线球的碰撞检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做一个简单的游戏,其中我有一个绕中心旋转的球和弧线.当用户触摸屏幕时,球沿指针方向移动并击中弧线.但是我找不到任何方法可以检测到该碰撞 附有图片以便更好地理解

I am making a simple game in which i have a ball and an arc revolving around the center. When user touches the screen the ball moves in the direction of pointer and hits the arc. But i am not able to find any method to detect that collision An image has been attached for better understanding

游戏图片

调试快照.

我的球周围有一个圆圈... 我在做什么

I have a circle bound around my ball... What i am doing is

确定圆弧正在旋转的球中心与圆的交点. 但是当球与圆相交时,我无法检测到弧线是否存在? 请帮助...:'(

Detecting the point of intersection of ball center and circle on which arc is >revolving. But i am not able to detect whether the arc was there when ball intersected the circle?? please help...:'(

制作弧的代码:

 public void arc (float x, float y, float radius, float start, float degrees,int segments) {
  //  int segments = (int)(6 * (float)Math.cbrt(radius) * (degrees / 360.0f));

    if (segments <= 0) throw new IllegalArgumentException("segments must be > 0.");
    float colorBits = color.toFloatBits();
    float theta = (2 * MathUtils.PI * (degrees / 360.0f)) / segments;
    float cos = MathUtils.cos(theta);
    float sin = MathUtils.sin(theta);
    float cx = radius * MathUtils.cos(start * MathUtils.degreesToRadians);
    float cy = radius * MathUtils.sin(start * MathUtils.degreesToRadians);

    for (int i = 0; i < segments; i++) {
        renderer.color(colorBits);
        Gdx.gl20.glLineWidth(10);
        Gdx.gl.glEnable(GL20.GL_BLEND);
        renderer.vertex(x + cx, y + cy, 0);
        float temp = cx;
        cx = cos * cx - sin * cy;
        cy = sin * temp + cos * cy;
        renderer.color(colorBits);
        renderer.vertex(x + cx, y + cy, 0);
    }
}

推荐答案

什么是弧?简单地说:两个圆之差,限制在两个向量(或一个三角形)之内.

What is an arc? Simply: the difference of two circles, constrained within two vectors (or a triangle).

图表可能会有所帮助;

A diagram may be helpful;

较大的红色圆圈的半径等于圆弧的外部半径.较小的蓝色圆圈的半径等于圆弧的内半径,减去球的直径.三角形显示了圆弧的边缘.

The radius of the larger red circle equals the outer radius of the arc. The radius of the smaller blue circle equals the inner radius of the arc, minus the diameter of the ball. The triangle shows the edges of the arc.

从这里,只需测试球[从中心]相对于圆弧半径的欧几里得距离,然后找到从原点到球的两个切线,看看它们中的任何一个是否通过弧线.

From here, just test the euclidean distance of the ball [from the center] against the radii of the circles, then find the two tangents from the origin to the ball and see if either of them fall pass through the angular measure of the arc.

意识到我自己的项目中需要这样的东西,所以我决定将其编写出来;

Realized I need something like this in my own project, so I decided to write it up;

    double ball_radius = //Your radius of the ball

    //the start and end angles of the arc
    double start = //i.e -PI/4;
    double end = //i.e PI/4;

    double innerRadius = //inner radius of arc
    double outerRadius = innerRadius + [width of lines, 10 in your code]

    /* Now all the fun mathsy stuff */

    boolean collides = false;

    double dx = bx - cx; //[bx, by] = ball coords
    double dy = by - cy; //[cx, cy] = center coords

    //get distance and direction to ball from center
    double dist = Math.sqrt(dx * dx + dy * dy);
    double dir = Math.atan2(dy, dx);

    //angles for tangents to ball from center
    double tangent_angle =  Math.asin(ball_radius/ dist);
    double dir0 = dir + tangent_angle;
    double dir1 = dir - tangent_angle;

    //check if distance is good
    if (dist + ball_radius> innerRadius && dist - ball_radius < outerRadius)
    {
        //check edges of ball against start and end of arc
        boolean d = dir > start && dir < end;
        boolean d0 = dir0 > start && dir0 < end;
        boolean d1 = dir1 > start && dir1 < end;

        //if both tangents are inside the angular measure
        if (d || d0 && d1)
        {
            collides = true;
        }
        //otherwise if one tangent is inside
        //We need to test the outside corners more precisely
        else if (d0 != d1)
        {
                double x0 = cx + outerRadius * Math.cos(start) - bx;
                double y0 = cy + outerRadius * Math.sin(start) - by;

                double x1 = cx + outerRadius * Math.cos(end) - bx;
                double y1 = cy + outerRadius * Math.sin(end) - by;

                /** And so on for the other 2 corners */
                /** If the arc is very thick, you will need to test against
                    the actual line segments at the ends of the arc */

                if (x0 * x0 + y0 * y0 < ball_radius * ball_radius
                    || x1 * x1 + y1 * y1 < ball_radius * ball_radius)
                    collides = true;

        }
    }

如果球只打算击中弧线的内部,或者击中弧线的角时3-4个像素的不精确度是可以的,那么您可以用以下代码替换上面代码中的整个if条件,这种方式效率更高(但在角落处非常混乱);

If the ball is only ever going to hit the inside of the arc, or 3-4 pixels of imprecision is okay when hitting the corners of the arc, then you can replace the entire if-condition in the above code with this, which is way more efficient (but messes up on the corners very slightly);

if (dist > innerRadius - ball_radius && dist + ball_radius < outerRadius)
{
    //if any tangent falls within the arc
    collides = ((dir0 > start && dir0 < end) || (dir1 > start && dir1 < end));
}

最终结果:

这篇关于弧线球的碰撞检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆