java - 碰撞检测 : What side was hit? [Java、Slick2D]

标签 java collision-detection slick2d bounding-box

我有两个矩形,r1 是移动的,r2 是静止的图 block 。我需要知道 r2 (或 r1)的哪一侧被击中,以确定 r1 ​​应该朝哪个方向移动。碰撞检测与 shape.intersects(otherShape) 一起使用,不幸的是,这意味着 r1 将“下沉”r2 内的几个像素。在处理矩形的角时,这是非常有问题的,因为这将导致每个矩形的两条边相交,从而通过检查哪条边相交来确定哪条边被击中是无效的。

我们所知道的:

  • r1 和 r2 的位置和中心位置
  • r1 和 r2 的速度和速度

因此,鉴于这些信息,我需要一种能够获得碰撞侧面的算法。

最佳答案

正方形由四个角定义,即左上角、右上角、左下角、右下角。如果您的更新/碰撞检测足够快,那么以下内容将起作用。这考虑到只有一个角发生碰撞的事件(如果您的矩形在 2D 中旋转或移动)。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JComponent;
 import javax.swing.JFrame;

public class TestMovingRect extends JComponent {
JFrame frame;
Rectangle2D r1;
Rectangle2D r2;
int speedX, speedY;
int width = 20;
int height = 20;

public static void main(String[] args) {
    new TestMovingRect();
}

public TestMovingRect() {
    r1 = new Rectangle2D.Double(0, 0, width, height);
    r2 = new Rectangle2D.Double(200, 0, width, height);
    speedX = 1;
    frame = new JFrame();
    frame.setSize(500, 500);
    frame.add(this);
    frame.setVisible(true);
    loop();
}

public void tick(){
    System.out.println("Old r1: " + r1.getX() + "," + r1.getY());
    double x = r1.getX();
    double y = r1.getY();
    r1.setRect(x + speedX, y + speedY, 10, 10);
    System.out.println("New r1: " + r1.getX() + "," + r1.getY());

}

private void loop() {
    while (true){
        tick();
        sleep();
        checkIntersect();
        frame.validate();
        frame.repaint();
    }
}

private void checkIntersect() {
    Point2D upperLeft = new Point2D.Double(r1.getX(), r1.getY());
    Point2D upperRight = new Point2D.Double(r1.getX() + r1.getWidth(),
            r1.getY());
    Point2D lowerLeft = new Point2D.Double(r1.getX(), r1.getY()
            + r1.getHeight());
    Point2D lowerRight = new Point2D.Double(r1.getX() + r1.getWidth(),
            r1.getY() + r1.getHeight());

    if (r2.contains(upperRight)){
        System.out.println("UpperRight hit");
        //Do stuff
    }

    if (r2.contains(lowerRight)) {
        System.out.println("lowerRight hit");
        // Do stuff
    }

    if (r2.contains(lowerLeft)) {
        System.out.println("LowerLeft hit");
        // Do stuff
    }

    if (r2.contains(upperLeft)) {
        System.out.println("UpperLeft hit");
        // Do stuff
    }
}

private void sleep() {
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

}

@Override
public void paintComponent(Graphics g) {
    // TODO Auto-generated method stub
    super.paintComponents(g);
    g.setColor(Color.blue);
    g.fillRect((int) r1.getX(), (int) r1.getY(), (int) r1.getWidth(),
            (int) r1.getHeight());
    g.setColor(Color.red);
    g.fillRect((int) r2.getX(), (int) r2.getY(), (int) r2.getWidth(),
            (int) r2.getHeight());
}


 }

另一种(更简单的)方法是对矩形的速度进行插值。如果它向右移动并且相交,那么您就知道它一定撞到了右侧。但是,如果您的矩形在 2D 中旋转或移动,您将增加复杂性,上面的代码也同样可以。

编辑:到您的评论

if (r2.contains(upperRight)){
        if (speedX * speedX > speedY * speedY) {
            System.out.println("I hit on the right side");
        }

        else if (speedY * speedY > speedX * speedX) {
            System.out.println("I  hit on the topside");
        }

        else if (speedX * speedX == speedY * speedY) {
            System.out
                    .println("I hit on a 45 degree diagonal, side is ambigious, please decide for me");
        }
    }

关于java - 碰撞检测 : What side was hit? [Java、Slick2D],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16254184/

相关文章:

java - 以编程方式加载 Java cacert 时出现授权错误

java - Java中的非阻塞IO解决方案

ios - swift中有无碰撞测试的函数吗?

Java NullPointerException Collision 是来源,但不确定为什么

java - 当您必须替换许多 fragment 时,保存 fragment 状态的最佳实践方法是什么?

java - JpaSpecificationExecutor<T> 似乎不像 JpaRepository<T, I> 那样工作

ios - Sprite Kit 碰撞错误 - Swift

Android:如何检测两个圆之间的碰撞

java - 声明 Java 对象数组的数组时遇到问题

java - Slick 变得非常慢但只能绘制矩形