Xu hướng, đi bộ ngẫu nhiên bảo thủ


13

Tôi có một sprite có VelocityPosition, hoặc được lưu trữ dưới dạng Vector2. Ở mỗi Updatechu kỳ, vận tốc được thêm vào vị trí.

Tôi muốn cung cấp cho sprite một vector thứ ba Target,. Các mục tiêu mới có thể được đưa ra tại bất kỳ lần lặp nào. Tôi muốn sprite về cơ bản di chuyển theo mô hình đi bộ ngẫu nhiên, tuy nhiên hai tham số phải được đưa ra:

  1. Một bước đi ngẫu nhiên điển hình có khả năng tăng hoặc giảm khoảng cách đến bất kỳ mức nào Target(cộng với cơ hội chuyển động tiếp tuyến nhỏ). Tôi phải có khả năng thiên vị bước đi ngẫu nhiên của mình để trong khi vẫn ngẫu nhiên, hướng mà sprite "quyết định" sẽ có nhiều khả năng đưa nó đến gần hơn Target.
  2. Lối đi ngẫu nhiên phải "trơn tru" - sprite không nên nhanh chóng thay đổi hướng, vì điều này sẽ trông giống như "nhấp nháy" hoặc "run rẩy" đối với người chơi. Nó nên dần dần xoay theo cách này hoặc cách khác, di chuyển ngẫu nhiên, trong khi từ từ tiến gần hơn khi tính trung bình.

Một cách tốt, đơn giản để làm điều này là gì? Nếu có thể, hãy đưa ra câu trả lời như một Vector2 RandomWalk(Vector2 target)phương pháp.

Tôi đã có sẵn một NextGaussian(mean, stdev)phương pháp, nếu điều đó hữu ích.


Cho nó một cơ hội rất nhỏ để thay đổi hướng mỗi khung hình? Và làm cho cơ hội đó lớn hơn đáng kể nếu nó không di chuyển theo hướng bạn muốn?
BlueRaja - Daniel Pflughoeft

Đó là giải pháp tốt. Tuy nhiên tôi muốn tránh sự thay đổi hướng đột ngột, giật nếu có thể.
Tuyệt vời nhất

1
Chỉ cần thêm một yếu tố gia tốc, vì vậy thay vì thay đổi vận tốc, bạn thay đổi gia tốc, từ đó thay đổi vận tốc. Điều này sẽ loại bỏ jitter khỏi chuyển động và bạn chỉ có thể điều chỉnh ứng dụng tăng tốc cho đến khi bạn có được bước đi suôn sẻ
skeletalmonkey

Câu trả lời:


4

Tôi sẽ thực hiện hành vi lái "đi lang thang" (có thể tìm thấy mã nguồn ở đây ) và điều chỉnh nó theo cách sao cho các số ngẫu nhiên bị lệch về phía mục tiêu của bạn.


Vâng, tôi nghĩ rằng hành vi chỉ đạo là con đường để đi. Chỉ cần thực hiện Wander + Seek và thêm trọng lượng thấp vào hành vi tìm kiếm.
krolth

6

Để có được một bước đi ngẫu nhiên suôn sẻ, bạn có thể sử dụng spline Catmull-Rom . Loại spline này có một chuỗi các điểm và tạo ra các đường cong mượt mà đi qua từng điểm. Vì vậy, bạn có thể tạo các điểm mốc ngẫu nhiên để sprite di chuyển qua và hoạt hình nó dọc theo một đường nối Catmull-Rom thông qua các điểm mốc. Để spline hoạt động, bạn sẽ cần tổng cộng bốn điểm tham chiếu: hai điểm trước và hai điểm tiếp theo. Khi sprite đạt đến một điểm tham chiếu, hãy vứt bỏ một trong bốn bộ cũ nhất của bạn và tạo một cái mới, sau đó tiếp tục hoạt hình dọc theo spline.

Cuối cùng, về phía mục tiêu, một ý tưởng sẽ là bù đắp sự phân phối của bước đi ngẫu nhiên về phía mục tiêu. Chẳng hạn, nếu bạn thường chọn một điểm dừng ngẫu nhiên bằng cách sử dụng phân phối Gaussian tập trung vào vị trí hiện tại của sprite của bạn, thay vào đó bạn có thể bù trung tâm của Gaussian theo một khoảng cách định sẵn về phía mục tiêu. Kích thước tương đối của phần bù và độ lệch chuẩn của Gaussian sẽ xác định độ lệch của chuyển động.


Tôi đã nghĩ về điều này, và trong khi khuyến nghị là tốt, tôi muốn sự thiên vị sẽ hướng đến vị trí của người chơi. Vì phương thức spline yêu cầu tôi tạo ra một số đường dẫn trước, nên sẽ có độ trễ trong khả năng theo dõi người chơi.
Tuyệt vời nhất

@Superbest nếu bạn sử dụng đường cong Bezier, bạn chỉ cần tạo hai điểm tiếp theo - và bạn có thể thực hiện bước thứ hai trong tương lai về phía người chơi khi anh ta di chuyển xung quanh.
Jonathan Dickinson

2

Đây là thứ tôi đã đánh lên trong khoảng 20 phút. Chúng tôi đi theo hướng từ người đi bộ đến mục tiêu, chọn một hướng trong một mức độ nhất định của hướng đó (một lượng giảm khi người đi bộ đến gần mục tiêu của họ hơn). Thuật toán này cũng chiếm khoảng cách đến mục tiêu để nó không đi qua mục tiêu. Câu chuyện dài, về cơ bản, nó lắc lư trái và phải một lượng nhỏ ngẫu nhiên và tập trung vào mục tiêu khi nó tiến gần hơn.

Để kiểm tra thuật toán này, tôi đặt walker tại (10, 0, 10) và mục tiêu tại (0, 0, 0). Lần đầu tiên thuật toán chạy nó đã chọn ngẫu nhiên một vị trí cho người đi bộ đi bộ đến (3.73f, 0, 6.71f). Sau khi người đi bộ đạt đến vị trí đó, nó đã chọn (2.11f, 0, 3.23), sau đó (0.96f, 0, 1.68f), sau đó (0,50f, 0, 0,79f), sau đó nó đi thẳng đến mục tiêu vì nó nằm trong một khoảng cách dung sai tối thiểu.

Vẽ đồ thị từ tầm nhìn của một con chim, con đường sẽ trông giống như các điểm trong hình ảnh bên dưới, bắt đầu từ 'W' (walker) và kết thúc tại 'T' (mục tiêu). Nếu bạn muốn có một chuyển động tự nhiên hơn, bạn sẽ định trước một vài điểm trước thời hạn và tạo ra một spline, cung cấp cho bạn nhiều điểm hơn bạn có thể có người đi bộ đi theo. Tôi đã ước tính con đường này sẽ trông như thế nào sau khi được tạo thành một spline và được thể hiện bằng đường thẳng trong hình ảnh.

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

Và đây là mã ví dụ:

Vector3 WalkerPosition = new Vector3(10, 0, 10);
Vector3 TargetPosition = Vector3.Zero;

public Game1()
{
    // Each time you reach the next walk-to position, call this again.
    // Eventually you'll reach your target, assuming the target isn't moving away
    // from the walker faster than the walker can reach them.
    Vector3 NextWalkToPosition = PickRandomTarget();
}

public Vector3 PickRandomTarget()
{
    // For this code sample we'll assume that our two targets are on
    // the same horizontal plane, for simplicity.

    Vector3 directionToTarget = ( TargetPosition - WalkerPosition );
    float distance = directionToTarget.Length();
    directionToTarget.Normalize();

    float distanceThisIteration = distance * 0.5f;

    // We should never walk too little or too far, to make this more realistic
    // you could randomize the walking distance each iteration a bit.
    distanceThisIteration = MathHelper.Clamp(distanceThisIteration, 1.0f, 10.0f);

    // We're within minimum distance to the target, so just go straight to them
    if (distanceThisIteration > distance)
    {
        return TargetPosition;
    }

    directionToTarget *= distanceThisIteration; // Walk roughly halfway to the target            

    // Now we pick a new walking direction within an FOV that gets smaller as
    // we get closer to the target. We clamp the FOV between 0 and 90 degrees (45 degrees in either direction).
    const float walkerAggroRadius = 30.0f; // Walker aggros when within 30 units of target

    // Any distance outside of 30 we'll just treat as 30.
    float distanceMod = MathHelper.Clamp(distance, 0.0f, walkerAggroRadius);

    // We need a percentage value representing the current distance between the min 0, and max, 30
    float percentageAlongDistance = distanceMod / walkerAggroRadius;

    // We want FOV from center, so we cut the final FOV result in half
    float maxFOVAtThisDistance = MathHelper.Lerp(0.0f, MathHelper.PiOver2, percentageAlongDistance) * 0.5f;

    // Now we pick a random FOV from center within our maxFOV based on how far we are
    // from the target
    Random rand = new Random(System.DateTime.Now.Second);
    float randFOV = (float)(rand.NextDouble() * maxFOVAtThisDistance);

    // Right now our FOV value is an FOV from a vector pointing directly at our target, we now
    // need to randomly choose if we're going to aim to the left or right of the target. We'll
    // treat a result of 0 as left, and 1 as right
    int randDirection = rand.Next(2);
    if (randDirection == 0) // Left
    {
        // Rotate our direction vector left by randFOV radians
        return WalkerPosition + RotateAroundPoint(directionToTarget, Vector3.Zero, Vector3.UnitY, -randFOV);
    }
    else // Right
    {
        return WalkerPosition + RotateAroundPoint(directionToTarget, Vector3.Zero, Vector3.UnitY, randFOV);
    }
}

// Generic helper function to rotate a vector by a specific amount of degrees
public Vector3 RotateAroundPoint( Vector3 point, Vector3 originPoint, Vector3 rotationAxis, float radiansToRotate )
{
    Vector3 diffVect = point - originPoint;

    Vector3 rotatedVect = Vector3.Transform(diffVect, Matrix.CreateFromAxisAngle(rotationAxis, radiansToRotate));

    rotatedVect += originPoint;

    return rotatedVect;
}

Dựa trên trò chơi cụ thể của bạn, bạn có thể điều chỉnh khoảng cách, FOV, tính ngẫu nhiên và tần suất mà trò chơi này được chạy, cho đến khi nó phù hợp với nhu cầu của bạn. Tôi chắc rằng thuật toán có thể được dọn dẹp một chút và tối ưu hóa, tôi đã không dành nhiều thời gian cho việc đó, tôi chỉ muốn nó dễ đọ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.