Tay lái tránh tường


8

Tôi tạo ra một trình mô phỏng lái nhỏ bằng thuật toán bo Reynold. Bây giờ tôi muốn thêm một tính năng tránh tường. Tường của tôi ở dạng 3D và được xác định bằng hai điểm như thế:

   ---------. P2
   |        |
P1 .---------

Đặc vụ của tôi có vận tốc, vị trí, v.v ...

Bạn có thể cho tôi biết làm thế nào để tránh với các đại lý của tôi?

Vector2D ReynoldsSteeringModel::repulsionFromWalls()
{
    Vector2D force;
    vector<Wall *> wallsList = walls();
    Point2D pos = self()->position();
    Vector2D velocity = self()->velocity();

    for (unsigned i=0; i<wallsList.size(); i++)
    {
        //TODO
    }

    return force;
}

Sau đó, tôi sử dụng tất cả các lực được trả về bởi các chức năng boid của tôi và tôi áp dụng nó cho đại lý của mình.

Tôi chỉ cần biết làm thế nào để làm điều đó với các bức tường của tôi.

Cảm ơn bạn đã giúp đỡ.


2
bạn đã nhìn vào bài báo gốc của Reynold chưa? Nếu tôi nhớ lại một cách chính xác, nó có thông tin về cách tránh chướng ngại vật và tránh tường. Tôi nghĩ đây là tài liệu: red3d.com/cwr/steer/gdc99
krolth

1
Cảm ơn nhưng nó giải thích làm thế nào để tránh chướng ngại vật hình tròn, không phải hình chữ nhật.
Vodemki

2
Sử dụng khoảng cách xuyên tâm từ tác nhân đến tâm của vòng tròn ( trừ bán kính của tường vòng tròn ).
bobobobo

Câu trả lời:


14

Để mỗi bức tường gây ảnh hưởng đến vận tốc.

Hãy thử một cái gì đó như sử dụng khoảng cách nghịch đảo (hoặc khoảng cách bình phương nghịch đảo) từ tường để xác định cường độ của lực mà mỗi bức tường "tác động" và bình thường của bức tường để xác định hướng của lực mà bức tường "tác động".

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

Vì vậy, ở đây boid tương tác với 4 bức tường. Vì sản phẩm chấm của các vectơ màu đỏ (boid-to-wall-centre) lớn hơn 0 đối với 3 trong số 4 bức tường, những bức tường đó sẽ không tác dụng lực lên boid.

Chỉ bức tường có vectơ màu xanh (sản phẩm chấm âm) sẽ có lực.

Độ lớn của lực phải rất lớn khi boid quá sát tường và hướng của lực phải theo hướng mũi tên đen trên tường (chỉ thẳng ra khỏi tường).

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

Nếu bạn sử dụng 1 / (t+1)cho độ lớn của lực, tkhoảng cách từ tường, thì lực sẽ thực sự mạnh khi ở gần 0, nhưng giảm dần thành không có gì khi t cao hơn (lưu ý tỷ lệ trục trong sơ đồ, nó không phải là 0 khi t = 5, nó là 0,2). (T + 1 là để bạn không nhận được một lực vô hạn / chia cho 0 nếu boid xảy ra để vào tường).

Nếu bạn sử dụng 1/(t^2+1), thì lực sẽ mạnh hơn gần tường và rơi ra nhanh hơn / mượt mà hơn.

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

Thử nghiệm với nó và xem những gì bạn thích.


Cảm ơn nhưng làm thế nào để đối phó với một bức tường 3D. Ví dụ, tường của tôi có 4 cạnh, vì vậy tôi tin rằng tôi chỉ cần tối đa 2 lực (nếu hướng của tác nhân là theo đường chéo).
Vodemki

Trong 2D, cứ 2 điểm là một "bức tường". Nếu đó là một cột vuông ở giữa một căn phòng, thì bạn có 4 bức tường ở đó. Bạn có thể "loại bỏ" các bức tường che mặt (để các bức tường che khuất không "hút" người chơi) nếu vectơ từ boong đến trung tâm tường có sản phẩm chấm dương với tường bình thường.
bobobobo

Vì vậy, bạn có nghĩ rằng điều này sẽ làm công việc? Khoảng cách Vector2D (wallList [i] -> centre (), pos); double dotSản phẩm = khoảng cách * wallList [i] -> normal (); if (dotSản phẩm> 0) {force + = wallList [i] -> normal () / distance.length (); }
Vodemki

Có vẻ hợp lý, kiểm tra nó ra!
bobobobo

Một thiếu sót của phương pháp này là chỉ đạo được mô hình hóa như một lực đẩy độc lập với chuyển động của tác nhân. Đó là nó coi tác nhân là một hạt tích điện trong trường tĩnh điện. Hãy xem xét trường hợp mà đặc vụ là bay bay song song với bức tường (màu xanh) đó và hơi cao hơn nó (trên trang). Trong trường hợp này, không cần tránh lái hoặc vượt chướng ngại vật. Các đặc vụ chỉ đơn giản là đi ngang qua, và không nên bị đẩy ra khỏi bức tường. Xem ví dụ về ngăn chặn của người dùng trong bài viết về GDC 99 này .
Craig Reynold

8

Nếu ai đó cần mã, đây là, hãy thoải mái phân phối lại. Tôi đã cố gắng bình luận nó để dễ hiểu hơn. Dựa trên giải pháp của bobobobo .

Vector2D ReynoldsSteeringModel::repulsionFromWalls(vector<Vector2D *> walls)
{
    Vector2D force; // My force will be stored here
    Point2D pos = self()->position(); // Position of the agent

    // For each wall
    for (unsigned j=0; j<walls->size(); j++)
    {
        // Get the center point of the wall
        Real coordX = (walls[j]->p1().x() + walls[j]->p1().y()) / 2.0;
        Real coordY = (walls[j]->p2().x() + walls[j]->p2().y()) / 2.0;
        Point2D center(coordX, coordY);

        // Create a new vector between my agent and the center of the current wall
        Vector2D distance(center, pos);

        // If the wall is visible, calculate the force to apply
        double dotProduct = distance * partsList[j]->normal();
        if (dotProduct < 0)
        {
            force +=  partsList[j]->normal() / (distance.length() * distance.length() + 1);
        }
    }

    // Returned the calculated force
    return force;
}
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.