Thuật toán bắn vào mục tiêu trong trò chơi 3d


11

Đối với những người còn nhớ Descent Freespace, nó có một tính năng hay giúp bạn nhắm vào kẻ thù khi bắn tên lửa hoặc tia laze không bắn: nó cho thấy một con trỏ ở phía trước con tàu mà bạn đuổi theo nói cho bạn biết phải bắn vào đâu để di chuyển Mục tiêu.

Tôi đã thử sử dụng câu trả lời từ /programming/4107403/ai-alerskym-to-shoot-at-a-target-in-a-2d-game?lq=1 nhưng nó đã cho 2D nên tôi đã thử thích nghi với nó

Trước tiên, tôi đã phân tách phép tính để giải điểm giao nhau cho mặt phẳng XoZ và lưu tọa độ x và z rồi giải điểm giao nhau cho mặt phẳng XoY và thêm tọa độ y vào xyz cuối cùng mà sau đó tôi chuyển đổi sang không gian clip và đặt kết cấu vào đó tọa độ. Nhưng tất nhiên nó không hoạt động như bình thường nếu không tôi sẽ không đăng câu hỏi.

Từ những gì tôi nhận thấy sau khi tìm x trong mặt phẳng XoZ và trong XoY thì x không giống nhau nên có gì đó phải sai.

    float a = ENG_Math.sqr(targetVelocity.x) + ENG_Math.sqr(targetVelocity.y) -
            ENG_Math.sqr(projectileSpeed);
    float b = 2.0f * (targetVelocity.x * targetPos.x + 
            targetVelocity.y * targetPos.y);
    float c = ENG_Math.sqr(targetPos.x) + ENG_Math.sqr(targetPos.y);
    ENG_Math.solveQuadraticEquation(a, b, c, collisionTime);

TargetVelocity.y lần đầu tiên thực sự là targetVelocity.z (giống với targetPos) và lần thứ hai nó thực sự là targetVelocity.y.

Vị trí cuối cùng sau XoZ là

    crossPosition.set(minTime * finalEntityVelocity.x + finalTargetPos4D.x, 0.0f, 
                minTime * finalEntityVelocity.z + finalTargetPos4D.z);

và sau XoY

    crossPosition.y = minTime * finalEntityVelocity.y + finalTargetPos4D.y;

Là cách tiếp cận của tôi để tách thành 2 mặt phẳng và tính toán bất kỳ tốt? Hay đối với 3D có một cách tiếp cận hoàn toàn khác?

  • sqr () là hình vuông không phải sqrt - tránh nhầm lẫn.

1
"Dẫn đầu mục tiêu" có thể là cụm từ bạn đang tìm kiếm.
MichaelHouse

Câu trả lời:


12

Không cần phải chia nó thành 2 chức năng 2d. Đó là phương trình bậc hai mà bạn đang làm việc với hoạt động tốt trong 3d. Đây là mã giả cho 2d hoặc 3d. Nó ám chỉ một tòa tháp (tháp phòng thủ) đang bắn đạn:

Vector totarget =  target.position - tower.position;

float a = Vector.Dot(target.velocity, target.velocity) - (bullet.velocity * bullet.velocity);
float b = 2 * Vector.Dot(target.velocity, totarget);
float c = Vector.Dot(totarget, totarget);

float p = -b / (2 * a);
float q = (float)Math.Sqrt((b * b) - 4 * a * c) / (2 * a);

float t1 = p - q;
float t2 = p + q;
float t;

if (t1 > t2 && t2 > 0)
{
    t = t2;
}
else
{
    t = t1;
}

Vector aimSpot = target.position + target.velocity * t;
Vector bulletPath = aimSpot - tower.position;
float timeToImpact = bulletPath.Length() / bullet.speed;//speed must be in units per second 

'aimSpot' có thể là vectơ bạn đang hỏi về.


Bạn là một thiên tài và đã cứu cái mông của tôi !! Chết tiệt, tôi cần 15 danh tiếng để nâng cấp ....
Sebastian Bugiu

@SebastianBugiu tôi đã làm điều đó cho bạn.
AgentFire

@SebastianBugiu Cảm ơn, tôi rất vui khi biết được khái niệm này và rất vui vì nó đã giúp bạn. Một tính năng trang nhã khác của nó là bạn không cần phải loay hoay với các thuật toán phát hiện va chạm. Không cần viết mã CD. Vì đường dẫn đích và đường đạn có thể dự đoán được, tác động SILL xảy ra khi timeToImpactđếm ngược về không.
Steve H

1

Ngoài ra còn có một bài đăng blog tốt về cùng một chủ đề: http://playtechs.blogspot.kr/2007/04/aiming-at-moving-target.html . Nó cũng chứa các mẫu phức tạp hơn bao gồm cả trọng lực.

Tác giả đã thực hiện đơn giản hóa hơn, dẫn đến mã nhỏ gọn hơn:

double time_of_impact(double px, double py, double vx, double vy, double s)
{
    double a = s * s - (vx * vx + vy * vy);
    double b = px * vx + py * vy;
    double c = px * px + py * py;

    double d = b*b + a*c;

    double t = 0;
    if (d >= 0)
    {
        t = (b - sqrt(d)) / a;
        if (t < 0) 
        {
            t = (b + sqrt(d)) / a;
            if (t < 0)
                t = 0;
        }
    }

    return t;
}

Cập nhật: Tác giả gốc chỉ tính đến root lớn hơn. Nhưng trong trường hợp gốc nhỏ hơn không âm, nó mang lại giải pháp tốt hơn, vì thời gian tác động nhỏ hơn. Tôi đã cập nhật mã tương ứng.

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.