বৃত্তের সংঘর্ষের ভিতরে চেনাশোনা


9

আমার একটি প্রকল্পে আমার একটি বৃত্ত আকারে একটি গেম অঞ্চল রয়েছে have এই বৃত্তের অভ্যন্তরে আরও একটি ছোট বৃত্ত ঘুরছে। আমি যা করতে চাই তা হল ছোট বৃত্তটিকে বৃহত্তর বাইরে বেরিয়ে আসা থেকে বিরত রাখা। নীচে আপনি দেখতে পারেন যে ফ্রেম 2 এ ছোট বৃত্তটি আংশিকভাবে বাইরে রয়েছে, বাইরে চলে যাওয়ার ঠিক আগে আমার এটিকে আবার সরিয়ে নেওয়ার একটি উপায় প্রয়োজন। কিভাবে এই কাজ করা যেতে পারে?

বেসিক উদাহরণ

এছাড়াও, আমার বড় বৃত্তের চাপটি দিয়ে সংঘর্ষের স্থানটি দরকার যাতে আমি ছোট বৃত্তের গতিবেগ আপডেট করতে পারি। কিভাবে এই পয়েন্ট গণনা করা যেতে পারে?

আমি যা করতে চাই তা হল ছোট বৃত্তটি সরানোর আগে, আমি এর পরবর্তী অবস্থানটি পূর্বাভাস দিয়েছি এবং এটি বাইরে থাকলে আমি টি = 0 এবং টি = 1 (টি = 1 ফুলটাইম স্টেপ) এর মধ্যে সংঘর্ষের সময়টি পাই। আমার যদি সংঘর্ষের সময় টি থাকে তবে আমি পুরো সময়ের পদক্ষেপের পরিবর্তে টিয়ের সময় ছোট বৃত্তটি সরিয়ে নিয়ে যাই। তবে আবার সমস্যাটি হ'ল আমি জানি না যে কীভাবে সেই সময় সংঘর্ষটি ঘটে যখন দুটি বৃত্ত এবং একজনের মধ্যে অন্যটির উপস্থিতি আসে তখন এটি ঘটে occurs

সম্পাদনা করুন:

সংঘর্ষ পয়েন্টের উদাহরণ (সবুজ) আমি সন্ধান করতে চাই। ছবিটি কিছুটা বন্ধ থাকলেও আপনি ধারণাটি পেতে পারেন।

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

উত্তর:


10

আসুন ধরে নেওয়া যাক বড় বৃত্তের কেন্দ্র Aএবং ব্যাসার্ধ রয়েছে Rএবং ছোট বৃত্তটির কেন্দ্র Bএবং ব্যাসার্ধ rঅবস্থানের দিকে চলেছে C

এই সমস্যা সমাধানের জন্য একটি মার্জিত ভাবে ব্যবহার নেই Minkovski অঙ্কের ব্যাসার্ধ্যের ডিস্ক প্রতিস্থাপন: (subtractions, আসলে) Rব্যাসার্ধ একটি ডিস্ক সঙ্গে R-r, এবং ব্যাসার্ধ্যের ডিস্ক rব্যাসার্ধ একটি ডিস্ক সঙ্গে 0, অর্থাৎ। একটি সাধারণ পয়েন্ট অবস্থিত B। সমস্যাটি একটি লাইন-বৃত্ত ছেদ সমস্যা হয়ে যায়।

তারপরে আপনাকে কেবল দূরত্বের ACচেয়ে ছোট কিনা তা পরীক্ষা করা দরকার R-r। যদি তা হয় তবে চেনাশোনাগুলি সংঘর্ষে নেমে না। যদি এটি বড় হয় তবে কেবলমাত্র দূরত্বে অবস্থিত বিন্দুটি সন্ধান Dকরুন এবং এটি আপনার ছোট বৃত্তের কেন্দ্রের নতুন অবস্থান। এটি এটি সন্ধানের সমতুল্য :BCR-rAk

  vec(BD) = k*vec(BC)
and
  norm(vec(AD)) = R-r

প্রদানের vec(AD)সাথে প্রতিস্থাপন vec(AB) + vec(BD):

AB² + k² BC² + 2k vec(AB).vec(BC) = (R-r

প্রদত্ত প্রাথমিক অবস্থানটি বৃহত বৃত্তের ভিতরে ছিল, এই চতুর্ভুজ সমীকরণটির kএকটি ইতিবাচক মূল রয়েছে। সিউডোকোডে সমীকরণটি কীভাবে সমাধান করবেন তা এখানে:

b = - vec(AB).vec(BC) / BC²    // dot product
c = (AB² - (R-r)²) / BC²
d = b*b - c
k = b - sqrt(d)
if (k < 0)
    k = b + sqrt(d)
if (k < 0)
    // no solution! we must be slightly out of the large circle

এর মান সহ k, ছোট বৃত্তের নতুন কেন্দ্রটি Dএমন BD = kBC

সম্পাদনা : চতুর্ভুজ সমীকরণ সমাধান যুক্ত করুন


ধন্যবাদ, এটি মার্জিত দেখায় তবে আমি নিশ্চিত যে আমি বুঝতে পেরেছি তা নিশ্চিত নই। উদাহরণস্বরূপ: "খ্রিস্টপূর্বের A এর দূরত্বে D বিন্দুটি সন্ধান করুন"। আরও ভাল করে বোঝার চেষ্টা করার জন্য আমি একটি ছবি আঁকলাম । সুতরাং আমরা যদি বি (এএক্স, এওয়াই- (আরআর)) এবং সি থেকে শুরু করি তবে আমরা বর্তমান গতিবেগটি শেষ করব। আমি উদ্ধৃত পাঠ্যটি যেভাবে বুঝতে পেরেছি: খ্রিস্টপূর্ব লাইন বিভাগে একটি বিন্দু সন্ধান করুন যা এ থেকে আরআর এর দূরত্ব But অন্যদের পয়েন্টগুলি> এ। থেকে দূরে থাকবে আমি কী মিস করছি?
dbostream

@dbostream আপনি কিছুই মিস করছেন না। যদি দুটি চেনাশোনা ইতিমধ্যে যোগাযোগে থাকে তবে সনাক্ত করার জন্য এখানে কোনও প্রকৃত সংঘর্ষ নেই : সংঘর্ষ ঘটে Bএবং এর মধ্যে k=0। এখন যদি এটির সংঘর্ষের সমাধানটি আপনি চান তবে আমি আমার উত্তরে এটি আবরণ করিনি কারণ এটির জন্য বস্তুর শারীরিক বৈশিষ্ট্য সম্পর্কে জ্ঞান প্রয়োজন। কী হওয়ার কথা? অভ্যন্তরীণ বৃত্ত ভিতরে প্রবেশ করা উচিত? নাকি রোল? পরিষ্কার করা?
সাম হোচেভার 26'12

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

@dbostream যদি আন্দোলনটি এমনভাবে সীমাবদ্ধ করা উচিত তবে আমি আপনাকে পরামর্শ দিচ্ছি যত তাড়াতাড়ি সম্ভব সেই সীমাবদ্ধতা অনুসরণ করুন: যদি বেগ হয় তবে চক্রের পরিধিটি বরাবর Vঅভ্যন্তরীণ বৃত্তটিকে অগ্রসর করুন । এর অর্থ বিন্দুর চারপাশে কোণ রেডিয়ানের একটি ঘূর্ণন । এবং বেগ ভেক্টরটি একইভাবে ঘোরানো যায়। সাধারণটি (যা সর্বদা সার্কেলের কেন্দ্রের দিকে লক্ষ্য করা যায়) বা অন্য কোনও উপায়ে বেগ আপডেট করার দরকার নেই। V*tR-rV*t/(R-r)A
সাম হোচেভার

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

4

বলুন বড় বৃত্তটি বৃত্ত এ এবং ছোট বৃত্তটি বৃত্ত বি।

বি এ এর ​​অভ্যন্তরে রয়েছে কিনা তা পরীক্ষা করে দেখুন:

distance = sqrt((B.x - A.x)^2 + (B.y - A.y)^2))
if(distance > A.Radius + B.Radius) { // B is outside A }

যদি ফ্রেমে n-1বি এ এর ​​অভ্যন্তরে ছিল এবং ফ্রেমে nবি এর বাইরে ছিল এবং ফ্রেমের মধ্যে সময়টি খুব বেশি বড় ছিল না (ওরফে বি খুব বেশি দ্রুত চলছিল না) আমরা কেবল বি আত্মীয়ের কার্তেসিয়ান স্থানাঙ্কগুলি আবিষ্কার করে সংঘর্ষের বিন্দুটি অনুমান করতে পারি can একটি:

collision.X = B.X - A.X;
collision.Y = B.Y - A.Y;

এরপরে আমরা এই পয়েন্টগুলিকে একটি কোণে রূপান্তর করতে পারি:

collision.Normalize(); //not 100% certain if this step is necessary     
radians = atan2(collision.Y, collision.X)

আপনি যদি tপ্রথমবারের জন্য খ এর বাইরে থাকেন ঠিক তেমন জানতে চান তবে আপনি প্রতিটি ফ্রেমে একটি রে-বৃত্ত ছেদটি করতে পারেন এবং তারপরে বি থেকে সংঘর্ষের দূরত্বটি আরও বড় হলে তুলনা করুন বি এর ফলে দূরত্বটি যেভাবে ভ্রমণ করতে পারে বর্তমান গতি. যদি তাই হয় তবে সংঘর্ষের সঠিক সময় গণনা করতে পারেন।


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

হুম আমি মনে করি যে দৃশ্যটি সম্ভব। হতে পারে একটি নতুন বৃত্ত সি দিয়ে পরীক্ষা করুন যা বি ফ্রেডিয়াস + বি এই ফ্রেমের সর্বাধিক গতিবিধি রয়েছে, পরীক্ষা করুন যে এটি A এর সাথে সংঘর্ষিত হয়েছে এবং তারপরে সি এর যে বিন্দুটি এ থেকে আরও দূরে রয়েছে তা পরীক্ষা করুন (
রায়

3
কম শব্দ ব্যবহার করে: যদি (দূরত্ব (এ, বি))> (রা-আরবি) সংঘর্ষ হয় এবং আপনি কেবলমাত্র ছোট বৃত্তটি রা-আরবি সমান দূরত্ব পেতে সরিয়ে নিয়ে যান। অন্যথায় আপনি সাধারণত ছোট বৃত্তটি সরান। @ ডবস্ট্রিমে আপনি যে পরিমাণে অনুশীলনকারী পরিচিতিগুলির সরলীকৃত ফর্মের অনুরূপ কিছু ব্যবহার করছেন, সেটির জন্য অনুসন্ধান করার চেষ্টা করুন।
ডার্কওইংস

@ ডার্কওয়িংস +1 আপনি একেবারে ঠিক বলেছেন, এবং এটি আরও সহজ শোনায়!
রায় টি।

এটি সহজ শোনায় কারণ আমি প্রয়োজনীয় সমস্ত বেস জ্যামিতিটি সরিয়ে নিয়েছি। এটিকে 'সংঘর্ষ' নামকরণের পরিবর্তে আপনি এটির নামকরণ করতে পারেন কারণ এটি আসলে এটি ছিল: নিখরচায় ভেক্টর এবি আবদ্ধ (0,0)। একবার আপনি এটি স্বাভাবিক করে আনলে আপনি সোজা রেখার এবি বান্ডিলের সমান্তরাল এবং দরকারী ইউনিট ভেক্টর উভয়ের সমীকরণ পাবেন। তারপরে আপনি যে একক ভেক্টরকে যে কোনও দূরত্ব ডি এর জন্য গুন করতে পারেন এবং সদ্য পাওয়া প্যারামেন্টারগুলিকে আপনার প্রয়োজনীয় সংঘর্ষের পয়েন্টটি সন্ধান করতে পারেন: সি (এক্স + ডিএক্স, এআই + ডাই)। এখন এটি আরও জটিল মনে হচ্ছে তবে এটি একই জিনিস: পি
ডার্কওইংস

0

(Xa, Ya) বড় বৃত্তের অবস্থান এবং এটি ব্যাসার্ধ R, এবং (Xb, Yb) ছোট বৃত্তের অবস্থান এবং এটি ব্যাসার্ধ r Let

এই দুটি বৃত্তের সংঘর্ষ হয় কিনা তা আপনি পরীক্ষা করতে পারেন

DistanceTest = sqrt(((Xa - Xb) ^ 2) + ((Ya - Yb) ^ 2)) >= (R - r)

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

left = 0 //the frame with no collision
right = 1 //the frame after collision
steps = 8 //or some other value, depending on how accurate you want it to be
while (steps > 0)
    checktime = left + (right - left) / 2
    if DistanceTest(checktime) is inside circle //if at the moment in the middle of the interval [left;right] the small circle is still inside the bigger one
        then left = checktime //the collision is after this moment of time
        else right = checktime //the collision is before
    steps -= 1
finaltime = left + (right - left) / 2 // the moment of time will be somewhere in between, so we take the moment in the middle of interval to have a small overall error

আপনি যখন সংঘর্ষের সময়টি জানেন, চূড়ান্ত সময়ে দুটি চেনাশোনাগুলির অবস্থানগুলি গণনা করুন এবং চূড়ান্ত সংঘর্ষের স্থান

CollisionX = (Xb - Xa)*R/(R-r) + Xa
CollisionY = (Yb - Ya)*R/(R-r) + Ya

0

আমি স্যাম হোসেভারের দ্বারা বর্ণিত অ্যালগরিদমটি ব্যবহার করে জেসফিডেলে একটি বৃত্তে বাউনের একটি ডেমো প্রয়োগ করেছি :

http://jsfiddle.net/klenwell/3ZdXf/

জাভাস্ক্রিপ্ট এখানে যোগাযোগের বিষয়টি চিহ্নিত করে:

find_contact_point: function(world, ball) {
    // see https://gamedev.stackexchange.com/a/29658
    var A = world.point();
    var B = ball.point().subtract(ball.velocity());
    var C = ball.point();
    var R = world.r;
    var r = ball.r;

    var AB = B.subtract(A);
    var BC = C.subtract(B);
    var AB_len = AB.get_length();
    var BC_len = BC.get_length();

    var b = AB.dot(BC) / Math.pow(BC_len, 2) * -1;
    var c = (Math.pow(AB_len, 2) - Math.pow(R - r, 2)) / Math.pow(BC_len, 2);
    var d = b * b - c;
    var k = b - Math.sqrt(d);

    if ( k < 0 ) {
        k = b + Math.sqrt(d);
    }

    var BD = C.subtract(B);
    var BD_len = BC_len * k;
    BD.set_length(BD_len);

    var D = B.add(BD);
    return D;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.