最近做一個彈珠游戲菠发,核心就是碰撞檢測,網(wǎng)上也看了一些資料贺嫂,無奈悟性太低滓鸠,理解不了什么投影法等,靜下心來第喳,自己也琢磨了一個思路糜俗。
游戲的場景是這樣:在一個平面上有一個矩形框,框內有一個圓形彈珠曲饱,還有任意多邊形悠抹,如圖要檢測一個多邊形與該小球是否碰撞,我的思路是:
- 對于多邊形每一條邊扩淀,通過小球的圓心做垂直線楔敌,如果垂直線的長度小于或等于小球的半徑則認為小球與該邊碰撞
- 對于多邊形每一個頂點,與小球的圓心的距離小于或等于小球的半徑則認為小球與該邊碰撞
邊界的碰撞檢測是非常簡單的驻谆,判斷小球的左右上下是否等于邊框的或左或右或上或下
下面細說代碼
- 通過圓心求任意直線的垂直線的交點
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);
}
- 已知交點勺卢,求交點是否在該線段上
/**
* 已知t在a與b確定的直線上
* 檢測t點是否在a與b組成的線段上
*
* @param t 監(jiān)測目標
* @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);
}
}
不對之處值漫,請大家指正!