Phản ứng va chạm hình chữ nhật


10

Tôi gặp khó khăn khi có một hình chữ nhật có thể di chuyển để va chạm với nhiều hơn một hình chữ nhật.

Tôi đang sử dụng SFML và nó có một chức năng tiện dụng được gọi là intersectscó 2 hình chữ nhật và trả về các giao điểm. Tôi có một vectơ đầy hình chữ nhật mà tôi muốn hình chữ nhật có thể di chuyển của mình va chạm với. Tôi đang lặp lại điều này bằng cách sử dụng đoạn mã sau (p là hình chữ nhật di chuyển).

IsCollidingWithtrả về một bool nhưng cũng sử dụng SFML intersectsđể xử lý các giao điểm.

while(unsigned i = 0; i!= testRects.size(); i++){
   if(p.IsCollidingWith(testRects[i]){
        p.Collide(testRects[i]);
   }
}

Collide()mã thực tế :

void gameObj::collide( gameObj collidingObject ){

 printf("%f %f\n", this->colliderResult.width, this->colliderResult.height);

if (this->colliderResult.width < this->colliderResult.height) {
    // collided on X
    if (this->getCollider().left < collidingObject.getCollider().left ) {
        this->move( -this->colliderResult.width , 0);
    }else {
        this->move( this->colliderResult.width, 0 );
    }

}

if(this->colliderResult.width > this->colliderResult.height){
    if (this->getCollider().top < collidingObject.getCollider().top ) {
        this->move( 0, -this->colliderResult.height);
    }else {     
        this->move( 0, this->colliderResult.height );
    }

}

IsCollidingWith()mã là:

bool gameObj::isCollidingWith( gameObj testObject ){
if (this->getCollider().intersects( testObject.getCollider(), this->colliderResult )) {
    return true;
}else {
    return false;
}

Điều này hoạt động tốt khi chỉ có 1 Recttrong cảnh. Tuy nhiên, khi có nhiều hơn một, Rectnó gây ra sự cố khi xử lý 2 va chạm cùng một lúc.

Bất kỳ ý tưởng làm thế nào để đối phó với điều này một cách chính xác? Tôi đã tải lên một video lên youtube để hiển thị vấn đề của tôi. Bảng điều khiển ở phía bên phải hiển thị chiều rộng và chiều cao của các giao lộ. Bạn có thể thấy trên bảng điều khiển đang cố gắng tính toán 2 va chạm cùng một lúc, tôi nghĩ đây là vấn đề đang được gây ra.

Cuối cùng, hình ảnh dưới đây dường như minh họa vấn đề của tôi độc đáo:

hình chữ nhật va chạm với nhiều hình chữ nhật khác


Liên kết video bị hỏng.
XiaoChuan Yu

Là các colliderđối tượng trả về bởi this->getCollider()cập nhật bởi this->move()??
XiaoChuan Yu

Bạn có thể thêm một số thông tin xin vui lòng? Chính xác thì vấn đề là gì? Video YouTube dường như hiển thị hành vi có thể dự đoán được và chỉ có một hình chữ nhật khác trong cảnh.
Wackidev

Câu trả lời:


3

Hình ảnh của bạn minh họa một trong nhiều vấn đề khi cố gắng sử dụng các hình lồi - đặc biệt là hình chữ nhật - để mô phỏng một bề mặt phẳng như sàn nhà. Thuật toán dẫn đến các ký tự bị kẹt ở các cạnh bên trong của các hình tạo thành sàn nhà.

Một sửa chữa đơn giản cho điều đó là chỉ kiểm tra va chạm dọc, sửa lỗi đó, sau đó kiểm tra lại xem có va chạm ngang không. Trừ khi bạn ngã và cố gắng trượt xuống một bức tường, trong trường hợp đó bạn muốn kiểm tra va chạm ngang trước. Làm thế nào để bạn biết khi nào nên kiểm tra cái nào trước? Bạn có thể làm điều đó dựa trên thành phần nào của vận tốc của bạn lớn hơn (nếu chuyển động ngang lớn hơn, trước tiên hãy kiểm tra va chạm dọc, nếu không thì kiểm tra va chạm ngang).

Điều thậm chí có thể đơn giản hơn - và hiệu quả hơn - thay vào đó là tạo ra một danh sách các cạnh cho thế giới của bạn. Đó là, đối với các hộp của bạn tạo thành sàn, đặt cờ cho biết chỉ có cạnh trên của chúng thực sự có thể va chạm, và sau đó bỏ qua va chạm với các cạnh khác. Bạn sẽ không thể sử dụng thói quen va chạm của SFML cho điều đó, nhưng thật ra, va chạm hộp đơn giản có thể là đoạn mã dễ nhất bạn từng viết trong trò chơi. Kỹ thuật này hoạt động đặc biệt tốt nếu thế giới của bạn được liên kết với một lưới. Tôi sẽ kiểm tra các hướng dẫn Metanet tuyệt vời (http://www.metanetsoftware.com/technique.html/) cho kỹ thuật đó.

Bạn sẽ gặp phải nhiều vấn đề khác khi cố gắng xây dựng một game platformer 2D đơn giản như bạn. Cho đến nay, tài nguyên tốt nhất mà tôi đã thấy latel cho đó là tài nguyên sau, bạn nên đọc và sau đó đọc lại:

http://higherorderfun.com/blog/2012/05/20/the-guide-to-im THỰCing-2d-pl platformers /


1

Có lẽ một giải pháp đơn giản sẽ là kiểm tra va chạm với mọi hình chữ nhật và di chuyển trở lại, theo hướng ngược lại của chuyển động, cho đến khi không phát hiện được va chạm nào. Nếu điều đó giải quyết được vấn đề, việc thực hiện cũng khá đơn giản.


+1, tôi thực sự đã viết về nó ở đây: gamedev.stackexchange.com/questions/38252/iêu
Markus von Broady

0

Tôi không nghĩ rằng có 2 va chạm được tính toán là một vấn đề, chỉ là vấn đề hiệu suất. Để va chạm được xử lý chính xác, nó có thể phải được kiểm tra hai lần. Sử dụng sơ đồ của bạn nghĩ rằng nếu A được thử nghiệm trước B, thì nó cũng sẽ cần được thử nghiệm với các hộp khác và cũng có thể va chạm với nhau.

Hy vọng đó là hữu ích?


0

Đây không phải là thực sự là một phương pháp tối ưu, bạn nên cố gắng để xác định có thời gian sớm nhất khi hoặc điểm đầu tiên dọc theo di chuyển các đối tượng con đường nơi va chạm xảy ra và di chuyển các đối tượng đến vị trí đó (hoặc vị trí tại thời điểm tính toán), cố gắng chính xác dựa trên các vị trí thâm nhập sau khi di chuyển là rất có vấn đề, nhưng bạn có thể sử dụng quy trình hiện tại của mình với một thay đổi nhỏ. Chỉ cần tiếp tục kiểm tra va chạm cho đến khi không có.

bool collided = true;
while(collided) {
   collided = false
   while(unsigned i = 0; i!= testRects.size(); i++){
      if(p.IsCollidingWith(testRects[i]){
         collided = true
         p.Collide(testRects[i]);
      }
   }
}

Lưu ý rằng có những tình huống điều này sẽ dẫn đến Vòng lặp vô hạn (nghĩ về tình huống di chuyển chiếc hộp ra khỏi va chạm dẫn đến một bộ sưu tập khác và di chuyển chiếc hộp ra khỏi sự va chạm đó sẽ đưa nó trở lại vị trí va chạm như trước)

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.