কোয়াড ট্রি / গ্রিড ভিত্তিক সংঘর্ষ - কার্যত যুক্তিকে যুক্ত করা


13

প্রথমত, আমি কেবলমাত্র অল্প সময়ের জন্য নিজের গেমের যুক্তিটি লিখছি, তাই যদি এটিকে সরাসরি সামনে মনে হয় তবে আমি ক্ষমাপ্রার্থী।

আমি কোয়াড ট্রি এবং গ্রিড ভিত্তিক সংঘর্ষ সনাক্তকরণ সম্পর্কে প্রচুর পড়ছি। আমি যুক্তিটি বুঝতে পারি - মূলত বস্তুগুলি মূলত কাছাকাছি না থাকলে মূলত সংঘর্ষের জন্য যাচাই করবেন না। তবে এটি কখনই বাস্তবে এটি কার্যকর করে তা উল্লেখ করা হয়নি।

আমার মাথায় বেশ কয়েকটি সম্ভাব্য পদ্ধতি রয়েছে তবে কোনটি সবচেয়ে ভাল তা নিশ্চিত নই

সাধারণ সংঘর্ষ পরীক্ষা - কোন অপ্টিমাইজেশন

for(var i:int = 0; i < objects.length; i++){
        //find object A
        var objectA = objects[i];

        for(var j:int = i + 1; j < objects.length; j++){
            //find object B
            var objectB = objects[j];

            if(objectA.collidesWith(objectB){

               //handle collision logic
              }
        }

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

var objects:Array = new Array();
    var neighbours:Array = new Array();

    for(var i:int = 0; i < objects.length; i++){
        //find object A
        var objectA = objects[i];

        for(var j:int = i + 1; j < objects.length; j++){
            //find object B
            var objectB = objects[j];

            if(objectA.isNear(objectB){

               neighbours.push(objectA, objectB);
              }
        }

    }

    //somewhere else
    for(i:int = 0; i < neighbours.length; i++){
        //only check neighbours

        for(j:int = i + 1; j < neighbours.length; j++){

            if(objectA.collidesWith(objectB){

               //handle collision logic
              }
        }
    }

সমস্ত বস্তু লুপ করুন তবে কেবল সংঘর্ষের জন্য প্রতিবেশীদের পরীক্ষা করুন (পদ্ধতি 3) অন্যান্য সম্ভাবনা হ'ল আমরা এখনও সমস্ত কিছু লুপ করছি তবে সংঘর্ষের পরীক্ষার আগে বস্তুগুলি কাছে রয়েছে কিনা তা পরীক্ষা করে দেখুন।

for(var i:int = 0; i < objects.length; i++){
        //find object A
        var objectA = objects[i];

        for(var j:int = i + 1; j < objects.length; j++){
            //find object B
            var objectB = objects[j];

            if(objectA.isNear(objectB){
               //they are near - check collision!
               if(objectA.collidesWith(objectB){

               //handle collision logic
              }
            }
        }

    }

টাইলের ডেটাগুলিতে অবজেক্টগুলি সঞ্চয় করুন (পদ্ধতি 3) টাইল ভিত্তিক সিমেট ব্যবহার করে অন্য বিকল্পের জন্য অনুমতি দেওয়া; টাইলের ডেটাতেই নির্দিষ্ট টাইলের উপর থাকা অবজেক্টগুলিকে সঞ্চয় করুন। আশেপাশের টাইলগুলিতে কোন টাইলের সাথে টাইলটি পড়তে পারে এমন কোনও বস্তু রয়েছে তা পরীক্ষা করে দেখুন:

var ObjectA;

for(var i:int = 0; i < 4; i ++){
//check 4 surrounding tiles from object A

   if(Object.currentTile + surroundingTile[i] CONTAINS collidable object){
   //check collision!
    if(objectA.collidesWith(surroundingTile.object){

    //handle collision logic
     }

}
}

আমি সবসময় উদাহরণ হিসাবে বাস্তব জগতের দিকে দেখার চেষ্টা করি। আমি যদি আইটেমগুলিকে একই রঙের সাথে তুলনা করতে চাইতাম তবে রঙের সাথে না মেলে এমনকি প্রতিটি আইটেমটি পরীক্ষা করা অযৌক্তিক মনে হবে (পদ্ধতি 2, প্রতিটি আইটেম পরীক্ষা করুন)। আমি সম্ভবত একই রঙ (আইটেমগুলি একে অপরের কাছাকাছি) দিয়ে সংগ্রহ করব এবং সমস্ত কিছু যাচাই করার পরিবর্তে সেগুলি (পদ্ধতি 1) পরীক্ষা করব।

সংঘর্ষের চেকিংয়ের আইটেমগুলি ক্রমাগত চলমান থাকে যাতে অর্ডার মিশ্রিত হয় এটি এটিকে অনুমোদনের তুলনা করে না। যা আমাকে বিভ্রান্ত করছে।

প্রতিবেশীদের একটি অ্যারে জেনারেট করে রাখার স্ট্রেনটি সরিয়ে প্রতিটি আইটেম পরীক্ষা করা কি আরও দক্ষ হবে?

অথবা প্রতিবেশীদের যাতে সংঘর্ষটি চেক করার জন্য এতগুলি বস্তুর মধ্য দিয়ে লুপ না করতে হয় তা আরও দক্ষ?

প্রতিটি টাইলের ডেটা পরিবর্তন করা পাশাপাশি খুব নিবিড় বলে মনে হচ্ছে, সুতরাং আমি নিশ্চিত নই যে এটি একটি ভাল ধারণা ..

আমি একটি টাওয়ার প্রতিরক্ষা গেমের কথা ভাবছিলাম যেখানে টাওয়ারটি শ্যুট করার আগে যদি বস্তুগুলি সীমার মধ্যে থাকে তবে টাওয়ারটি সনাক্ত করতে হবে। সমস্ত আইটেমগুলি চেক করা কেবল নির্বোধ বলে মনে হয় যখন কোনও সময়ে কোনও বস্তু একেবারেই কাছে আসবে না।

আমি দীর্ঘ পোস্টের জন্য ক্ষমা চাইছি, নিজেকে বোঝাতে সর্বদা সমস্যা হয়!


এই কি ভাষা? জাভাস্ক্রিপ্ট?
কাইল সি

2
অ্যাকশনসক্রিপ 3, তবে ভাষাটি বেশ অপ্রাসঙ্গিক। এটি হ্যান্ডেল এবং কাঠামোগত করার সর্বোত্তম
উপায়টি কী

উত্তর:


8

আপনাকে প্রকৃত সংঘর্ষের পরীক্ষার গণনা হ্রাস করতে হবে। হ্যাঁ স্পষ্ট আমি জানি। সুতরাং এর উপর বিস্তারিত জানাতে দিন:

আপনার প্রথম সংঘর্ষ চেক অ্যালগরিদম কোনও অপ্টিমাইজেশন ছাড়াই: এটি এক রানে কতগুলি চেক করবে? যদি n হ'ল অবজেক্টের গণনা হয় তবে এটি n * (n-1) টি পরীক্ষার কাছাকাছি হবে। অনেকগুলি অবজেক্টের জন্য (> 100) এটি মারাত্মকভাবে ধীর হবে।

আপনার প্রতিবেশী যাচাইয়ের পদ্ধতিটি আরও দ্রুত হবে না। যদি আপনার অবজেক্টগুলি স্থিতিশীল না হয় এবং প্রচুর পরিমাণে ঘোরাফেরা করে তবে আপনার গেম লুপে প্রতিবারের জন্য আপনাকে এই প্রতিবেশীদের তালিকা তৈরি করতে হবে। প্রতিবেশীর তালিকাটি তৈরি করতে আপনি এন * (এন -1) করছেন এবং তারপরে প্রতিবেশীর কোনওটির সাথে এটি সংঘর্ষিত হয় কিনা তা প্রতিটি বস্তুর জন্য পরীক্ষা করে দেখুন এটি আসলে প্রথম অ্যালগরিদমের চেয়েও খারাপ।

আপনার গেম স্পেসটি ভাগ করতে হবে। আপনার গেমের স্থান 400x400 পিক্সেল প্রশস্ত বলতে দিন। আপনি এটি প্রতি 200x200 আকারে 4 টি সাব-স্পেসে বিভক্ত করতে পারেন এবং এটি যে সাব-স্পেসের অন্তর্গত তা প্রতিটি বস্তুর জন্য পরীক্ষা করতে পারেন (একটি বস্তু একাধিক উপ-স্পেসের অভ্যন্তরে থাকতে পারে)। তারপরে আপনার কেবলমাত্র প্রতিটি সাবস্পেসের অবজেক্ট একই উপ-স্পেসের অন্য বস্তুর সাথে সংঘর্ষিত হয়েছে কিনা তা পরীক্ষা করতে হবে।

সুতরাং রানটাইম ব্যয় হবে: 4 টি উপ-স্থান তালিকা + (এন / 4) * ((এন -1) / 4) তৈরি করার জন্য যা আগের রানটাইম ব্যয়ের চেয়ে অনেক ভাল। এটি সাব-স্পেসগুলি আরও ছোট করে তৈরি করা যেতে পারে (উদাঃ 50x50)।

সুতরাং আমাদের অ্যালগরিদম এখন এরকম কিছু দেখাচ্ছে:

for each (object in objects)
  check into which subspace the object belongs

for each (subspace in subspaces)
  for each (object in subspace)
    check object for collision with other objects in same subspace

এটি আপনার টাইলের ডেটা ধারণার সাথে কিছুটা মিল। তবে সাব-স্পেসগুলি টাইলসের সমান আকারের হওয়ার দরকার নেই।

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

এই ব্যয়টি হ্রাস করতে আমরা একটি চতুর্ভুজ ব্যবহার করি। চতুষ্কোণ হল আমাদের গেমের স্পেসটি ভাগ করার আরেকটি উপায়। আমাদের 400x400 স্পেসটি 64 50x50 উপ-স্পেসে বিভক্ত করার পরিবর্তে এবং বর্তমানে বর্তমানে যে 64 টি উপ-স্পেস রয়েছে সেগুলির প্রতিটি বস্তুর জন্য এটি পরীক্ষা করার পরিবর্তে গেম স্পেসটি 4 স্পেসস্পেসগুলিতে গেম স্পেসের অর্ধেক আকারে (200x200) বিভক্ত হয়ে যায়, যা পরিবর্তিত হয় ছোট ছোট সাবস্পেস (100x100), যা ঘুরে আবার 50x50 উপ-স্পেসে বিভক্ত হয়। এটি আমাদের চতুর্ভুজ।

এখন যদি আমরা কোন বস্তুর অন্তর্ভুক্ত হয় কোন 50x50 উপ-স্থানের মধ্যে এটি জানতে চাই আমরা 200x200 উপ-স্থানগুলির মধ্যে কোনটি পরীক্ষা করে তা পরীক্ষা করে দেখি। তারপরে আমরা আমাদের চতুর্মুখী স্তরে আরও গভীরতর এক জায়গায় যাই এবং 410x100 উপ-স্থানের সন্ধান করি যা 200x200 উপস্থানের সন্ধান পেয়েছে just অবজেক্টটি কোন 50x50 সাবস্পেসের মধ্যে এটি অবধি জানা না হওয়া অবধি এটি পুনরাবৃত্তি হবে। সুতরাং এখন কত চেক প্রয়োজন ছিল? চতুষ্কোণীর প্রতিটি স্তরের জন্য 4 (মনে রাখবেন কোনও বস্তু দুটি উপ-স্পেসের প্রান্তে থাকতে পারে)। সুতরাং আমাদের 50 * 50 সাবস্পেসে একটি অবজেক্ট বরাদ্দ করতে 4 * 3 টি চেক দরকার। 64৪ টি চেকের চেয়ে অনেক বেশি ভাল।

সুতরাং আমাদের কোয়াড্ট্রি অ্যালগরিদমের সাবস্পেস তালিকাগুলি তৈরি করতে 4 * 3 * n টি চেক প্রয়োজন এবং তারপরে প্রতিটি বস্তুর সংঘর্ষগুলি পরীক্ষা করতে কে * (এন / কে) এর মতো কিছু পরীক্ষা করা উচিত।


একটি খুব পরিষ্কার এবং বোধগম্য অ্যাঞ্জেন্সার, অনেক ধন্যবাদ! কোন উপস্থানে কোন অবজেক্টটি এটি পরিচালনা করা হয়? উপ-স্থানটি কি কোনও অবজেক্ট হিসাবে হ্যান্ডেল করা হয়েছে, যেখানে তার অবজেক্টটি অ্যারে হিসাবে সংরক্ষণ করা হয়েছে এবং একে অপরের বিপরীতে পরীক্ষা করা হয়েছে? বা প্রধান লুপটির ভিতরে এক্স এবং ওয়াই পরীক্ষা করে আপনি কেবল কোন সাবস্পেসটি পরীক্ষা করছেন? দেখে মনে হচ্ছে সারাক্ষণ অ্যারে বিল্ডিং এবং পরিবর্তন করা বেশ কার্যকর is সুতরাং আমি নিশ্চিত হতে চাই যে আমি উপযুক্ত পদ্ধতিটি ব্যবহার করি :) আমি যখন বস্তুগুলির আকারের আকারে পৃথক হয় তখন সমস্যা দেখা দিতে পারি। আমার ধারণা, ক্ষুদ্রতম উপসর্গটি সবচেয়ে বড় অবজেক্টের মতো হওয়া উচিত?
omgnoseat

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

ধন্যবাদ, ভুলে গেছি যে আমরা ক্ষুদ্রতম উপস্থানে প্রকৃত বস্তুর মধ্যে সংঘর্ষগুলিও চেক করব, তা বোঝা যায় যে এটি এখন একাধিক বস্তু ধরে রাখতে সক্ষম হবে। আমি একটি পরীক্ষা শুরু করেছি এবং এটি সুন্দরভাবে সামনে আসছে। আমার সবচেয়ে বড় সমস্যাটি হ'ল এটি সনাক্ত করা যা কোন বস্তুর অন্তর্ভুক্ত subs আমি সাবস্পেস বাচ্চাদের এক্স এবং ওয়াইয়ের মানগুলির মধ্য দিয়ে লুপিং চালিয়ে যাচ্ছি, এটি কি অ্যাপ্রোপিয়েট পদ্ধতি?
বাদ দিন

একাধিক উপ-স্পেসে বিস্তৃত বস্তুগুলি আপনি কীভাবে পরিচালনা করবেন (যেমন যার অবস্থান একটি সীমানার উপরে বা তার কাছাকাছি)?
mghicks

সাধারণ: আমি না। যদি প্রতিটি সাবস্পেসের সীমানায় থাকে তবে অবজেক্টগুলি একাধিক সাবস্পেসের অংশ হতে পারে। সুতরাং একটি অবজেক্ট 4 টি সাবস্পেসের অংশ হতে পারে। তবে এটি সংখ্যালঘু।
স্টিফেন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.