Java實現矩形碰撞檢測
本文實例為大傢分享瞭Java實現矩形碰撞檢測的具體代碼,供大傢參考,具體內容如下
第1種方法:通過檢測一個矩形的4個頂點是否在另一個矩形的內部來完成。
通常由x和y坐標以及長度和寬度來確定一個矩形,因此又可以利用這四個參數來確定是否發生瞭碰撞。
相交的情況下一定會發生碰撞,如下圖:
還有一類特殊的相交情況,就是重疊,如下圖:
所以開發的碰撞檢測類如下:
public class Actor { int x, y, w, h;// 分別是x和y坐標,寬度和高度,構成一個矩形 public Actor() { } public Actor(int x, int y, int w, int h) { this.x = x; this.y = y; this.w = w; this.h = h; } public int getX() { return x; } public int getY() { return y; } public int getActorWidth() { return w; } public int getActorHeight() { return h; } @Override public String toString() { return "Actor{" + "x=" + x + ", y=" + y + ", w=" + w + ", h=" + h + '}'; } public boolean isCollidingWith(int px, int py) { // px和py分別傳入的是x坐標和y坐標 // 等號的情況就是考慮垂直重疊和水平重疊的情況 // 考慮的情況就是傳入的坐標是否在當前的矩形范圍內,隻要滿足下面所有條件就表示傳入的坐標在當前矩形范圍內,返回true if (px >= getX() && px < getX() + getActorWidth() && py >= getY() && py < getY() + getActorHeight()) { return true; } return false; } // 碰撞檢測,發生碰撞返回true,否則返回false public boolean isCollidingWith(Actor another) { // 判斷矩形隻要有任何一個點在另一個Actor所表示的矩形范圍內,就表示發生瞭碰撞 if (isCollidingWith(another.getX(), another.getY()) || isCollidingWith(another.getX() + another.getActorWidth(), another.getY()) || isCollidingWith(another.getX(), another.getY() + another.getActorHeight()) || isCollidingWith(another.getX() + another.getActorWidth(), another.getY() + another.getActorHeight())) { return true; } return false; } public static void main(String[] args) { Actor actor = new Actor(10, 10, 100, 150); Actor another = new Actor(20, 50, 100, 150); boolean collidingWith = actor.isCollidingWith(another); System.out.println(collidingWith); } }
上面測試代碼你不能很好的觀察是否發生矩形碰撞瞭,所以寫瞭下面這個界面,可以通過ASWD操作左邊的矩形進行移動,通過上下左右鍵操作右邊的矩形進行移動,效果如下圖:
代碼如下:
class TestPanel extends JPanel implements KeyListener { private int x1 = 20, y1 = 20, x2 = 160, y2 = 20, width = 100, height = 100; public TestPanel() { // 設置焦點並且添加鍵盤事件監聽器 setFocusable(true); addKeyListener(this); } @Override public void paint(Graphics g) { // 在進行繪制之前,一定要清除之前的圖形 g.clearRect(0, 0, this.getWidth(), this.getHeight());// 先清除屏幕上原來的畫 g.drawRect(x1, y1, width, height); g.drawRect(x2, y2, width, height); } @Override public void keyTyped(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { // 處理第一個矩形的移動 switch (e.getKeyCode()) { case KeyEvent.VK_A:// 'A'鍵 x1 -= 5; break; case KeyEvent.VK_D:// 'D'鍵 x1 += 5; break; case KeyEvent.VK_W:// 'W'鍵 y1 -= 5; break; case KeyEvent.VK_S://'S'鍵 y1 += 5; break; case KeyEvent.VK_LEFT://'LEFT'鍵 x2 -= 5; break; case KeyEvent.VK_RIGHT:// 'RIGHT'鍵 x2 += 5; break; case KeyEvent.VK_UP:// 'UP'鍵 y2 -= 5; break; case KeyEvent.VK_DOWN:// 'DOWN'鍵 y2 += 5; break; } repaint();// 修改坐標後,重繪圖形 // 判斷是否碰撞,輸出信息 Actor actor = new Actor(x1, y1, width, height); Actor another = new Actor(x2, y2, width, height); System.out.println("是否碰撞:" + (actor.isCollidingWith(another) || another.isCollidingWith(actor)) + "| " + actor + "| " + another); } @Override public void keyReleased(KeyEvent e) { } } public class Demo { public static void main(String[] args) { JFrame frame = new JFrame(); frame.setLocation(200, 200); frame.setSize(500, 500); TestPanel panel = new TestPanel(); frame.setContentPane(panel); frame.setVisible(true); frame.setResizable(false); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }
第2種方法:從相反的角度考慮,以前是處理什麼時候相交,現在處理什麼時候不會相交。如兩個矩形a和b來判斷4條邊,假如a矩形在左邊,b矩形在右邊,那麼可以判斷左邊a矩形的右邊界在b矩形的左邊界之外,同理,a的上邊界需要在b的下邊界以外,4條邊都判斷,則可以知道a矩形是否與b矩形相交。
方法如下:
/** * 判斷兩個矩形是否會發生碰撞 * * @param ax 矩形a的x坐標 * @param ay 矩形a的y坐標 * @param aw 矩形a的寬度 * @param ah 矩形a的高度 * @param bx 矩形b的x坐標 * @param by 矩形b的y坐標 * @param bw 矩形b的寬度 * @param bh 矩形b的高度 * @return 如果發生碰撞則返回true,否則返回false */ public boolean isCollidingWith(int ax, int ay, int aw, int ah, int bx, int by, int bw, int bh) { if (ay > by + bh || by > ay + ah || ax > bx + bw || bx > ax + aw) { return false; } return true; }
第3種方法:是方法2的變異,我們保存兩個矩形的左上和右下兩個坐標的坐標值,然後對兩個坐標的一個對比就可以得出兩個矩形是否相交。
/** * rect1[0]:矩形1左上角x坐標 * rect1[1]:矩形1左上角y坐標 * rect1[2]:矩形1右下角x坐標 * rect1[3]:矩形1右下角y坐標 * rect2[0]:矩形2左上角x坐標 * rect2[1]:矩形2左上角y坐標 * rect2[2]:矩形2右下角x坐標 * rect2[3]:矩形2右下角y坐標 * * @param rect1 第一個矩形的左上角坐標和右下角坐標數組 * @param rect2 第二個矩形的左上角坐標和右下角坐標數組 * @return 如果發生碰撞則返回true,否則返回false */ public static boolean isCollidingWith(int rect1[], int rect2[]) { if (rect1[0] > rect2[2]) { return false; } if (rect1[2] < rect2[0]) { return false; } if (rect1[1] > rect2[3]) { return false; } if (rect1[3] < rect2[1]) { return false; } return true; }
最後Actor類的完整代碼如下:
public class Actor { int x, y, w, h;// 分別是x和y坐標,寬度和高度,構成一個矩形 public Actor() { } public Actor(int x, int y, int w, int h) { this.x = x; this.y = y; this.w = w; this.h = h; } public int getX() { return x; } public int getY() { return y; } public int getActorWidth() { return w; } public int getActorHeight() { return h; } @Override public String toString() { return "Actor{" + "x=" + x + ", y=" + y + ", w=" + w + ", h=" + h + '}'; } public boolean isCollidingWith(int px, int py) { // px和py分別傳入的是x坐標和y坐標 // 等號的情況就是考慮垂直重疊和水平重疊的情況 // 考慮的情況就是傳入的坐標是否在當前的矩形范圍內,隻要滿足下面所有條件就表示傳入的坐標在當前矩形范圍內,返回true if (px >= getX() && px < getX() + getActorWidth() && py >= getY() && py < getY() + getActorHeight()) { return true; } return false; } // 碰撞檢測,發生碰撞返回true,否則返回false public boolean isCollidingWith(Actor another) { // 判斷矩形隻要有任何一個點在另一個Actor所表示的矩形范圍內,就表示發生瞭碰撞 if (isCollidingWith(another.getX(), another.getY()) || isCollidingWith(another.getX() + another.getActorWidth(), another.getY()) || isCollidingWith(another.getX(), another.getY() + another.getActorHeight()) || isCollidingWith(another.getX() + another.getActorWidth(), another.getY() + another.getActorHeight())) { return true; } return false; } /** * 判斷兩個矩形是否會發生碰撞 * * @param ax 矩形a的x坐標 * @param ay 矩形a的y坐標 * @param aw 矩形a的寬度 * @param ah 矩形a的高度 * @param bx 矩形b的x坐標 * @param by 矩形b的y坐標 * @param bw 矩形b的寬度 * @param bh 矩形b的高度 * @return 如果發生碰撞則返回true,否則返回false */ public boolean isCollidingWith(int ax, int ay, int aw, int ah, int bx, int by, int bw, int bh) { if (ay > by + bh || by > ay + ah || ax > bx + bw || bx > ax + aw) { return false; } return true; } /** * isCollidingWith方法的重載方法 * * @param a * @param b * @return */ public boolean isCollidingWith(Actor a, Actor b) { return isCollidingWith(a.getX(), a.getY(), a.getActorWidth(), a.getActorHeight(), b.getX(), b.getY(), b.getActorWidth(), b.getActorHeight()); } /** * rect1[0]:矩形1左上角x坐標 * rect1[1]:矩形1左上角y坐標 * rect1[2]:矩形1右下角x坐標 * rect1[3]:矩形1右下角y坐標 * rect2[0]:矩形2左上角x坐標 * rect2[1]:矩形2左上角y坐標 * rect2[2]:矩形2右下角x坐標 * rect2[3]:矩形2右下角y坐標 * * @param rect1 第一個矩形的左上角坐標和右下角坐標數組 * @param rect2 第二個矩形的左上角坐標和右下角坐標數組 * @return 如果發生碰撞則返回true,否則返回false */ public static boolean isCollidingWith(int rect1[], int rect2[]) { if (rect1[0] > rect2[2]) { return false; } if (rect1[2] < rect2[0]) { return false; } if (rect1[1] > rect2[3]) { return false; } if (rect1[3] < rect2[1]) { return false; } return true; } public static void main(String[] args) { Actor actor = new Actor(10, 10, 100, 150); Actor another = new Actor(20, 50, 100, 150); boolean collidingWith = actor.isCollidingWith(another); System.out.println(collidingWith); } }
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。