পক্ষপাতদুষ্ট, রক্ষণশীল এলোমেলো পদচারনা


13

আমার কাছে একটি স্প্রাইট রয়েছে যা রয়েছে Velocityএবং Positionহয় হিসাবে সংরক্ষণ করা হয়েছে Vector2। প্রতিটি Updateচক্রের স্থানে বেগ যুক্ত হয়।

আমি স্প্রাইটকে একটি তৃতীয় ভেক্টর দিতে চাই Target। নতুন লক্ষ্যগুলি যে কোনও পুনরাবৃত্তিতে দেওয়া যেতে পারে। আমি চাই স্প্রাইটটি মূলত এলোমেলো হাঁটার প্যাটার্নে চলে আসুক, তবে দুটি পরামিতি অবশ্যই প্রকাশ করা উচিত:

  1. একটি সাধারণ এলোমেলো পদব্রজেতা যে কোনও প্রদত্ত দূরত্ব হ্রাস বা হ্রাস করার সমান সম্ভাবনা Target(প্লাস স্পর্শকাতর চলাচলের ক্ষুদ্র সম্ভাবনা)। আমার অবশ্যই এলোমেলো হাঁটার পক্ষপাতিত্ব করতে সক্ষম হব, এখনও এলোমেলো অবস্থায় স্প্রাইট যেদিকে "সিদ্ধান্ত নেয়" তার কাছাকাছি আসার সম্ভাবনা আরও বেশি হওয়া উচিত Target
  2. এলোমেলো হাঁটা "মসৃণ" হওয়া উচিত - স্প্রাইটটি দ্রুত দিক পরিবর্তন করা উচিত নয় কারণ এটি খেলোয়াড়ের কাছে "ঝাঁকুনি" বা "কাঁপুন" এর মতো দেখাবে। এটি ধীরে ধীরে এইভাবে বা সেভাবে ঘুরে বেড়াতে হবে, এলোমেলোভাবে চলতে হবে, গড় গড় যখন ধীরে ধীরে কাছে আসে।

এটি করার একটি ভাল, সহজ উপায় কী? যদি সম্ভব হয় তবে একটি Vector2 RandomWalk(Vector2 target)পদ্ধতি হিসাবে উত্তর দিন ।

আমি ইতিমধ্যে একটি NextGaussian(mean, stdev)পদ্ধতি উপলব্ধ আছে, যদি এটি সহায়ক হয়।


প্রতি ফ্রেমে দিক পরিবর্তন করার জন্য এটি একটি খুব ছোট সুযোগ দেবেন? এবং যদি সেই সুযোগটি আপনি যেদিকে যেতে চান সেদিকে না চলে তবে সেই সুযোগটি উল্লেখযোগ্যভাবে আরও বড় করুন?
ব্লুরাজা - ড্যানি পিফ্লুঘুফুট

এটি দুর্দান্ত সমাধান। তবে আমি যদি সম্ভব হয় তবে হঠাৎ হতাশার দিকনির্দেশ পরিবর্তনকে এড়াতে পছন্দ করব।
সুপারবেস্ট

1
কেবল একটি ত্বরণ ফ্যাক্টর যুক্ত করুন, সুতরাং বেগ পরিবর্তন করার পরিবর্তে, আপনি ত্বরণ পরিবর্তন করেন, যার ফলে গতি পরিবর্তন হয়। এটি চলাচল থেকে জিটারটি সরিয়ে ফেলতে হবে এবং আপনি একটি মসৃণ পদচারণা না করা পর্যন্ত আপনি কেবল ত্বরণের অ্যাপ্লিকেশনটিকে টুইঙ্ক করতে পারেন
skeletalmonkey

উত্তর:


4

আমি "ঘোরাঘুরি" স্টিয়ারিং-আচরণটি গ্রহণ করব (উত্স কোডটি এখানে পাওয়া যাবে ) এবং এটিকে এমনভাবে টুইঙ্ক করব যাতে এলোমেলো সংখ্যাগুলি আপনার টার্গেটের দিকে পক্ষপাতদুষ্ট হয়।


হ্যাঁ, আমি মনে করি স্টিয়ারিং আচরণগুলি চলার উপায়। স্রেফ একটি ঘোরাফেরা + অনুসন্ধান করুন এবং অনুসন্ধানের আচরণে একটি কম ওজন যুক্ত করুন।
krolth

6

একটি মসৃণ এলোমেলো হাঁটা পেতে, আপনি ক্যাটমুল-রোমের স্প্লাইস ব্যবহার করতে পারেন । এই জাতীয় স্প্লাইনটি পয়েন্টগুলির একটি ক্রম নেয় এবং প্রতিটি পয়েন্টের মধ্য দিয়ে যায় এমন মসৃণ বক্ররেখা উত্পন্ন করে। সুতরাং, আপনি স্প্রাইটের মধ্য দিয়ে চলতে এবং এটিকে পথনির্দেশের মাধ্যমে ক্যাটমুল-রোমের স্প্লাইন বরাবর অ্যানিমেট করার জন্য এলোমেলো উপায়গুলি তৈরি করতে পারেন। স্প্লাইনটি কাজ করার জন্য আপনার মোট চারটি পয়েন্ট পয়েন্ট দরকার: পূর্ববর্তী দুটি এবং পরের দুটি। স্প্রাইট যখন কোনও ওয়েপয়েন্টে পৌঁছে যায়, তখন আপনার চারটি সেটগুলির মধ্যে সবচেয়ে পুরানো একটিকে ফেলে দিন এবং একটি নতুন তৈরি করুন, তারপরে স্প্লাইন বরাবর অ্যানিমেটিং চালিয়ে যান।

শেষ পর্যন্ত লক্ষ্যটির দিকে যাবার জন্য, একটি ধারণা লক্ষ্যটির দিকে এলোমেলো হাঁটার বিতরণটি অফসেট করে। উদাহরণস্বরূপ, যদি আপনি সাধারণত আপনার স্প্রাইটের বর্তমান অবস্থানকে কেন্দ্র করে কোনও গাউসীয় বিতরণ ব্যবহার করে কোনও এলোমেলো পথ বেছে নিতে চান, তবে আপনি পরিবর্তে লক্ষ্যটির দিকে কিছু প্রিসেট দূরত্ব রেখে গাউসির কেন্দ্রটি অফসেট করতে পারেন। অফসেটের আপেক্ষিক আকার এবং গাউসের মানক বিচ্যুতি গতিটি কতটা পক্ষপাতদুষ্ট তা নির্ধারণ করবে।


আমি এটি সম্পর্কে ভেবেছি, এবং প্রস্তাবনাটি দুর্দান্ত হলেও, আমি চাইব পক্ষপাতদুটি প্লেয়ারের অবস্থানের দিকে। যেহেতু স্প্লাইন পদ্ধতিতে আমার আগে থেকেই কিছু পথ তৈরি করা দরকার, তাই প্লেয়ারকে অনুসরণ করার ক্ষমতা পিছনে থাকবে।
সুপারবেস্ট

@ সুপার্পেস্ট আপনি যদি বেজিয়ার কার্ভটি ব্যবহার করেন তবে আপনাকে কেবল পরবর্তী দুটি পয়েন্ট তৈরি করতে হবে - এবং খেলোয়াড়ের কাছাকাছি চলার সাথে সাথে আপনি ভবিষ্যতের দ্বিতীয়-পয়েন্টে-ভবিষ্যতের দিকে যেতে পারেন।
জোনাথন ডিকিনসন

2

এখানে প্রায় 20 মিনিটের মধ্যে এমন কিছু রয়েছে যা আমি বেত্রাঘাত করি। আমরা ওয়াকার থেকে লক্ষ্য পর্যন্ত দিকনির্দেশ নিয়ে যাই, সেই দিকের একটি নির্দিষ্ট পরিমাণের ডিগ্রির মধ্যে একটি দিক বাছাই করি (ওয়াকারটি তাদের টার্গেটের কাছাকাছি যাওয়ার সাথে সাথে এটি হ্রাস পায়)। এই অ্যালগরিদমটি দূরত্বের লক্ষ্য হিসাবেও লক্ষ্য করে যাতে এটি লক্ষ্য ছাড়িয়ে যায় না। দীর্ঘ গল্প সংক্ষিপ্ত, এটি মূলত বাম এবং ডানদিকে একটি ছোট এলোমেলো পরিমাণ এবং ঘরের কাছাকাছি আসার সাথে লক্ষ্যবস্তুতে ডুবে গেছে।

এই অ্যালগরিদমটি পরীক্ষা করতে আমি ওয়াকারকে (10, 0, 10) এবং লক্ষ্য (0, 0, 0) এ রেখেছি। প্রথমবারের মতো অ্যালগরিদম এলোমেলোভাবে এটিকে চালিয়ে যাওয়ার জন্য ওয়াকারের পক্ষে (3.73f, 0, 6.71f) পদক্ষেপের জন্য একটি অবস্থান বেছে নিয়েছিল। ওয়াকার সেই অবস্থানে পৌঁছানোর পরে এটি (2.11f, 0, 3.23), তারপরে (0.96f, 0, 1.68f), তারপরে (0.50f, 0, 0.79f) বেছে নিয়েছে, তারপরে এটি সরাসরি টার্গেটে চলে গেছে কারণ এটির মধ্যে ছিল সর্বনিম্ন সহনশীলতার দূরত্ব।

পাখির চোখের দর্শন থেকে আঁকাগুলি পথটি নীচের চিত্রের পয়েন্টগুলির মতো দেখাবে, 'ডাব্লু' (ওয়াকার) থেকে শুরু হয়ে 'টি' (লক্ষ্য) শেষ হবে। আপনি যদি আরও প্রাকৃতিক চলাচল করতে চান তবে আপনি সময়ের আগে কয়েক পয়েন্ট প্রাক্কলিত করতে হবে এবং একটি স্প্লাইন তৈরি করবে, আপনাকে আরও অনেক পয়েন্ট দেবে যাতে আপনি ওয়াকার অনুসরণ করতে পারেন। আমি অনুমান করেছি যে এই পাথটি একটি স্প্লাইন তৈরি হওয়ার পরে কেমন হবে এবং এটি চিত্রের লাইনটি দ্বারা প্রতিনিধিত্ব করা হয়েছে।

এখানে চিত্র বর্ণনা লিখুন

এবং এখানে উদাহরণ কোডটি রয়েছে:

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;
}

আপনার নির্দিষ্ট গেমের উপর ভিত্তি করে আপনি দূরত্ব, এফওভি, এলোমেলোতা এবং ফ্রিকোয়েন্সি এটি চালানো সম্ভব, যতক্ষণ না এটি আপনার প্রয়োজন অনুসারে কাজ করে। আমি নিশ্চিত যে অ্যালগরিদমটি কিছুটা সাফ হয়ে যায় এবং অনুকূলিত হতে পারে, আমি তাতে বেশি সময় ব্যয় করি না, আমি চেয়েছিলাম এটি পড়া সহজ হয় easy

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.