碰撞检测新思路

最近做一个弹珠游戏,核心就是碰撞检测,网上也看了一些资料,无奈悟性太低,理解不了什么投影法等,静下心来,自己也琢磨了一个思路。

游戏的场景是这样:在一个平面上有一个矩形框,框内有一个圆形弹珠,还有任意多边形,如图
1.png

要检测一个多边形与该小球是否碰撞,我的思路是:

  1. 对于多边形每一条边,通过小球的圆心做垂直线,如果垂直线的长度小于或等于小球的半径则认为小球与该边碰撞
  2. 对于多边形每一个顶点,与小球的圆心的距离小于或等于小球的半径则认为小球与该边碰撞
    边界的碰撞检测是非常简单的,判断小球的左右上下是否等于边框的或左或右或上或下

下面细说代码

  1. 通过圆心求任意直线的垂直线的交点
public static Point getVerticalPoint(Point o, Point a, Point b) {
        double a1 = a.x;
        double b1 = a.y;
        double a2 = b.x;
        double b2 = b.y;

        System.out.println("线段从(" + a1 + "," + b1 + ")至(" + a2 + "," + b2 + ")");
//        double k = (b2 - b1) / (a2 - a1);
//        System.out.println("线段的斜率k=" + k);
        double c1 = o.x;
        double d1 = o.y;
        System.out.print("则从点(" + c1 + "," + d1 + ")引该线段的垂直线,其垂直点为:");
        double c2, d2;
        //特殊情况1,a.x==b.x
        if (a1 == a2) {
            c2 = a1;
            d2 = d1;
        }
        //特殊情况2,a.y==b.y
        else if (b1 == b2) {
            c2 = c1;
            d2 = b1;
        } else {
            d2 = (b1 * (a2 - a1) * (a2 - a1) + d1 * (b2 - b1) * (b2 - b1) + (c1 - a1) * (a2 - a1) * (b2 - b1))
                    / ((b2 - b1) * (b2 - b1) + (a2 - a1) * (a2 - a1));
            c2 = (c1 * (a2 - a1) - (b2 - b1) * (d2 - d1)) / (a2 - a1);
        }
        System.out.println("(" + c2 + ", " + d2 + ")");
        return new Point((int) c2, (int) d2);
    }
  1. 已知交点,求交点是否在该线段上
 /**
     * 已知t在a与b确定的直线上
     * 检测t点是否在a与b组成的线段上
     *
     * @param t 监测目标
     * @param a 点a
     * @param b 点b
     * @return true如果t在点a和点b组成的线段上
     */
    public static boolean isInSegment(Point t, Point a, Point b) {
        return (t.x > a.x && t.x < b.x || t.x < a.x && t.x > b.x)
                && (t.y > a.y && t.y < b.y || t.y < a.y && t.y < b.y);
    }

3.再求两点之间的距离

public static int getDistance(Point a, Point b) {
        return (int) Math.sqrt((b.y - a.y) * (b.y - a.y) + (b.x - a.x) * (b.x - a.x));
    }

4.判断一个多边形是否与小球碰撞,以三角形为例,代码中Block是阻碍物的抽象接口

public class Triangle implements Block {
    private final Point a;
    private final Point b;
    private final Point c;

    public Triangle(Point a, Point b, Point c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    @Override
    public boolean isImpact(Ball ball) {
        Point o = ball.getCenterPoint();
        Point t = GeometryUtil.getVerticalPoint(o, a, b);
        if (GeometryUtil.isInSegment(t, a, b)) {
            if (GeometryUtil.getDistance(t, o) <= (int) ball.getRadio()) {
                return true;
            }
        }
        t = GeometryUtil.getVerticalPoint(o, a, c);
        if (GeometryUtil.isInSegment(t, a, c)) {
            if (GeometryUtil.getDistance(t, o) <= (int) ball.getRadio()) {
                return true;
            }
        }
        t = GeometryUtil.getVerticalPoint(o, b, c);
        if (GeometryUtil.isInSegment(t, b, c)) {
            if (GeometryUtil.getDistance(t, o) <= (int) ball.getRadio()) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void location(int left, int top) {
        a.offset(left, top);
        b.offset(left, top);
        c.offset(left, top);
    }

    @Override
    public void draw(Canvas canvas, Paint paint) {
        canvas.drawLines(new float[]{a.x, a.y, b.x, b.y, a.x, a.y, c.x, c.y, b.x, b.y, c.x, c.y}, paint);
    }
}

不对之处,请大家指正!

你可能感兴趣的:(碰撞检测新思路)