2012-07-13 38 views
9

Tôi đang tạo một trò chơi 2D trong Java bằng cách sử dụng thư viện Java2D để vẽ và tôi thực sự cần một đối tượng Đa giác chính xác mà tôi có thể sử dụng để vẽ các đối tượng trò chơi và phát hiện va chạm trên chúng . Thật không may, đối tượng Polygon của Java chỉ có độ chính xác int, và không có Polygon2D tương đương như với Rectangle và Rectangle2D. Tôi đã làm đủ nghiên cứu để thấy rằng tôi có một vài lựa chọn, nhưng không ai trong số họ có vẻ rất tốt.Thực hiện Polygon2D trong Java 2D

  1. Sử dụng Path2D. Theo một nhà phát triển Java đăng trong this forum, việc thiếu Polygon2D là một sự giám sát, nhưng thay thế được đề xuất của nó là Path2D. Thật không may, Path2D không cung cấp một cách để truy cập các đỉnh hoặc cạnh riêng lẻ của nó, mà tôi cần để phát hiện xung đột (đặc biệt là tôi cần phải có một trực giao vectơ cho mỗi cạnh).

  2. Triển khai Polygon2D của riêng mình triển khai giao diện Hình dạng để tôi vẫn có thể chuyển giao cho Graphics2D.draw(Shape). Điều này có vẻ như nó sẽ khá khó khăn. Giao diện Hình dạng yêu cầu các phương pháp khó thực hiện như contains(Rectangle2D)getPathIterator(AffineTransform). Đối với getPathIterator nói riêng, có vẻ như để thực hiện nó, tôi cần trả về một đối tượng kiểu PathIterator, nhưng không có sự triển khai cụ thể nào của giao diện PathIterator có sẵn trong các gói AWT công khai.

  3. Wrap Path2D trong một đối tượng "ghi nhớ" các đỉnh riêng lẻ và cung cấp chúng cho khách hàng. Điều này làm việc cho tôi khi tôi cần một Vùng nhớ hình dạng thành phần của nó: Tôi bọc nó trong một lớp CompoundShape đã triển khai giao diện Shape và chuyển tiếp tất cả các phương thức Shape tới việc thực hiện Area của chúng, trong khi vẫn theo dõi từng Shape đã được thêm vào Khu vực trong một ArrayList. Vấn đề với điều này là nếu tôi theo dõi các đỉnh riêng lẻ trong hai mảng float s, không có cách nào để hiển thị chúng cho người dùng mà không có khả năng người dùng thay đổi các đỉnh - và vì điều đó sẽ xảy ra khi truy cập mảng trực tiếp , Path2D nội bộ sẽ không được thông báo về các thay đổi.

  4. Sao chép Polygon.java. Mã nguồn thực tế của lớp Polygon của Java có sẵn trên grepcode.com và tôi có thể chỉ cần thay thế các liên quan đến đỉnh int s bằng số float trong suốt để lấy một Polygon2D. Thật không may, khi tôi đã thử điều này, dòng import sun.awt.geom.Crossings; đã ném một lỗi trình biên dịch nói rằng "Các loại Crossings không thể truy cập do hạn chế trên thư viện cần thiết C: \ Program Files \ Java \ jre7 \ lib \ rt.jar." Theo this question điều đó xảy ra vì thỏa thuận cấp phép của Sun ngăn bạn thay thế các lớp Java lõi bằng chính bạn, nhưng Đa giác không cố gắng làm điều đó - nó đơn giản tạo ra một đối tượng kiểu sun.awt.geom.Crossings, không thay thế hoặc mở rộng xảy ra và tôi chắc chắn đã đặt bản sao Đa giác của mình trong một gói không được gọi là "java".

Cách tốt nhất để tiếp tục điều này là gì? Tôi muốn đánh giá cao một trong hai đề xuất về cách làm cho một trong các tùy chọn này hoạt động hoặc ý tưởng cho một tùy chọn khác không có vấn đề trong cuộc gặp gỡ này.

+0

Tìm kiếm [java Polygon2D] (https://www.google.com/search?q=java+polygon2d&ie=utf-8&oe=utf-8&client=ubuntu&channel=fs) trên google đã cho tôi [trang web này] (http : //www.koders.com/java/fid058B5904198EB5BA18B9B086CC3B953F96CD2750.aspx) là một 'Polygon2D' sử dụng độ chính xác kép. – dacwe

+1

Có vẻ như mã Polygon2D cũng sử dụng sun.awt.geom.Crossings, vì vậy nó sẽ có cùng một vấn đề như nỗ lực của tôi để sao chép 'Đa giác' và thay đổi nó để sử dụng' float '. – Edward

Trả lời

5

Tôi cũng khuyên bạn nên Path2D. GeneralPath là lớp cũ; không sử dụng nó.

Path2D không cung cấp quyền truy cập vào các giá trị đỉnh, mặc dù nó là một đường vòng.Bạn cần phải sử dụng một PathIterator:

PathIterator pi = path.getPathIterator(null); 
float[] value = new float[6]; 
float x = 0, y = 0; 

while (!pi.isDone()) { 
    int type = pi.currentSegment(values); 
    if (type == PathIterator.SEG_LINETO) { 
     x = values[0]; 
     y = values[1]; 
    } 
    else if (type == PathIterator.SEG_CLOSE) { 
     x = 0; 
     y = 0; 
    } 
    else { 
     // SEG_MOVETO, SEG_QUADTO, SEG_CUBICTO 
    } 
    pi.next(); 
} 

Khi bạn đã sẵn sàng để có được ưa thích, bạn có thể mở rộng mà khác để hỗ trợ các đường cong bậc hai và khối. Tôi cho rằng bạn không cần những người vào thời điểm này khi bạn đang nói về đa giác.

Ngoài ra, Path2D còn có một số phương pháp tĩnh tiện dụng để kiểm tra xem đường dẫn intersects có hình chữ nhật hay không và đường dẫn contains hình chữ nhật hoặc điểm. Đáng buồn thay, không có phương pháp để thử nghiệm cho một con đường giao nhau hoặc có chứa một con đường khác.

+1

Tôi thử nghiệm cho giao lộ Path2D/Path2D và ngăn chặn bằng cách lặp qua từng phân đoạn của một đường dẫn và, đối với từng phân đoạn như vậy, lặp qua từng đoạn của đường dẫn khác. Đó là O (n^2), nhưng tôi nghĩ điều đó là không thể tránh khỏi. Đối với mỗi hai phân đoạn (một từ mỗi đường dẫn), tôi kiểm tra giao lộ. Nếu không có giao lộ giữa hai phân đoạn, tôi sẽ kiểm tra một điểm từ mỗi đường dẫn được chứa bên trong đường khác. Nếu cả hai bài kiểm tra đều thất bại, thì cả hai đường đều không giao nhau, cũng không bao quanh cả hai. –

0

Bạn có thể sử dụng thư viện của bên thứ ba không? Nếu có, tôi có thể đề xuất sử dụng lớp học Slick 2D Polygon. Những gì tôi sẽ làm là nội bộ, sử dụng lớp này cho Đa giác thực tế của bạn để kiểm tra giao lộ với contains và sau đó khi bạn cần vẽ, chỉ cần đúc các giá trị float tới int và vẽ Đa giác Java2D.

Tôi biết điều này có thể không phải là giải pháp tối ưu, nhưng nó có thể phù hợp với những gì bạn đang làm.

0

Có thể có nội bộ của đa giác ở một tỷ lệ khác?

Nhân với số lượng lớn và được nhập vào int khi viết cho nó, chia cho cùng một số lượng lớn khi đọc?