Làm thế nào để tôi tìm thấy giao điểm của hai dòng


7

Tôi có một khung giới hạn trên nhân vật của mình, vị trí của nó trong khung trước đó là khung hiện tại. Hộp giới hạn được căn chỉnh trục.

Nhân vật của tôi đang chạy quanh bên trong một hang động, tôi có một danh sách các điểm (đường thẳng) đại diện cho bức tường của hang động (không phải trục thẳng hàng)

Tôi đã có một thuật toán hạt thô cho tôi biết khi nào một phần nhân vật của tôi có khả năng va chạm với một phần của bức tường hang động.

Tôi không có một thuật toán hạt mịn để cho tôi biết cụ thể đường nào của bức tường bị va chạm và tại điểm nào.

Suy nghĩ hiện tại của tôi là tôi chỉ có thể tạo một đường cho mỗi góc của khung giới hạn từ vị trí của nó trong khung trước đó, đến vị trí của nó trong khung hiện tại, sau đó kiểm tra từng đường này để tìm giao điểm với bất kỳ đường nào trong hang Tường.

Google fu của tôi tuy nhiên đã không chỉ cho tôi một công thức dễ dàng để tính toán các giao lộ. Tôi đã chọn một cách tồi để làm điều này, hay tôi chỉ tệ khi tìm kiếm?

Trò chơi của tôi được viết bằng scala, tuy nhiên tôi có thể đọc / dịch hầu hết mọi ngôn ngữ kiểu c và nhiều ngôn ngữ kịch bản, bất cứ điều gì bạn cảm thấy muốn trả lời

Câu trả lời:


-3

googling "phân đoạn dòng thử nghiệm phân khúc" sản xuất này:

http://paulbourke.net/geometry/lineline2d/


2
Giải pháp lớn hơn chỉ là điểm giao nhau giữa hai đường. Trav có một số dòng mô tả địa hình và bất kỳ phần nào của nhân vật có thể giao nhau với bất kỳ phần nào của bất kỳ dòng địa hình nào.
doppelgreener

Đó chỉ là sự lặp lại của thuật toán. Công thức để kiểm tra sự hiện diện của giao lộ, cho dù đó là trong các đoạn tôi đang xem, và sau đó lấy vị trí cụ thể chính xác là những gì tôi đang theo dõi
The Trav

1
Lý do tôi trả lời câu trả lời là bởi vì có, đó là sự lặp lại của thuật toán và bạn có thể bắt bẻ nó. Tôi mong đợi có nhiều hơn cho đến ngày nay mặc dù. Tôi không nghĩ chỉ cần chỉ ra công thức toán học cho giao lộ đường là vấn đề công bằng. Thế còn khi cấp độ của bạn trở nên lớn hơn và bạn đang lãng phí chu kỳ kiểm tra giao lộ với một bức tường hoàn toàn không liên quan thì sao?
doppelgreener

Jonathan: Chà, từ câu hỏi: "Tôi đã có một thuật toán hạt thô cho tôi biết khi nào một phần nhân vật của tôi có khả năng va chạm với một phần của bức tường hang động." Mặc dù chúng ta không biết liệu thuật toán chi tiết thô đó có tốt hay không ...
Olhovsky

7

Bạn có thể làm điều đó với các cách tiếp cận khác nhau;

  • phân đoạn so với phân khúc sử dụng các dòng tham số cộng với một số xác minh (vì các dòng không phải là phân khúc).

  • phân khúc vs hộp

  • phân đoạn so với vòng tròn (cái này sẽ là yêu thích của tôi)

. Nhưng khi bạn yêu cầu thử nghiệm phân đoạn so với phân khúc, đây là một ví dụ giả C ++ được trích từ cuốn sách rất thú vị "Phát hiện va chạm thời gian thực":

float Signed2DTriArea(Point a, Point b, Point c)
{
    return (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x);
}

int Test2DSegmentSegment(Point a, Point b, Point c, Point d, float &t, Point &p)
{
    // signs of areas correspond to which side of ab points c and d are
    float a1 = Signed2DTriArea(a,b,d); // Compute winding of abd (+ or -)
    float a2 = Signed2DTriArea(a,b,c); // To intersect, must have sign opposite of a1

    // If c and d are on different sides of ab, areas have different signs
    if( a1 * a2 < 0.0f ) // require unsigned x & y values.
    {
        float a3 = Signed2DTriArea(c,d,a); // Compute winding of cda (+ or -)
        float a4 = a3 + a2 - a1; // Since area is constant a1 - a2 = a3 - a4, or a4 = a3 + a2 - a1

        // Points a and b on different sides of cd if areas have different signs
        if( a3 * a4 < 0.0f )
        {
            // Segments intersect. Find intersection point along L(t) = a + t * (b - a).
            t = a3 / (a3 - a4);
            p = a + t * (b - a); // the point of intersection
            return 1;
        }
    }

    // Segments not intersecting or collinear
    return 0;
}

Thỏa thuận cấp phép phần mềm của cuốn sách yêu cầu bao gồm tín dụng sau để sử dụng các ví dụ mã:

ví dụ mã "từ Phát hiện va chạm trong thời gian thực của Christer Ericson, được xuất bản bởi Nhà xuất bản Morgan Kaufmaan, © 2005 Elvesier Inc"


4

Mặc dù ai đó đã cung cấp câu trả lời được coi là thỏa đáng, tôi không chắc phương pháp bạn mô tả sẽ mang lại thời gian tác động chính xác (TOI). Quan điểm đầu tiên của tôi là tìm ra câu trả lời chính xác cho câu hỏi, "người chơi có thể di chuyển bao xa trước khi va chạm với một phần của hang động, nếu xảy ra va chạm?" đòi hỏi phải dùng đến các kỹ thuật phát hiện va chạm liên tục (CCD).

Cụ thể, có một kỹ thuật mà theo đó bạn có thể "thu nhỏ" AABB của mình thành một điểm một cách hiệu quả, đồng thời "phát triển" các đoạn đường của hang động bằng cách sử dụng Bổ sung Minkowski. Sau đó, vấn đề có thể được xem là truyền một tia tới một vật lồi hoặc tập hợp các vật lồi (vì một điểm chuyển động theo thời gian với vận tốc không đổi trở thành một tia). Khoảng cách sớm nhất dọc theo tia giao nhau với hang "cồng kềnh" sẽ biểu thị thời gian tác động sớm nhất (TOI).

Thông thường nhất là tài liệu về cách thực hiện thỏa thuận này với ba chiều, nhưng vẫn áp dụng cho hai chiều và phải chuyển dễ dàng. Hiện tại tôi không có thời gian để đánh vần tất cả các chi tiết hoặc cung cấp mã psuedo, nhưng có lẽ người khác sẽ có thể xác minh và mở rộng dựa trên những gì tôi đang đề cập. Hiện tại, đây là một vài bài viết giải thích quy trình và một số thuật ngữ bạn có thể quan tâm đến Google.


0

Trong nỗ lực giúp những người khác tìm thấy điều này trong chuyến đi của họ, đây là thử nghiệm giao cắt đường 2D bằng các phương pháp được tìm thấy tại https://stackoverflow.com/a/1968345/431528 .

inline bool lines_intersect_2d(Vector2 const& p0, Vector2 const& p1, Vector2 const& p2, Vector2 const& p3, Vector2* i const = 0) {
    Vector2 const s1 = p1 - p0;
    Vector2 const s2 = p3 - p2;

    Vector2 const u = p0 - p2;

    float const ip = 1.f / (-s2.x * s1.y + s1.x * s2.y);

    float const s = (-s1.y * u.x + s1.x * u.y) * ip;
    float const t = ( s2.x * u.y - s2.y * u.x) * ip;

    if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
        if (i) *i = p0 + (s1 * t);
        return true;
    }

    return false;
}
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.