Làm thế nào để đối phó với va chạm góc trong 2D?


22

Tôi đang viết một trò chơi XNA 2d từ trên xuống. Vì đây là lần đầu tiên tôi cố gắng tự viết vật lý và va chạm để học nó.

Bất cứ khi nào người chơi của tôi viết nhân vật cố gắng di chuyển vào vị trí mà giới hạn của nó giao nhau với mép tường, tôi sẽ tìm ra một góc nảy (góc tới = góc phản chiếu) và tôi làm cho người chơi bật ra khỏi tường và tránh va chạm .

Tôi đang gặp khó khăn trong việc tìm ra cách xử lý tình huống sprite của tôi giao nhau với hai cạnh tường đồng thời, ví dụ như nó va vào một góc.

va chạm góc

Mã của tôi hiện cho tôi biết rằng hai cạnh tường đã được giao nhau nhưng không phải là cạnh nào nó sẽ chạm đầu tiên và do đó cạnh nào bị bật ra.

Bài kiểm tra toán học để chọn cạnh nào bị bật ra? Thật đơn giản để nhìn thấy khi nhìn vào nó nhưng tôi đang vật lộn để tìm ra bài kiểm tra toán cho nó.



Cảm ơn Tetrad. Tôi đã nhìn thấy cái đó nhưng có vẻ như quả bóng sẽ hành xử khác với vấn đề hình chữ nhật của tôi. Trong trường hợp được minh họa ở trên, hình chữ nhật sprite sẽ chạm vào cạnh dưới của bức tường và bật ra khỏi nó. Các cạnh bên của bức tường sẽ không bao giờ đi vào phương trình. Tôi chỉ không biết làm thế nào để thể hiện điều đó trong mã và đưa ra quyết định.
TerryB

Câu trả lời:


9

Nếu bạn tính toán bao xa vào Wallcác Player Spriteđã di chuyển, bạn có thể có thể căn cứ trên vùng châu thổ của các tọa độ x và y của các góc được giao nhau. Tôi hy vọng điều đó có ý nghĩa, tôi không thể nghĩ ra cách nào tốt hơn để diễn đạt nó.

Vì vậy, ví dụ, nếu bạn nhìn vào sơ đồ của bạn. Lấy xgiá trị của góc trên cùng bên trái của Player Sprite(sau khi di chuyển) và trừ xgiá trị của góc dưới cùng bên phải của Wall. Làm điều tương tự cho các ygiá trị và sau đó xem cái nào lớn hơn. Điều quan trọng là nếu cái này lớn hơn cái kia, Player Spritecó lẽ giao nhau ở phía đó.

Đây là một ví dụ hình ảnh (đây là phần phụ của hình ảnh của bạn với các dòng của riêng tôi được thêm vào):

ví dụ giao lộ

Bây giờ, bạn thấy ở đây là dòng màu xanh lớn hơn dòng màu xanh lá cây. Trong trường hợp này, đường màu xanh cũng nằm ở phía mà Player Spritedự kiến ​​sẽ bật ra.

Nếu hai giá trị bằng nhau, chúng đánh đúng vào góc.

Bây giờ, có một vấn đề nhỏ khi làm theo cách này. Nếu Player Spriteđang di chuyển rất nhanh hoặc va chạm rất gần với góc, có thể nó Player Spritecó thể đi xa hơn về Wallhướng sai. Trong trường hợp đó, có lẽ bạn sẽ phải kiểm tra vận tốc của vật chuyển động. (Xem câu trả lời của Nathan Reed .)

Lưu ý: Tôi nghĩ rằng về cơ bản tôi đang cố gắng mô tả phát hiện va chạm SAT mà @Blau đã đề cập, nhưng tôi đã mất một thời gian dài để viết bài này vì vậy tôi sẽ đăng nó bằng mọi cách. Hy vọng nó sẽ giúp bạn một số.


Cảm ơn Drackir! Và tôi đoán nếu bức tường của tôi được xoay tương đối so với sprite thì nó hơi phức tạp hơn nhưng cũng áp dụng nguyên tắc tương tự. Tìm vectơ dịch chuyển chiều dài tối thiểu có nghĩa là sprite sẽ không va chạm với tường. Sau đó sử dụng bức tường bình thường cho vectơ đó làm bức tường của tôi bật ra.
TerryB

@TerryB - Rotation thêm một chút phức tạp cho nó. Bạn có thể muốn đọc lên các hộp giới hạn liên kết trục (AABB). Về cơ bản, bạn vẫn sử dụng nguyên tắc tương tự như trên bằng cách kiểm tra hộp nhỏ nhất mà đối tượng xoay sẽ khớp với, nhưng trục của chúng được căn chỉnh theo trục cartesian. Hãy tưởng tượng nếu bạn có một hình vuông và bạn xoay nó 45 độ để biến nó thành một viên kim cương. Việc tính toán va chạm trên đó sẽ rất khó khăn và tốn kém, vì vậy trước tiên hãy kiểm tra xem vật thể có ở gần nó hay không bằng cách sử dụng AABB sẽ là một hình vuông trong đó mỗi điểm của viên kim cương chạm vào mỗi bên ở giữa.
Richard Marskell - Drackir

Sau đó, khi bạn biết nó ở gần nó, bạn có thể thực hiện các phép tính tốn kém hơn để xem liệu chúng có giao nhau trên các góc không (có lẽ nên là một câu hỏi khác hoàn toàn :)).
Richard Marskell - Drackir

1
-1 vì chuyển vị tối thiểu không phải lúc nào cũng đưa ra câu trả lời đúng cho "cạnh nào va chạm trước"; xem câu trả lời của tôi
Nathan Reed

@NathanReed - Đó là lý do tại sao tôi đề cập đến việc kiểm tra vận tốc trong đoạn "Bây giờ, có một vấn đề nhỏ khi thực hiện theo cách này".
Richard Marskell - Drackir

15

Chuyển vị tối thiểu không phải lúc nào cũng đưa ra câu trả lời đúng cho cạnh nào được đánh trước. Hãy xem xét trường hợp này:

trường hợp phá vỡ thuật toán chuyển vị ngắn nhất

Điều này xảy ra khi vận tốc đủ cao để khối di chuyển khá xa trong một khung hình. Để phát hiện chính xác cạnh nào bị tấn công trước, bạn sẽ cần thiết lập một phương trình tuyến tính để giải quyết thời gian va chạm với mỗi cạnh. Trong trường hợp này được mô tả trong sơ đồ của OP, các phương trình liên quan là:

timeXCollision = (player.left - wall.right) / -player.velocity.x
timeYCollision = (wall.bottom - player.top) / player.velocity.y

(Đây là giả sử hệ tọa độ Y-up, Y-up.) Nói chung, bạn phải sử dụng các dấu hiệu của các thành phần X và Y của player.velocity để xác định cặp cạnh nào cần được kiểm tra. Dù sao, một khi bạn có thời gian va chạm được tính toán, trước đó của hai là va chạm bạn cần xử lý.


1
Bạn có thể cung cấp một ví dụ về cách hai biến của bạn có thể được thực hiện?
BjarkeCK

1

Bạn cần phát hiện va chạm SAT

Về cơ bản, bạn cần tìm vectơ chuyển vị tối thiểu được trừ vào một trong các đối tượng để chúng không giao nhau.

Trong ảnh của bạn sự dịch chuyển tối thiểu là đoạn màu cam.

nhập mô tả hình ảnh ở đây


4
-1 vì chuyển vị tối thiểu không phải lúc nào cũng đưa ra câu trả lời đúng cho "cạnh nào va chạm trước"; xem câu trả lời của tôi
Nathan Reed

ai đang hỏi vậy
Blau

Câu hỏi là hỏi điều đó. "Mã của tôi hiện đang nói với tôi rằng hai cạnh tường đã được giao nhau nhưng không phải là cạnh nào nó sẽ chạm đầu tiên và do đó cạnh nào bị bật ra."
Nathan Reed

Đầu tiên? Vấn đề không phải là cái đầu tiên là gì, nó va chạm với hai cạnh cùng một lúc, ... vấn đề là cạnh nào bị bật ra, bạn đã chọn một phương pháp tốt cho bạn, tôi đã chọn một phương pháp đó là tốt cho tôi, cả hai đều hợp lệ
Blau

1
Nếu bạn muốn đưa ra quyết định thiết kế để cho các vật thể lướt qua nhau như thế, như thể chúng được làm tròn hoặc vát ở các góc, đó là quyết định của bạn và có thể là điều phù hợp với lối chơi của bạn. Nhưng tôi không nghĩ câu hỏi là hỏi về quyết định thiết kế; nó đang hỏi về mặt toán học làm thế nào để bật các hình chữ nhật thẳng hàng với nhau. Đây không phải là vấn đề giải thích; bài toán này có một câu trả lời rõ ràng và chính xác cho cạnh nào bị bật ra.
Nathan Reed

0

Đã trả lời một câu hỏi tương tự ở đây

Bạn có thể muốn xem xét việc kiểm tra các vị trí trước đó-

Ví dụ: nếu bên trái của bạn trước đây ở bên phải của họ và bạn đang va chạm, thì đã xảy ra va chạm tay phải.

Nếu bạn làm điều này, chỉ cần giải quyết các va chạm trục y, kiểm tra xem bạn có va chạm với bất cứ điều gì không, sau đó giải quyết các va chạm trục x.

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.