Lớp va chạm từ trên xuống có thể tái sử dụng


8

Gần đây tôi đã chọn monogame và đang làm việc với một trò chơi đơn giản từ trên xuống để giúp tôi bắt đầu và tìm hiểu những điều cơ bản.
Tôi đã có chuyển động và xoay để theo con chuột được sắp xếp nhưng tôi bị kẹt với các va chạm.
Những gì tôi muốn biết, về cơ bản, là hai điều:

  1. Điều gì sẽ là cách tốt nhất để xử lý va chạm? Tôi biết rằng Rectangle.Intersects(Rectangle1, Rectangle2)sẽ trả về hình chữ nhật chồng chéo, nhưng, vì chuyển động từ trên xuống nằm trên trục x / y Tôi muốn biết nơi xảy ra va chạm để tôi có thể tạo ra loại "trượt tường" nơi người chơi không nhận được mắc kẹt ở tường.
    Việc kiểm tra tọa độ x / y của người chơi với tọa độ vật thể rắn, sau đó ném người chơi về vị trí trước đó nếu anh ta đi vào giới hạn của vật thể rắn có thực sự là cách tiếp cận tốt nhất? Bạn muốn đề nghị gì?
  2. Điều gì sẽ là cách tốt nhất để áp dụng va chạm cho tất cả các vật rắn, npc, v.v.? Tôi hiện đang nghĩ đến việc tạo ra một gameObjectlớp mà tất cả các đối tượng sẽ kế thừa và chỉ xử lý các va chạm ở đó.

Cảm ơn đã đọc và hy vọng rằng ai đó có thể cho tôi một số lời khuyên.


Đối với một số suy nghĩ về câu hỏi thứ hai của bạn, hãy xem câu trả lời này về kiến ​​trúc trò chơi .
Andrew Russell

Câu trả lời:


9

Nói chung cách mà hầu hết các động cơ vật lý xử lý vấn đề này là bằng cách tách các đối tượng giao nhau .


Vì vậy, nếu các đối tượng của bạn được đại diện bởi các hình chữ nhật (còn được gọi là "Hộp giới hạn căn chỉnh trục") và chúng va chạm vào một khung nhất định như vậy:

Va chạm


Sau đó, bạn sẽ đo lượng xen kẽ trên mỗi trục. Sau đó chọn trục có lượng xen kẽ nhỏ nhất và tách các đối tượng dọc theo trục đó.

Tách rời


Sau đó, bạn sẽ đăng ký này như là một "va chạm" và áp dụng động lực thích hợp.

Ví dụ: nếu bạn muốn trượt dọc theo bức tường, bạn sẽ chỉ bằng không vận tốc trên trục mà bạn tách ra (trục X, trong hình minh họa ở trên), chỉ để lại vận tốc trên trục khác.

Nhưng bạn cũng có thể áp dụng ma sát, hoặc làm cho các vật thể bật ra.


Dưới đây là một hướng dẫn tương tác tuyệt vời cho thấy làm thế nào để làm điều này chi tiết hơn rất nhiều.

Mặc dù, nếu bạn sẽ đi xa trên con đường này (bất cứ điều gì khác hơn là va chạm AABB đơn giản), bạn có thể muốn xem xét sử dụng một công cụ hiện có như Vật lý Farseer .


Cuối cùng, một lưu ý khi thực hiện (nếu bạn không đi theo lộ trình Farseer): Rectanglesử dụng intcác giá trị, điều này không thực sự phù hợp để thực hiện vật lý trong hầu hết các trường hợp. Xem xét làm cho AABBlớp của riêng bạn mà sử dụng floatthay thế.

Câu hỏi thứ hai của bạn được trả lời khá tốt bởi câu trả lời cũ của tôi về kiến ​​trúc trò chơi ở đây , vì vậy tôi sẽ không lặp lại ở đây.


Có thể có điều gì đó tôi không hiểu, nhưng cách tiếp cận này không hoàn hảo? Tôi đã minh họa vấn đề ở đây: jmp.sh/jEW2lvR Nó sẽ dẫn đến một số hành vi kỳ lạ đôi khi.
BjarkeCK

@BjarkeCK: Vâng, bạn cần phải làm thêm để xử lý các trường hợp như vậy. Tôi không đủ thành thạo để giải thích đầy đủ cách xử lý chúng đúng cách (tôi chỉ sử dụng Farseer và gọi nó là một ngày). Có thể xem "Phần 5" của liên kết này .
Andrew Russell

1

1: Tôi cũng đang làm việc với một trò chơi hành động từ trên xuống tương đối đơn giản, và sau một tuần (-s?), Tôi đã kết thúc bằng cách sử dụng một cách tiếp cận từng bước để phát hiện và phản ứng va chạm. Lý do chính là việc sử dụng lượng xen kẽ ngắn nhất trong một số trường hợp sẽ dẫn đến việc "dịch chuyển tức thời" đến một vị trí mới mà đối tượng chuyển động không có trước đây.

vì vậy, khi một đối tượng muốn di chuyển,

  1. Tôi tạo một hộp giới hạn của đối tượng ở vị trí của đối tượng + vector moveAmount, tạo ra một loại hộp giới hạn mục tiêu
  2. sau đó tôi kiểm tra hộp giới hạn mục tiêu này xem có bất kỳ giao điểm nào với các đối tượng trò chơi, ô xếp, v.v. nếu có, tôi thêm chúng vào danh sách mới, chứa tất cả các va chạm tiềm năng cho khung hình hiện tại
  3. nếu không có giao điểm, đối tượng di chuyển. nhưng nếu có một giao lộ,
  4. Tôi chia phong trào mong muốn thành "các bước". sau đó tôi chạy một vòng lặp cho số bước tôi có. mỗi bước di chuyển đối tượng chỉ cho 1 pixel theo hướng x và y.
  5. đối với mỗi bước tôi kiểm tra mọi vị trí dự kiến ​​mới cho các va chạm, nếu không có gì, tôi thêm vectơ di chuyển của bước vào vectơ di chuyển cuối cùng.
  6. nếu có va chạm (giao nhau trả về đúng), tôi so sánh vị trí trước đó (vị trí ở bước trước) của vật thể chuyển động với vật mà nó va chạm.
  7. tùy thuộc vào vị trí trước đó, tôi dừng chuyển động dọc theo trục xung đột (ví dụ: nếu đối tượng chuyển động đến đối tượng va chạm từ phía trên, tôi đặt giá trị y của vectơ di chuyển thành 0, v.v.).
  8. Tôi lặp lại điều này cho mỗi bước liên tiếp, cộng các vectơ bước điều chỉnh lại với nhau để tạo một vectơ di chuyển được điều chỉnh cuối cùng mà tôi có thể sử dụng một cách an toàn để di chuyển đối tượng mà không có bất kỳ va chạm nào xảy ra.

Cách tiếp cận này vừa đảm bảo rằng đối tượng "bật" trở lại để sửa vị trí trước đó và nó cho phép trượt vào tường, vật thể, bất cứ điều gì.

2: Bản thân tôi sử dụng một lớp va chạm tĩnh có thể được sử dụng bởi bất cứ điều gì. nó giữ các phương pháp phát hiện va chạm và điều chỉnh véc tơ, có thể được gọi bằng khá nhiều thứ. liệu các phương thức này được gọi từ một lớp trò chơi "chính" hay bởi một lớp con đối tượng nào đó không thực sự quan trọng trong trường hợp của tôi, bởi vì lớp va chạm tạo ra một danh sách mới mỗi khung cho tất cả các hình chữ nhật mà đối tượng chuyển động đang giao nhau. những hình chữ nhật này có thể là từ gạch, trang trí, NPC, bất cứ thứ gì có ranh giới và về cơ bản là có thể va chạm. điều này có nghĩa là sự cần thiết trần trụi cho tất cả các đối tượng trò chơi có thể va chạm là có hình chữ nhật ranh giới. nếu họ có điều đó, lớp va chạm sẽ xử lý phần còn lại.

hy vọng điều này là dễ hiểu.


0

1: Tôi đã sử dụng thành công một kỹ thuật để giải quyết điều này: sử dụng tốc độ và vị trí bạn có thể khám phá ra vụ va chạm và lặp lại cho đến khi vị trí rất gần với điểm va chạm chính xác.

Đây không phải là một phần của câu trả lời cho câu hỏi đầu tiên của bạn, nhưng nếu bạn có nhiều đối tượng có thể va chạm với nhau, bạn nên sử dụng tứ giác để cải thiện hiệu suất. Có một hướng dẫn rất tốt với rất nhiều ví dụ ở đây .

2: Tôi luôn khuyên dùng Entity-Systems .

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.