Phát hiện va chạm 2D nhanh hơn


13

Gần đây tôi đang làm việc trên một game bắn súng 2d có nhịp độ nhanh và tôi đã gặp một vấn đề rất lớn. Phát hiện va chạm. Chắc chắn, nó đang làm việc, nhưng nó rất chậm. Mục tiêu của tôi là: Có rất nhiều kẻ thù trên màn hình và khiến chúng không chạm vào nhau. Tất cả kẻ thù đang đuổi theo thực thể người chơi. Hầu hết chúng đều có cùng tốc độ nên sớm muộn gì chúng cũng chiếm cùng một không gian trong khi đuổi theo người chơi. Điều này thực sự làm giảm yếu tố vui nhộn vì, đối với người chơi, có vẻ như bạn chỉ bị truy đuổi bởi một kẻ thù. Để ngăn chúng lấy cùng một không gian, tôi đã thêm một phát hiện va chạm (phát hiện 2D rất cơ bản, phương pháp duy nhất tôi biết) đó là.

Enemy class update method
    Loop through all enemies (continue; if the loop points at this object)
        If enemy object intersects with this object
            Push enemy object away from this enemy object

Điều này hoạt động tốt. Miễn là tôi chỉ có <200 thực thể kẻ thù. Khi tôi đến gần hơn 300-350 thực thể kẻ thù, tốc độ khung hình của tôi bắt đầu giảm mạnh. Đầu tiên tôi nghĩ đó là kết xuất xấu nên tôi đã gỡ bỏ cuộc gọi rút thăm của họ. Điều này chẳng giúp ích gì cả nên dĩ nhiên tôi nhận ra đó là phương pháp cập nhật. Phần nặng duy nhất trong phương pháp cập nhật của họ là phần từng kẻ thù-vòng lặp xuyên qua mọi kẻ thù. Khi tôi đến gần hơn 300 kẻ thù, trò chơi sẽ thực hiện bước lặp 90000 (300x300). Của tôi

Tôi chắc chắn phải có một cách khác để vượt qua sự phát hiện va chạm này. Mặc dù tôi không biết làm thế nào. Các trang tôi tìm thấy là về cách thực sự va chạm giữa hai đối tượng hoặc cách kiểm tra va chạm giữa một đối tượng và ô. Tôi đã biết hai điều đó.

tl; dr? Làm cách nào để tôi phát hiện va chạm giữa RẤT NHIỀU thực thể?

Chỉnh sửa nhanh: Nếu có bất kỳ trợ giúp nào, tôi đang sử dụng C # XNA.


Tôi đang tự hỏi làm thế nào bạn có được nó để đi đến 90K ở nơi đầu tiên. của tôi bị sặc ở mức 20K (mặc dù tôi đang thực hiện phát hiện SAT MTV đầy đủ). Nhưng tôi lặp qua tất cả kẻ thù là điều duy nhất dường như có thể. Tuy nhiên, điều bạn cần làm là kiểm tra xem chúng đã được kiểm tra chưa, bởi vì nếu bạn làm như bạn nói, thì mọi người sẽ được kiểm tra với mọi người hai lần.
Logic ảo tưởng

3
Đây là bản sao có thể có của gamedev.stackexchange.com/questions/39931/NH
Markus von Broady

Có một câu trả lời rất hay trong câu hỏi mà @MarkusvonBroady đã liên kết.
Cypher

Câu trả lời:


11

Bạn đã đánh vào vấn đề của mình ngay trên đầu, bạn đang kiểm tra mọi thực thể chống lại mọi thực thể khác. Những gì bạn sẽ muốn là một số loại hệ thống 'Cấp độ chi tiết' (khá giống biểu đồ cảnh rất đơn giản, bạn chỉ sử dụng nó cho những thứ khác ngoài kết xuất :)) trong đó các ứng cử viên va chạm có thể được lựa chọn tốt hơn.

Tôi thường làm ba bộ sưu tập cho các hệ thống như thế này. Và khi bạn đang nói về số lượng thực thể mà bạn đang nhắm đến, bạn thậm chí có thể cần phải đi với một biểu đồ cảnh đầy đủ cho điều này vì dữ liệu theo dõi (3 danh sách cho mỗi thực thể với một mục nhập cho mọi thực thể khác) có thể nhanh chóng thoát ra kiểm soát.

Về cơ bản mặc dù bạn có ba danh sách. Cái đầu tiên phải là một danh sách rất nhỏ các thực thể mà bạn sẽ kiểm tra với các tương tác mỗi khung. Bạn xác định điều này bởi vì chúng nằm trong phạm vi X của thực thể được đề cập. Như đã đề cập, điểm của danh sách này là chứa mọi thực thể có thể va chạm hợp lý với khung khác.

Danh sách tiếp theo là những danh sách sẽ nằm trong phạm vi bộ đệm có thể di chuyển vào phạm vi của thực thể mà không cần quá nhiều nỗ lực .. Chúng tôi sẽ gọi phạm vi này là X * 1.5 chỉ để tranh luận. Đây là danh sách cắt thời gian, trong đó bạn sẽ chỉ cập nhật một số ít chúng trên mỗi khung nhưng đảm bảo rằng bạn sẽ vượt qua chúng đủ nhanh để theo kịp sự xuất hiện của mọi thứ hoạt động trơn tru.

Danh sách thứ ba là danh sách 'mọi thứ khác' và cách để tránh danh sách này có thể có giá trị trong khi (Quét toàn bộ danh sách thực thể và có thể kiểm tra xem liệu nó có nằm trong một trong các danh sách khác trước khi tiến hành không? Tùy thuộc vào kích thước danh sách này có thể hoạt động hoặc có thể khiến mọi thứ tồi tệ hơn nhiều.) Các đối tượng trong danh sách này được kiểm tra ít nhất vì tất cả phải mất nhiều hơn một vài khung hình để được đặt vào một trong hai danh sách khác.

Những gì bạn cũng sẽ cần phải làm để duy trì điều này là khi bạn đang thực hiện các bài kiểm tra va chạm, hãy đảm bảo bạn cập nhật danh sách các thực thể đang ở trong đó. Những người di chuyển ra khỏi phạm vi nên bị hạ cấp và những người di chuyển gần hơn nên được nâng cấp thành danh sách kiểm tra tích cực hơn.

Giả sử bạn đang giữ mọi thứ đủ đơn giản, điều này sẽ phù hợp với nhu cầu của bạn. Nếu bạn có thể thêm thông tin bổ sung vào biểu đồ cảnh kết xuất hiện có (giả sử bạn có) để bạn có thể truy vấn nó để có danh sách các thực thể nằm trong phạm vi hợp lý, thậm chí còn tốt hơn vì đó là toàn bộ điểm của biểu đồ cảnh dù sao (truy cập nhanh vào danh sách dữ liệu liên quan dựa trên một vị trí). Điều này sẽ có khả năng mất nhiều công việc hơn để làm và bạn nên luôn luôn xem xét những gì bạn cần làm so với những gì bạn thực tế nên làm.

Hi vọng điêu nay co ich.


1
Đây là một câu trả lời mơ hồ. Và chúng ta có thể chấp nhận để bỏ lỡ một số va chạm ?? Đơn giản hơn nhiều, hãy sử dụng cấu trúc dữ liệu sẽ thực hiện phân vùng bề mặt cho bạn, như Quad Tree tôi nói ở đây. Ngay cả Quad Tree cũng cần một chút tinh chỉnh để tránh chi phí hoạt động, vì vậy tôi không thể tưởng tượng được sự phức tạp của "giải pháp" mà bạn nói đến. Quy tắc lập trình cơ bản: chỉ cần sử dụng đúng cấu trúc dữ liệu.
GameAlchemist

@VincentPiel Một đồ thị cảnh không phức tạp hơn cây tứ giác.
Cypher

@James: rõ ràng nó phức tạp hơn. Nếu bạn không ngại nắm bắt toàn bộ tốc độ của QuadTree, bạn có thể nhận được một lib QuadTree trên mạng và khiến nó hoạt động hoàn hảo trong vài giờ. Không có câu hỏi nào như: tôi sẽ đưa gì vào danh sách đầu tiên, thứ hai, thứ ba, làm thế nào để tôi quyết định đưa một thực thể vào danh sách khác ... và không có sự va chạm nào bị bỏ lỡ. Tại sao nên sử dụng xe đạp khi bạn có thể có một chiếc xe hơi?
GameAlchemist

@VincentPiel Tôi nghĩ bạn có ý muốn @ bình luận của bạn cho Cypher thay vì tôi ở đây. Dù sao, một cây tứ giác chỉ là một loại biểu đồ cảnh và bạn phải nhớ rằng bạn đang chạy ở X khung hình mỗi giây. Nếu bạn nhận thấy các va chạm bị bỏ lỡ thì bạn cần điều chỉnh ngưỡng phạm vi của mình để cân bằng tốt hơn mọi thứ. Giải pháp của tôi chỉ là một cách tiếp cận rất đơn giản để đảm bảo bạn chỉ kiểm tra mọi thứ ở mọi khung hình có khả năng bị va chạm và sau đó thực hiện cập nhật nền / giới hạn trên phần còn lại để xem chúng có đủ điều kiện ưu tiên cao hơn không.
James

6

Bạn phải xử lý các xung đột với cấu trúc dữ liệu được sắp xếp, do đó bạn có thể có n * log (n) lần thay vì n ^ 2 khủng khiếp. Và n * log (n) gần như tuyến tính như bạn có thể biết. Một ví dụ (cổ điển) là một hình tứ giác, có một hướng dẫn khá đơn giản và được viết tốt ở đây, với đồ họa và mã (Java):

http://gamedev.tutsplus.com/tutorials/imcellenceation/quick-tip-use-quadtrees-to-detect-labilities-collutions-in-2d-space/

Rq: khá dễ dàng để tìm thấy một triển khai cho QuadTrees bằng bất kỳ ngôn ngữ nào. Tuy nhiên, bạn phải suy nghĩ về "độ chi tiết" phù hợp cho cây và kích thước cây càng lớn, chúng ta càng có nhiều thực thể không nằm gọn trong một nút.
Rq 2: vì phân vùng không gian của bạn chỉ được thực hiện để phát hiện va chạm, bạn có quyền tự do hoàn hảo để phân chia không gian theo ý muốn. Ví dụ, tôi sẽ không chia thành bốn phần bình thường mà thay vào đó tôi sẽ sử dụng baricenter của các thực thể cấp hiện tại làm trung tâm cho phân chia mới. 1) thuật toán vẫn là n * log (n), 2) bạn mất khả năng 'xây dựng lại' cảnh bên ngoài cây - nhưng bạn không quan tâm- và 3) bạn có một cây cân bằng hơn, ít chi phí hơn .
Rq3: Khi bạn có cây của mình, một 'va chạm' giữa màn hình và các thực thể cung cấp cho bạn ... các thực thể có thể nhìn thấy !! trong một thời gian giống như log (n), vậy tại sao không nếu n lớn? (trường hợp xấu nhất rõ ràng là một thời gian trong n cho phương pháp này.)


Vâng, một cây quad chỉ là một loại biểu đồ cảnh thực sự. Tôi chỉ luôn cho rằng những người ở đây muốn tự viết mọi thứ, không sử dụng thư viện của người khác trong trường hợp tại sao dừng lại ở cây bốn lá, chỉ cần tìm một thư viện va chạm hoàn chỉnh.
James

0

Cây phân vùng không gian nhị phân, quadtree, octree (cho 3D) là những cây có thể bạn có thể tạo (hoặc duy trì, nếu bạn có tham vọng) tại mỗi cuộc gọi cập nhật cho mọi đối tượng bạn muốn áp dụng.


3
Điều này phù hợp hơn để được bình luận. Xem xét thêm nhiều hơn vào câu trả lời của bạn.

0

Tôi khá ngây thơ khi nói về cây quad hoặc oct. Nhưng tôi nghĩ rằng phương pháp này nên làm:

Bạn sẽ cần phải sửa đổi cấu trúc / lớp người chơi. Thêm một mảng / vectơ con trỏ vào cấu trúc trình phát khác.

Mỗi giây kiểm tra khoảng cách giữa hai người chơi. Nếu nó thấp đến mức có thể đạt được trong vòng 1 giây thì hãy thêm con trỏ của người chơi đó vào mảng va chạm của người chơi hiện tại.

Bây giờ chỉ kiểm tra sự va chạm giữa những người chơi trong danh sách của nhau.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.