2013-08-07 25 views
5

Tôi đang tạo một trò chơi dựa trên vật lý đơn giản trong java và tôi bị kẹt trong việc triển khai các phương pháp phát hiện xung đột. Tôi có một số lớp học được thừa kế từ một hình dạng lớp cơ sở. Tôi lưu trữ tất cả các đối tượng có thể nhìn thấy trong một arraylist của lớp hình dạng. Tôi đã tạo ra một số phương pháp phát hiện va chạm cho mọi va chạm có thể có của các đối tượng. Khi tôi bắt đầu thực hiện những phương pháp tôi đã kết thúc với một mã như thế này:Cách tốt nhất để thực hiện dò tìm va chạm trong oop

private void collision_detector(Shape s1,Shape s2){ 

    if(s1.getClass()==Ball.class) 
     if(s2.getClass() == Block.class) collision_detector((Ball)s1,(Block)s2); 
     else collision_detector((Ball)s1,(Ball)s2); 
    else if(s1.getClass()==Block.class) 
     if(s2.getClass()==Block.class) collision_detector((Block)s1,(Block)s2); 
     else collision_detector((Ball)s2,(Block)s1);   
} 

Nó chỉ không cảm thấy như một cách đúng đắn để thực hiện việc phát hiện va chạm, vì tôi phải cập nhật phương thức này để kiểm tra cho mỗi thể kết hợp mỗi khi tôi thêm một hình dạng mới như hình tam giác hoặc hình lục giác. Tôi biết một chút về các mẫu Khách truy cập. Nhưng có cách nào tốt hơn để làm điều này?

+2

Tôi vẫn đang làm việc về câu hỏi chính của bạn, nhưng một điều, bạn có thể muốn xem xét sử dụng 'if (s1 instanceof Ball)' thay vì 'getClass()'. Đó là một cách tiêu chuẩn hơn một chút và cách gõ hiệu quả để làm điều này. – snickers10m

+0

Đây có phải là các lớp học của riêng bạn không? ('Shape',' Ball', 'Block') Nếu không, bạn có thể tìm thấy phát hiện xung đột được tạo sẵn trong bất kỳ API nào bạn đang sử dụng. – snickers10m

+0

Không chắc chắn hiệu suất quan trọng như thế nào, nhưng bạn có thể đăng ký danh sách thuật toán va chạm (hoặc sử dụng bản đồ được khóa bằng các lớp Shape) sau đó tìm thuật toán thích hợp trong danh sách cho các lớp hình dạng. Xem ví dụ mới được thêm vào câu trả lời của tôi bên dưới. –

Trả lời

3

Nếu bạn không nhớ đặt mã phát hiện va chạm trong các đối tượng bản thân, bạn có thể loại bỏ một bên kiểm tra bằng cách làm một cái gì đó như:

public abstract class Shape { 
    public abstract boolean collidesWith (Shape s); 
} 

public class Ball extends Shape { 
    @Override public boolean collidesWith (Shape s) { 
     if (s instanceof Block) 
      return Collision.blockBall((Block)s, this); 
     else if (s instanceof Ball) 
      return Collision.ballBall(this, (Ball)s); 
     else 
      return false; 
    } 
} 

public class Block extends Shape { 
    @Override public boolean collidesWith (Shape s) { 
     if (s instanceof Block) 
      return Collision.blockBlock(this, (Block)s); 
     else if (s instanceof Ball) 
      return Collision.blockBall(this, (Ball)s); 
     else 
      return false; 
    } 
} 

public class Collision { 
    public static boolean blockBlock (Block a, Block b) { ... } 
    public static boolean blockBall (Block a, Ball b) { ... } 
    public static boolean ballBall (Ball a, Ball b) { ... } 
} 

Đó cũng mang đến cho bạn sự tự do để thực hiện các thuật toán va chạm cho sự kết hợp nhất định của hình dạng trong hình dạng chính nó nếu cần thiết - bạn thậm chí có thể loại bỏ va chạm và chỉ cần làm ví dụ Block.collideWithBall, Block.collideWithBlock, và Ball.collideWithBlock, kêu gọi những người như thích hợp, ví dụ .:

public abstract class Shape { 
    public abstract boolean collidesWith (Shape s); 
} 

public class Ball extends Shape { 
    @Override public boolean collidesWith (Shape s) { 
     if (s instanceof Block) 
      return collidesWithBlock((Block)s); 
     else if (s instanceof Ball) 
      return collidesWithBall((Ball)s); 
     else 
      return false; 
    } 
    public boolean collidesWithBall (Ball b) { 
     ... 
    } 
    public boolean collidesWithBlock (Block b) { 
     ... 
    } 
} 

public class Block extends Shape { 
    @Override public boolean collidesWith (Shape s) { 
     if (s instanceof Block) 
      return collidesWithBlock((Block)s); 
     else if (s instanceof Ball) 
      return ((Ball)s).collidesWithBlock(this); 
     else 
      return false; 
    } 
    public boolean collidesWithBlock (Block b) { 
     ... 
    } 
} 

Cá nhân, tôi giống như sau này tốt hơn, vì nó giữ đang va chạm chứa trong các lớp học có liên quan. Lưu ý rằng Block.collidesWithBall là không cần thiết, vì Ball.collidesWithBlock có thể được sử dụng.

Bạn vẫn phải cập nhật mã ở trên mỗi khi bạn thêm hình dạng mới. Nếu hiệu suất không phải là một vấn đề, bạn có thể làm một cái gì đó như thế này cũng như:

public abstract class CollisionAlgorithm { 
    public abstract boolean canCollide (Class<? extends Shape> a, Class<? extends Shape> b); 
    public abstract boolean collide (Shape a, Shape b); 
} 

public class Collider { 

    private static final List<CollisionAlgorithm> algorithms; 

    public static void registerAlgorithm (CollisionAlgorithm a) { 
     algorithms.append(a); 
    } 

    public static CollisionAlgorithm findAlgorithm (Class<? extends Shape> a, Class<? extends Shape> b) { 
     for (CollisionAlgorithm algo : algorithms) 
      if (algo.canCollide(a, b)) 
       return algo; 
     return null; 
    } 

    public static boolean collide (Shape a, Shape b) { 
     if (a == null || b == null) 
      return false; 
     CollisionAlgorithm algo = findAlgorithm(a.getClass(), b.getClass()); 
     if (algo != null) 
      return algo.collide(a, b); 
     algo = findAlgorithm(b.getClass(), a.getClass()); // try swapped order 
     if (algo != null) 
      return algo.collide(b, a); 
     return false; 
    } 

} 

// usage: first register algorithms 
Collider.registerAlgorithm(new BallBallAlgorithm()); 
Collider.registerAlgorithm(new BallBlockAlgorithm()); 
Collider.registerAlgorithm(new BlockBlockAlgorithm()); 

// then 
Shape myShape1 = ...; 
Shape myShape2 = ...; 
boolean collide = Collider.collide(myShape1, myShape2); 

Xin lưu ý: Tôi gõ này ở đây một cách nhanh chóng, và nó có nghĩa là để minh họa cho một khái niệm - nhiều cải tiến có thể được thực hiện. Ví dụ: Ví dụ, một bản đồ có thể được sử dụng với hai lớp Hình dạng làm chìa khóa để cải thiện hiệu suất, hoặc CollisionAlgorithm có thể được cung cấp các tham số chung để loại bỏ nhu cầu đúc Hình dạng. Tuy nhiên, hãy nhớ, phương pháp này yêu cầu tra cứu trong vùng chứa thuật toán mỗi lần bạn cần thực hiện kiểm tra xung đột.

+0

Đã thêm tùy chọn cuối cùng. –

Các vấn đề liên quan