বল টু বল সংঘর্ষ - সনাক্তকরণ এবং পরিচালনা


266

স্ট্যাক ওভারফ্লো সম্প্রদায়ের সহায়তায় আমি একটি সুন্দর মৌলিক-তবে মজাদার পদার্থবিজ্ঞান সিমুলেটর লিখেছি।

বিকল্প পাঠ

আপনি একটি বল চালু করতে মাউসকে ক্লিক করুন এবং টেনে আনুন। এটি চারদিকে বাউন্স করবে এবং শেষ পর্যন্ত "তলে" থামবে।

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

আমার ধারণা আমার প্রশ্নের দুটি অংশ রয়েছে:

  1. বল থেকে বলের সংঘর্ষ শনাক্ত করার সেরা পদ্ধতি কী?
    আমার কি কেবলমাত্র একটি ও (এন ^ 2) লুপ রয়েছে যা প্রতিটি বলের উপরে পুনরাবৃত্তি করে এবং অন্যান্য বলটি এটি ব্যাসার্ধের ওভারল্যাপ হয় কিনা তা পরীক্ষা করে দেখায়?
  2. বল সংঘর্ষে বল পরিচালনা করতে আমি কী সমীকরণগুলি ব্যবহার করব? পদার্থবিজ্ঞান 101
    এটি দুটি বলের গতি X / y ভেক্টরকে কীভাবে প্রভাবিত করে? দুটি বল মাথা নীচু করার ফলে দিকটি কী? আমি প্রতিটি বল এ কীভাবে প্রয়োগ করব?

বিকল্প পাঠ

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

কিছু দ্রুত স্পষ্টতা: সরলতার জন্য আমি আপাতত একটি নিখুঁত স্থিতিস্থাপক সংঘর্ষের সাথে ঠিক আছি, আমার সমস্ত বলগুলিতে এখন একই ভর রয়েছে, তবে ভবিষ্যতে আমি এটি পরিবর্তন করতে পারি।


সম্পাদনা করুন: সংস্থানগুলি আমি দরকারী বলে মনে করেছি

ভেক্টর সহ 2 ডি বল পদার্থবিজ্ঞান: ত্রিগোনমিতি ছাড়া 2-মাত্রিক সংঘর্ষ। Pdf
2 ডি বল সংঘর্ষ সনাক্তকরণ উদাহরণ: সংযুক্তি সনাক্তকরণ


সফল!

আমার বল সংঘর্ষ সনাক্তকরণ এবং প্রতিক্রিয়া দুর্দান্ত কাজ করছে!

প্রাসঙ্গিক কোড:

সংঘর্ষ সনাক্তকরণ:

for (int i = 0; i < ballCount; i++)  
{  
    for (int j = i + 1; j < ballCount; j++)  
    {  
        if (balls[i].colliding(balls[j]))  
        {
            balls[i].resolveCollision(balls[j]);
        }
    }
}

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

তারপরে, আমার বল ক্লাসে আমার সংঘর্ষ () এবং রেজোলিউশনসিদ্ধকরণ () পদ্ধতি রয়েছে:

public boolean colliding(Ball ball)
{
    float xd = position.getX() - ball.position.getX();
    float yd = position.getY() - ball.position.getY();

    float sumRadius = getRadius() + ball.getRadius();
    float sqrRadius = sumRadius * sumRadius;

    float distSqr = (xd * xd) + (yd * yd);

    if (distSqr <= sqrRadius)
    {
        return true;
    }

    return false;
}

public void resolveCollision(Ball ball)
{
    // get the mtd
    Vector2d delta = (position.subtract(ball.position));
    float d = delta.getLength();
    // minimum translation distance to push balls apart after intersecting
    Vector2d mtd = delta.multiply(((getRadius() + ball.getRadius())-d)/d); 


    // resolve intersection --
    // inverse mass quantities
    float im1 = 1 / getMass(); 
    float im2 = 1 / ball.getMass();

    // push-pull them apart based off their mass
    position = position.add(mtd.multiply(im1 / (im1 + im2)));
    ball.position = ball.position.subtract(mtd.multiply(im2 / (im1 + im2)));

    // impact speed
    Vector2d v = (this.velocity.subtract(ball.velocity));
    float vn = v.dot(mtd.normalize());

    // sphere intersecting but moving away from each other already
    if (vn > 0.0f) return;

    // collision impulse
    float i = (-(1.0f + Constants.restitution) * vn) / (im1 + im2);
    Vector2d impulse = mtd.normalize().multiply(i);

    // change in momentum
    this.velocity = this.velocity.add(impulse.multiply(im1));
    ball.velocity = ball.velocity.subtract(impulse.multiply(im2));

}

উত্স কোড: বল টু বলের জন্য সম্পূর্ণ উত্স coll

কারও কাছে যদি এই বেসিক ফিজিক্স সিমুলেটরটি উন্নত করার জন্য কিছু পরামর্শ থাকে তবে আমাকে জানান! আমি এখনও একটি জিনিস যোগ করতে চাই কৌণিক গতি তাই বল আরও বাস্তববাদী রোল করবে। অন্য কোন পরামর্শ? মতামত দিন!


16
আমি মনে করি না এই অ্যালগরিদম ভাল যথেষ্ট কারণ আপনার বাজে কথা খুব দ্রুত চলন্ত ইন করেন (প্রাক্তন হয় না। কোনো দুর্ঘটনায় ছাড়া দ্রুত তারপর 2 ফ্রেম প্রতি * ব্যাসার্ধ, এক বল অন্য বল মাধ্যমে প্রেরণ করতে পারেন
বেনজি Mizrahi

@ সিমুলকাল আপনি কি আবার আপনার উত্স কোড আপলোড করতে পারবেন (সমস্ত ফাইলড্রপার ডটকম লিঙ্কগুলি ভাঙ্গা মনে হচ্ছে)।
জিওসিটিগুলি

1
: এখানে BallBounce আমি শেষ সংস্করণ একটি লিঙ্ক কাজ হয় dl.dropbox.com/u/638285/ballbounce.rar
mmcdole

@ যারা অবদান রেখেছেন তাদের সবাইকে: আপনি কি এই ইঞ্জিনটিকে 3D এ রূপান্তর করতে দয়া করে কিছুটা আলোকপাত করতে পারেন? এই দুর্দান্ত ইঞ্জিনটি কীভাবে জাভা 3 ডি তে কাজ করতে পারে।
স্থির অকার্যকর মূল

2
লাইনটি Vector2d impulse = mtd.multiply(i);আমি * সাধারণীকরণ করা এমটিডি ভেক্টর হতে হবে। এর মতো কিছু:Vector2d impulse = mtd.normalize().multiply(i);
ক্লেনওয়েল

উত্তর:


117

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

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

v_ {1} = rac frac {u_ {1} (এম_ {1} -ম_ {2}) + 2 মি_ {2} ইউ_ {2}} {এম_ {1} + এম_ {2}}

v_ {2} = \ frac {u_ {2} (এম_ {2} -ম_ {1}) + 2 মি_ {1} ইউ_ {1}} {এম_ {1} + এম_ {2}}

যদি বলগুলির একই ভর থাকে তবে বেগগুলি কেবল স্যুইচ করা হয়। আমি এখানে কিছু কোড লিখেছি যা কিছু অনুরূপ করে:

void Simulation::collide(Storage::Iterator a, Storage::Iterator b)
{
    // Check whether there actually was a collision
    if (a == b)
        return;

    Vector collision = a.position() - b.position();
    double distance = collision.length();
    if (distance == 0.0) {              // hack to avoid div by zero
        collision = Vector(1.0, 0.0);
        distance = 1.0;
    }
    if (distance > 1.0)
        return;

    // Get the components of the velocity vectors which are parallel to the collision.
    // The perpendicular component remains the same for both fish
    collision = collision / distance;
    double aci = a.velocity().dot(collision);
    double bci = b.velocity().dot(collision);

    // Solve for the new velocities using the 1-dimensional elastic collision equations.
    // Turns out it's really simple when the masses are the same.
    double acf = bci;
    double bcf = aci;

    // Replace the collision velocity components with the new ones
    a.velocity() += (acf - aci) * collision;
    b.velocity() += (bcf - bci) * collision;
}

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


2
বলুন যে দুটি বলের জনগণ সমান নয়। কীভাবে বলের মধ্যে ভেক্টর পরিবর্তিত হয়?
এমএমসিডল

3
12 ম শ্রেণীর পরে এটি বেশ কিছুক্ষণ হয়েছে, তবে আমি মনে করি তারা জনগণের অনুপাতের সাথে সঙ্গতিপূর্ণ গতির একটি অনুপাত পেয়েছে।
রায়ান ফক্স

6
@ জায়ে, কেবল দেখানোর জন্য .. যে একটি সমীকরণ চিত্র আপনি যুক্ত করেছেন সেটি 1 মাত্রিক সংঘর্ষের জন্য, 2 মাত্রিক নয়।
এমএমসিডল

@simucal। সত্য নয় ... আপনি এবং ভি সেই সমীকরণের ভেক্টর। অর্থাৎ, তাদের x, y (এবং z) উপাদান রয়েছে।
অ্যান্ড্রু রোলিংস

2
@ সিমুকাল, আপনি ঠিক বলেছেন, তারা এক মাত্রিক ক্ষেত্রে for আরও মাত্রা জন্য, কেবল সংঘর্ষের সাথে সামঞ্জস্যপূর্ণ বেগের উপাদানগুলি ব্যবহার করুন (এসিআই, কোডে বিসিআই)। অন্যান্য উপাদানগুলি সংঘর্ষের জন্য অরথগোনাল এবং পরিবর্তিত হবে না, তাই আপনাকে তাদের সম্পর্কে চিন্তা করার দরকার নেই।
জে কনরোড

48

ঠিক আছে, কয়েক বছর আগে আমি এখানে আপনি উপস্থাপন মত প্রোগ্রাম তৈরি।
একটি লুকানো সমস্যা রয়েছে (বা অনেকগুলি দৃষ্টিভঙ্গির উপর নির্ভর করে):

  • বলের গতি যদি খুব বেশি হয় তবে আপনি সংঘর্ষটি মিস করতে পারেন।

এবং এছাড়াও, প্রায় 100% ক্ষেত্রে আপনার নতুন গতি ভুল হবে। ভাল, গতি নয় , তবে অবস্থানগুলি । আপনাকে সঠিক জায়গায় সঠিকভাবে নতুন গতি গণনা করতে হবে । অন্যথায় আপনি কেবল কিছু ছোট "ত্রুটি" পরিমাণে বলগুলি স্থানান্তর করেন যা পূর্ববর্তী পৃথক পদক্ষেপ থেকে পাওয়া যায়।

সমাধানটি সুস্পষ্ট: আপনাকে টাইমস্টেপটি বিভক্ত করতে হবে, যাতে প্রথমে আপনি সঠিক জায়গায় স্থানান্তরিত হন, তারপরে সংঘর্ষে জড়িত হন, তারপরে আপনার অবশিষ্ট সময়টি স্থানান্তরিত করুন।


যদি স্থানগুলিতে স্থানান্তরিত হয় timeframelength*speed/2, তবে অবস্থানগুলি পরিসংখ্যানগতভাবে স্থির করা হবে।
নাকিলন

@ নকিলন: না, এটি কেবলমাত্র কিছু ক্ষেত্রে সহায়তা করে, তবে সাধারণত সংঘর্ষটি মিস করা সম্ভব। এবং সংঘর্ষের হাতছাড়া হওয়ার সম্ভাবনা সময়সীমার দৈর্ঘ্যের আকারের সাথে বেড়ে যায়। যাইহোক, দেখে মনে হচ্ছে আলেফ সঠিক সমাধানটি প্রদর্শন করেছে (আমি যদিও এটি স্কিম করেছিলাম)।
avp

1
@avp, আমি ছিলাম না বলের গতি যদি খুব বেশি হয় তবে আপনি সংঘর্ষটি মিস করতে পারেন। তবে আপনার নতুন অবস্থান সম্পর্কে ভুল হবে । সংঘর্ষের কারণে কিছুটা পরে সনাক্ত করা হচ্ছে, তারা সত্যিকারের সংঘর্ষের চেয়ে, যদি timeframelength*speed/2সেই অবস্থান থেকে বিয়োগ করা হয় তবে নির্ভুলতা দ্বিগুণ হবে।
নাকিলন

20

এই সমস্যাটি সমাধান করার জন্য আপনার স্পেস পার্টিশন ব্যবহার করা উচিত।

আপ পড়ুন বাইনারি স্পেস পার্টিশনের এবং Quadtrees


4
স্থান বিভাজনের পরিবর্তে, একটি ঝাড়ু এবং ছাঁটাই অ্যালগরিদম আরও ভাল কাজ করবে না ? বলগুলি দ্রুত গতিতে চলছে, সুতরাং যে কোনও বিভাজনকে ঘন ঘন আপডেট করা উচিত, ওভারহেড ব্যয় করে। কোনও ঝাড়ু এবং ছাঁটাই কোনও ক্ষণস্থায়ী ডেটা স্ট্রাকচার ছাড়াই ও (এন লগ এন) এর সমস্ত সংঘর্ষের জুটি খুঁজে পেতে পারে। বুনিয়াদিগুলির জন্য এখানে একটি ভাল টিউটোরিয়াল রয়েছে
হুগোউর

13

অঞ্চলগুলিতে স্ক্রিনটি বিভক্ত করার জন্য রায়ান ফক্সের পরামর্শের স্পষ্টতা হিসাবে, এবং কেবলমাত্র অঞ্চলগুলির মধ্যে সংঘর্ষের জন্য অনুসন্ধান করা হচ্ছে ...

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

এটি একেবারে সঠিক সমাধান। এটির সাথে একমাত্র সমস্যা (অন্য পোস্টারটি ইঙ্গিত করেছে) হ'ল সীমানা পেরিয়ে সংঘর্ষের সমস্যা।

এর সমাধানটি হ'ল একটি দ্বিতীয় গ্রিডকে 0.5 ইউনিট উল্লম্ব এবং অনুভূমিক অফসেটে প্রথম একের কাছে ওভারলে করা।

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


আরও নির্ভুল সমাধানের জন্য +1 এবং কাপুরুষোচিত ড্রাইভ বাই ডাউনভোটারের বিরুদ্ধে লড়াই করার জন্য
স্টিভেন এ। লো

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

10

সংঘর্ষের চেকগুলির সংখ্যা হ্রাস করার একটি ভাল উপায় হ'ল পর্দাটি বিভিন্ন বিভাগে বিভক্ত করা। তারপরে আপনি কেবলমাত্র প্রতিটি বলটিকে একই বিভাগে বলের সাথে তুলনা করুন।


5
কারেকশন: আপনি একই এবং সংলগ্ন বিভাগে সঙ্গে collisions জন্য চেক করতে হবে
দ্রণ

7

অনুকূলিতকরণের জন্য আমি এখানে একটি জিনিস দেখছি।

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

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

ও (এন ^ 2) হিসাবে, আপনি যা করতে পারেন তা হ'ল যেগুলি প্রত্যাখ্যান করে তার ব্যয় হ্রাস করুন:

1) এমন একটি বল যা চলতে পারে না কিছুই আঘাত করতে পারে না। যদি মেঝেতে চারপাশে যুক্তিসঙ্গত বল পড়ে থাকে তবে এটি অনেক পরীক্ষার সাশ্রয় করতে পারে। (দ্রষ্টব্য যে স্থির বলটিতে কিছু আঘাত করেছে কিনা তা অবশ্যই আপনার অবশ্যই পরীক্ষা করা উচিত))

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

3) আমি যেমনটি উল্লেখ করেছি, বর্গমূল করবেন না।


বর্গমূলের টিপ সম্পর্কিত তথ্যের জন্য আপনাকে ধন্যবাদ। বর্গক্ষেত্রের সাথে তুলনা করার সময় এর ব্যয়বহুল প্রকৃতি সম্পর্কে জানতাম না।
এমএমসিডোল

আর একটি অপটিমাইজেশন হ'ল বলগুলি যা অন্য কোনও বলের কাছে নেই find বলের গতিবেগ সীমাবদ্ধ থাকলে কেবল এটি নির্ভরযোগ্যভাবে কাজ করবে।
ব্র্যাড গিলবার্ট

1
বিচ্ছিন্ন বলগুলি খুঁজতে আমি একমত নই। এটি সংঘর্ষ সনাক্ত করার মতোই ব্যয়বহুল। জিনিসগুলিকে উন্নত করতে আপনার এমন কিছু দরকার যা প্রশ্নযুক্ত বলের জন্য O (n) এর চেয়ে কম।
লরেইন পেচটেল 7:25 '

7

আমি 2D তে সংঘর্ষ সনাক্তকরণ এবং প্রতিক্রিয়া সম্পর্কিত তথ্যের সাথে একটি দুর্দান্ত পৃষ্ঠা পেয়েছি।

http://www.metanetsoftware.com/technique.html

এটি একাডেমিক দৃষ্টিকোণ থেকে এটি কীভাবে হয়েছে তা বোঝানোর চেষ্টা করেন। তারা সাধারণ অবজেক্ট থেকে টু-অবজেক্টের সংঘর্ষ সনাক্তকরণ দিয়ে শুরু করে এবং সংঘর্ষের প্রতিক্রিয়াতে এবং কীভাবে এটি স্কেল করা যায় তার দিকে এগিয়ে যায়।

সম্পাদনা: আপডেট লিঙ্ক


3

এটি করার জন্য আপনার কাছে দুটি সহজ উপায় রয়েছে। জে বলের কেন্দ্র থেকে চেকিংয়ের সঠিক উপায়টি কভার করেছেন।

সহজ উপায় হ'ল আয়তক্ষেত্রের বাউন্ডিং বাক্সটি ব্যবহার করা, আপনার বক্সের আকারটি বলের 80% আকারে সেট করা এবং আপনি সংঘর্ষটি বেশ ভালভাবে অনুকরণ করতে পারেন।

আপনার বল শ্রেণিতে একটি পদ্ধতি যুক্ত করুন:

public Rectangle getBoundingRect()
{
   int ballHeight = (int)Ball.Height * 0.80f;
   int ballWidth = (int)Ball.Width * 0.80f;
   int x = Ball.X - ballWidth / 2;
   int y = Ball.Y - ballHeight / 2;

   return new Rectangle(x,y,ballHeight,ballWidth);
}

তারপরে, আপনার লুপে:

// Checks every ball against every other ball. 
// For best results, split it into quadrants like Ryan suggested. 
// I didn't do that for simplicity here.
for (int i = 0; i < balls.count; i++)
{
    Rectangle r1 = balls[i].getBoundingRect();

    for (int k = 0; k < balls.count; k++)
    {

        if (balls[i] != balls[k])
        {
            Rectangle r2 = balls[k].getBoundingRect();

            if (r1.Intersects(r2))
            {
                 // balls[i] collided with balls[k]
            }
        }
    }
}

1
এটি বলগুলি অনুভূমিক এবং উল্লম্ব সংঘর্ষে 20% একে অপরকে যেতে দেয়। দক্ষতার পার্থক্য নগণ্য হিসাবে, পাশাপাশি বিজ্ঞপ্তি বাউন্ডিং বাক্স ব্যবহার করতে পারে। এছাড়াও, (x-width)/2হওয়া উচিত x-width/2
মার্কাস জারাদারোট

অগ্রাধিকার টাইপো ভাল কল। আপনি দেখতে পাবেন যে বেশিরভাগ 2 ডি গেমগুলি আয়তক্ষেত্রাকার বাউন্ডিং বাক্সগুলি অ আয়তক্ষেত্রাকার আকারগুলিতে ব্যবহার করে কারণ এটি দ্রুত এবং ব্যবহারকারী প্রায়শই কোনওভাবেই লক্ষ্য করেন না।
ফ্লাইওয়াত

আপনি আয়তক্ষেত্রাকার বাউন্ডিং বাক্সটি করতে পারেন, তারপরে যদি হিট থাকে তবে এটি বিজ্ঞপ্তিযুক্ত বাউন্ডিং বাক্সটি পরীক্ষা করে check
ব্র্যাড গিলবার্ট

1
@ জোনাথান হল্যান্ড, আপনার অভ্যন্তরীণ লুপটি হওয়া উচিত (int k = i + 1; ...) এটি সমস্ত অনর্থক চেক থেকে মুক্তি পাবে। (অর্থাত্ নিজের সংঘর্ষের সাথে চেক করা এবং বল 2 এর সাথে বল 2 পরে বল 2 এর সাথে সংঘর্ষের বল 1 পরীক্ষা করা)।
এমএমসিডোল

4
প্রকৃতপক্ষে, একটি স্কোয়ার বাউন্ডিং বক্সটি বৃত্তাকার বাউন্ডিং বক্সের চেয়ে খারাপ পারফরম্যান্স অনুযায়ী হতে পারে (ধরে নিলে আপনি বর্গের মূলকে অপ্টিমাইজ করেছেন)
পোনকডুডল

3

আমি এটি এখানে এবং সেখানে ইঙ্গিতযুক্ত দেখছি, তবে আপনি প্রথমে একটি দ্রুত গণনাও করতে পারেন, যেমন, ওভারল্যাপের জন্য বাউন্ডিং বাক্সগুলির সাথে তুলনা করতে পারেন এবং প্রথম পরীক্ষাটি পাস হলে তারা ব্যাসার্ধ ভিত্তিক ওভারল্যাপ করে।

ব্যাসার্ধ বক্সের জন্য ব্যাসার্ধের বাক্সের জন্য ব্যাসার্ধের সমস্ত ট্রিগের চেয়ে অনেক দ্রুত গতিযুক্ত, এবং বেশিরভাগ সময়, বাউন্ডিং বক্স পরীক্ষা সংঘর্ষের সম্ভাবনা বাতিল করে দেয়। তবে আপনি যদি তখন ট্রিগ দিয়ে পুনরায় পরীক্ষা করেন তবে আপনি যে সঠিক ফলাফলটি সন্ধান করছেন তা পেয়ে যাচ্ছেন।

হ্যাঁ, এটি দুটি পরীক্ষা, তবে এটি সামগ্রিকভাবে দ্রুত হবে।


6
আপনার ট্রিগের দরকার নেই। bool is_overlapping(int x1, int y1, int r1, int x2, int y2, int r2) { return (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)<(r1+r2)*(r1+r2); }
পোনকডুডল


2

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

হিসাবের কিছু লগইন দেখিয়েছিল যে এই ক্ষেত্রে ন্যূনতম অনুবাদ দূরত্বটি এত বড় নয় যে পরের বারের ধাপে একই বলগুলিকে সংঘর্ষ হতে রোধ করতে পারে। আমি কিছু পরীক্ষা-নিরীক্ষা করে দেখেছি যে আপেক্ষিক গতির উপর ভিত্তি করে এমটিডি স্কেল করে আমি এই সমস্যাটি সমাধান করতে পারি:

dot_velocity = ball_1.velocity.dot(ball_2.velocity);
mtd_factor = 1. + 0.5 * Math.abs(dot_velocity * Math.sin(collision_angle));
mtd.multplyScalar(mtd_factor);

আমি যাচাই করেছি যে এই ঠিক করার আগে এবং পরে, মোট গতিময় শক্তি প্রতিটি সংঘর্ষের জন্য সংরক্ষণ করা হয়েছিল। Mtd_factor এর 0.5 মান হ'ল প্রায় সর্বনিম্ন মান হিসাবে সংঘর্ষের পরে বলগুলি সর্বদা আলাদা হয়।

যদিও এই ফিক্সটি সিস্টেমের সঠিক পদার্থবিজ্ঞানে অল্প পরিমাণে ত্রুটির পরিচয় দেয়, ট্রেড অফ হ'ল এখন খুব দ্রুত বলগুলি সময়ের ধাপের আকারটি হ্রাস না করে ব্রাউজারে সিমুলেট করা যায়।


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