球粘在线段上

时间:2019-01-30 16:08:31

标签: line collision-detection simulation collision geometry

我正在尝试编写一个程序来检测线段和球之间的碰撞,如果发生碰撞,则球会弹起线

使用此站点中的教程: http://doswa.com/2009/07/13/circle-segment-intersectioncollision.html 我设法找到该直线上最接近的点。也是物理学 因为弹跳很简单,所以速度的法向矢量应该颠倒而切线矢量保持不变。我想我在这里写了很多东西,因为对于某些粒子和速度,它们弹跳完美,但是大多数情况下它们会粘在线!这是我需要解释的代码部分:

                    Particle p = Particles[i];
        Vector v1 = new Vector(l.getP1());
        Vector v2 = new Vector(l.getP2());

        Vector c = new Vector(p.position.getX(), p.position.getY());

        // a is the closet of points 1 & 2 to the circles center
        // b is the farthest of points 1 & 2 to the circles center

        float deltaD1 = c.subtract(v1).getMagnitude();
        float deltaD2 = c.subtract(v2).getMagnitude();

        Vector a;
        Vector b;
        if (deltaD1 <= deltaD2) {
            a = v1;
            b = v2;
        } else {
            a = v2;
            b = v1;
        }

        float r = p.getRadius();

        // seg_v is a vector from a to b
        // pt_v is a vector from a to the center of the circle
        Vector seg_v = (b.subtract(a)).normalize();
        Vector pt_v = c.subtract(a);


        // now we find the closest point on the line to the circle
        float closeSize = pt_v.dot(seg_v);

        Vector closest;
        float distance;
        if (closeSize <= 0) {
            closest = a;
            distance = pt_v.getMagnitude();

        } else {
            closest = seg_v.multiply(closeSize).add(a);
            distance = c.getDistance(closest);
        }
        // now the collision checking!

        if (distance <= r) {



            // repositioning the particle
            Vector tangent = seg_v;

            // the normal vector is perpendicular to the line and it is a unit vector so we
            // have to normalize it
            Vector normal = new Vector(-seg_v.getX(), seg_v.getY());
            normal = normal.normalize();

            wallCollision(p, tangent, normal);    }}}



private void wallCollision(Particle p, Vector tangent, Vector normal) {

    // when collision happens the normal vector changes but the tangent vector is
    // the same
    float vt = p.getVelocity().dot(tangent);
    float vn = -p.getVelocity().dot(normal);
    Vector newVelocity = tangent.multiply(vt).add(normal.multiply(vn));
    p.setVelocity(newVelocity);

}

//游戏循环:

            public void mainLoop() {
    long previousTime = System.currentTimeMillis();
    long currentTime = previousTime;
    long elapsedTime;
    long totalElapsedTime = 0;
    int frameCount = 0;

    while (true) {
        currentTime = System.currentTimeMillis();
        elapsedTime = (currentTime - previousTime); // elapsed time in seconds
        totalElapsedTime += elapsedTime;
        // we are checking if more than one second has passed
        if (totalElapsedTime > 1000) {
            this.fps = frameCount;
            frameCount = 0;
            totalElapsedTime = 0;
        }

        moveParticles(elapsedTime / 1000f);
        render();

        try {

            Thread.sleep(5);
        } catch (Exception e) {
            e.printStackTrace();
        }

        previousTime = currentTime;
        frameCount++;

    }

}

我知道代码很乱!我创建了一个名为Vector和Particles的类,该类的方法和动作在代码中清晰可见。我认为问题在于球的速度。如果粒子尚未与直线碰撞,在下一帧中它可能会移动太多并与直线相交,因此其当前位置与最近点之间的距离不够大。要解决此问题,我要么必须重新定位球,要么预测碰撞。我找不到解决这些问题的好方法,也许我对粘贴是错误的。此外,我使用以下代码代替wallCollison方法:

            p.velocity.setX(-(p.velocity.getX())); // Reversing the velocity
            p.velocity.setY(-(p.velocity.getY()));

球反弹但明显以错误的方式反弹(但仍然偶尔有一些球粘在直线上),因此问题可能出在碰撞后的速度上! 我该如何解决? 感谢您的关注

enter image description here

0 个答案:

没有答案