2013-04-27 131 views
1

我有兩個矩形,r1正在移動,r2是一個固定的瓷磚。我需要知道r2(或r1)的哪一邊被擊中以確定r1應該走向哪個方向。碰撞檢測與shape.intersects(otherShape)一起工作,不幸的是這意味着r1會在r2中「下沉」幾個像素。當處理矩形的角部時,這是非常有問題的,因爲這將導致每個矩形的兩邊相交,從而通過檢查哪邊是相交的哪一邊是無效的,從而弄清楚哪一邊被擊中。碰撞檢測:碰到哪邊? [Java,Slick2D]

我們知道:

  • 位置和R1和R2
  • 速度和R1的速度和中心位置R2

所以,有了這些信息,我需要一種算法,能夠以獲得碰撞的一面。

回答

0

正方形由四個角定義,即左上角,右上角,左下角,右下角。如果你的更新/碰撞檢測足夠快,那麼下面的內容將起作用。這考慮到只有一個角落碰撞的事件(如果您的矩形旋轉或以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"); 
     } 
    } 
+0

不幸的是,我不認爲這個算法將正常工作。我期待得到被擊中的r1的一面。儘管此代碼在告訴我r1的哪個角落被擊中時很有用,但它並不告訴我哪一方被擊中。考慮r2右下角位於r1右上角的事件。從這些信息中我可以看出r1的頂部或左側被擊中,但不幸的是,它並沒有告訴我哪一個。 – user2327195 2013-04-27 16:55:49

+0

如果r1從右側移動到r2並且只有r1的右上角陷入r2(由於不同的wid和不同的y-poistions),那麼您無法知道碰撞是從右側r1還是從右側除非你考慮它來自哪個方向(速度),否則它會通過碰撞檢測來檢測其頂部。 – arynaq 2013-04-27 17:29:03

+0

我想知道你爲什麼要增加速度。不會speedX * speedX> speedY * speedY總是返回與speedX> speedY一樣的東西? – user2327195 2013-04-27 18:11:16