2D আয়তক্ষেত্রাকার বস্তুর সংঘর্ষের দিকটি আমি কীভাবে সনাক্ত করব?


11

এই প্রশ্নের পরে , আমার আরও কিছু সাহায্য দরকার।

একটি আয়তক্ষেত্রের কোন দিকটি সংঘর্ষে এসেছিল এবং কীভাবে সেই অনুযায়ী প্রতিক্রিয়া জানাতে পারি?

চারদিক থেকে আয়তক্ষেত্রের সংঘর্ষ হচ্ছে

নীল তীরগুলি সেই পথগুলি যা কিছু বৃত্তাকার বস্তু অনুসরণ করবে যদি বাক্সের সাথে সংঘর্ষের আগে এবং পরে ঘটে।

আমি কীভাবে এটি গণনা করতে পারি?

উত্তর:


8

যেহেতু এটি আপনার অন্যান্য প্রশ্নের উপর নির্ভর করে আমি যখন আয়তক্ষেত্রটি অক্ষ-সারিবদ্ধ হয় তখন এর জন্য একটি সমাধান দেব।

প্রথমত, আপনি নিম্নলিখিত মানগুলির সাথে আপনার বর্তমান অবজেক্টের আয়তক্ষেত্রটি তৈরি করেন:

int boxLeft = box.X;
int boxRight = boxLeft + box.Width;
int boxTop = box.Y;
int boxBottom = boxTop + box.Height;

এরপরে, পুরাতন অবজেক্টের আয়তক্ষেত্রটি তৈরি করতে (যখন এটি সংঘর্ষে ছিল না) তৈরি করতে আপনার অবশ্যই পুরানো অবজেক্টের অবস্থান (যা আপনি প্রতিটি বস্তুর উপর সঞ্চয় করতে পারেন বা কেবল কোনও ফাংশনে যেতে পারেন):

int oldBoxLeft = box.OldX;
int oldBoxRight = oldBoxLeft + box.Width;
int oldBoxTop = box.OldY;
int oldBoxBottom = oldBoxTop + box.Height;

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

আপনি কীভাবে এটি করতে পারেন তা এখানে রয়েছে (এই ফাংশনগুলি ধরে নেয় যে সংঘর্ষ রয়েছে coll সংঘর্ষ না হলে তাদের ডাকা উচিত নয়):

 bool collidedFromLeft(Object otherObj)
{
    return oldBoxRight < otherObj.Left && // was not colliding
           boxRight >= otherObj.Left;
}

রাজকুমারী এবং পুনরাবৃত্তি।

bool collidedFromRight(Object otherObj)
{
    return oldBoxLeft >= otherObj.Right && // was not colliding
           boxLeft < otherObj.Right;
}

bool collidedFromTop(Object otherObj)
{
    return oldBoxBottom < otherObj.Top && // was not colliding
           boxBottom >= otherObj.Top;
}

bool collidedFromBottom(Object otherObj)
{
    return oldBoxTop >= otherObj.Bottom && // was not colliding
           boxTop < otherObj.Bottom;
}

এখন, অন্যান্য প্রশ্নের সংঘর্ষের প্রতিক্রিয়া সহ প্রকৃত ব্যবহারের জন্য:

if (collidedFromTop(otherObj) || collidedFromBottom(otherObj))
    obj.Velocity.Y = -obj.Velocity.Y;
if (collidedFromLeft(otherObj) || collidedFromRight(otherObj))
    obj.Velocity.X = -obj.Velocity.X;

আবার এটি সর্বোত্তম সমাধান নাও হতে পারে তবে আমি সাধারণত সংঘর্ষ সনাক্তকরণের জন্যই যাই।


আবারও ঠিক বলেছেন! ; ডি ধন্যবাদ ... (পরের বার আমাকে আপনার বোর্ডের আরও পোস্টকার্ড প্রেরণ করুন ... ^ ___ ^)
নিমোস্টেইন

আহঃ দুঃখের সাথে আমি জানতাম না যে আমি এটির জন্য কী ব্যবহার করতে পারি .. সম্ভবত পরবর্তী সময়!
জেসি এমন্ড

7

হিসাবে প্রশ্নের আংশিকভাবে অভিন্ন এই প্রশ্নের , আমি আমার উত্তর কিছু অংশে যাতে পুনঃ-ব্যবহার করে আপনার প্রশ্নের উত্তর চেষ্টা করবে।


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

সুতরাং, আমরা একটি অক্ষ সংলগ্ন বাউন্ডিং বক্স (বা একটি ওরিয়েন্টেড সীমাবদ্ধ বাক্স ) এবং একটি চলমান সত্তা বিবেচনা করব

  • সীমানা বাক্সটি 4 টি সমন্বয়ে গঠিত এবং আমরা প্রত্যেককে এই
    রূপটি সংজ্ঞায়িত করব: সাইড 1 = [x1, y1, x2, y2] (দুটি পয়েন্ট [x1, y1] এবং [x2, y2])

  • চলমান সত্তাকে একটি বেগ ভেক্টর (অবস্থান + গতি) হিসাবে সংজ্ঞায়িত করা হয়:
    একটি অবস্থান [posX, posY] এবং একটি গতি [স্পিডএক্স, স্পিডওয়াই]


নিম্নলিখিত পদ্ধতিটি ব্যবহার করে কোনও AABB / OBB এর কোন দিকটি কোনও ভেক্টর দ্বারা আঘাত করা হয়েছে তা আপনি নির্ধারণ করতে পারেন:

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

  • 2 / একবার আপনি ছেদ পয়েন্টগুলি জানতে (যদি সেগুলি বিদ্যমান থাকে) আপনি সেগমেন্টের সীমানার মধ্যে রয়েছে তাদের জন্য অনুসন্ধান করতে পারেন।

  • 3 / শেষ অবধি, তালিকায় এখনও যদি একাধিক পয়েন্ট থাকে (বেগ ভেক্টর একাধিক পক্ষের মধ্য দিয়ে যেতে পারে), আপনি চৌরাস্তা থেকে সত্তার উত্স পর্যন্ত ভেক্টরের চৌম্বকটি ব্যবহার করে সত্তা উত্স থেকে নিকটতম বিন্দুটি সন্ধান করতে পারেন।

তারপরে আপনি একটি সাধারণ ডট পণ্য ব্যবহার করে সংঘর্ষের কোণটি নির্ধারণ করতে পারেন।

  • 4 / হিট সাইড ভেক্টরের সাথে সত্তার কোনও বিন্দু পণ্য (সম্ভবত কোনও বল?) ভেক্টর ব্যবহার করে সংঘর্ষের মধ্যবর্তী কোণটি সন্ধান করুন।

----------

আরো বিস্তারিত:

  • 1 / ছেদগুলি সন্ধান করুন

    • a / তাদের প্যারামেট্রিক ফর্ম (পি (টি) = পো + টিডি) ব্যবহার করে অসীম রেখাগুলি (অক্ষ + বিএক্স = ডি) নির্ধারণ করুন।

      পয়েন্টের উত্স: পো = [পোজএক্স, পজওয়াই]
      দিকনির্দেশক ভেক্টর: ডি = [স্পিডএক্স, স্পিডওয়াই]

      = ডায়ি = স্পিডওয়াই
      বি = -ডেক্স = -স্পিডএক্স
      ডি = (পো.এক্স * ডাই) - (পো.ই * * ডেক্স) = (পজএক্স স্পিডওয়াই) - (পজিএই স্পিডএক্স)

      অক্ষ + বাই = ডি <====> (স্পিডওয়াই এক্স) + (-স্পিডএক্স ওয়াই) = (পজএক্স স্পিডওয়াই) - (পজাই স্পিডএক্স)

      আমি পদ্ধতিটি চিত্রিত করার জন্য সত্তা বিন্দুর মানগুলি ব্যবহার করেছি, তবে সীমানা বাক্সের 4 পাশের অসীম লাইনগুলি নির্ধারণ করার জন্য ঠিক একই পদ্ধতি (পো = [x1, y1] এবং ডি = [x2-x1; y2-y1] পরিবর্তে).

    • খ / পরবর্তী, দুটি অসীম রেখার ছেদ খুঁজতে আমরা নিম্নলিখিত সিস্টেমটি সমাধান করতে পারি:

      A1x + B1x = D1 <== theাল হিসাবে গতি ভেক্টরের সাথে সত্তা পয়েন্টের মধ্য দিয়ে যাওয়া লাইন।
      A2x + B2x = D2 <== AABB দিকগুলির মধ্য দিয়ে যাওয়ার একটি লাইন।

      যা বাধা দেওয়ার জন্য নিম্নলিখিত স্থানাঙ্কগুলি দেয়:

      এক্সপ্রেশন এক্স = (( বি 2 * ডি 2)) ( বি 1 * ডি 2)) / (( 1 * বি 2) - ( 2 * বি 1))
      ইন্টারসেপশন y = (( 1 * ডি 2) - ( 2 * ডি 1)) / (( 1 * বি 2) - ( 2 * বি 1)

      যদি ডিনোমিনেটর ((A1 * B2) - (A2 * B1) সমান হয় তবে উভয় লাইন সমান্তরাল বা ওভারল্যাপিং হয়, অন্যথায় আপনি একটি ছেদ দেখতে পাবেন find

  • 2 / বিভাগের সীমা জন্য পরীক্ষা। এটি যাচাই করার জন্য সহজ সরল, আরও বিশদগুলির প্রয়োজন নেই for

  • 3 / নিকটতম পয়েন্ট জন্য অনুসন্ধান করুন। তালিকায় এখনও যদি একাধিক পয়েন্ট থাকে তবে সত্তা উত্সের বিন্দুর সবচেয়ে কাছের কোনটি আমরা খুঁজে পেতে পারি।

    • একটি / ছেদ বিন্দু থেকে সত্তা উত্স পয়েন্টে যেতে ভেক্টরটি নির্ধারণ করুন

      ভি = পো - ইনট = [পো.এক্স - আন্ত.এক্স; Po.y - Int.y]

    • খ / ভেক্টরের দৈর্ঘ্য গণনা করুন

      || ভী || = বর্গক্ষেত্র (V.x² + V.y²)

    • সি / সবচেয়ে ছোট খুঁজে।
  • 4 / এখন আপনি জানেন যে কোন দিকে আঘাত হানবে, আপনি কোনও বিন্দু পণ্য ব্যবহার করে কোণটি নির্ধারণ করতে পারেন।

    • এ / লেট এস = [x2-x1; y2-y1] আঘাত করা হবে এমন পাশের ভেক্টর হোন এবং ই = [স্পিডএক্স; স্পিডওয়াই] সত্তার বেগ ভেক্টর হোন

      ভেক্টর ডট পণ্য নিয়ম ব্যবহার করে আমরা এটি জানি

      এস · ই = এসএক্স প্রাক্তন + সি আই
      এবং
      এস · ই = || এস || || ই || cos

      সুতরাং আমরা এই সমীকরণটি কিছুটা চালিত করে determine নির্ধারণ করতে পারি ...

      কোস θ = (এস · ই) / (|| এস || || ই ||)

      θ = আকোস ((এস · ই) / (|| এস || || ই ||))

      সঙ্গে

      এস · ই = এসএক্স * প্রাক্তন + সী * এ
      || এস || = sqrt (Sx² + Sy²)
      || ই || = বর্গক্ষেত্র (Ex² + Ey²)


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

আমি কংক্রিটের ওবিবি উদাহরণ দিয়ে যাচাই করিনি (আমি একটি এএবিবি দিয়েছিলাম) তবে এটিও কার্যকর হওয়া উচিত।


6

একটি সহজ উপায় হ'ল সংঘর্ষের সমাধান করা, তারপরে চলন্ত অবজেক্টের সংঘর্ষের বাক্সটি প্রতিটি দিকের এক পিক্সেলের সাহায্যে অনুবাদ করুন এবং দেখুন কোনটি সংঘর্ষের ফলে ফলাফল হয়।

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


2

একটি উপায় হ'ল বিশ্বটিকে আপনার আয়তক্ষেত্রের চারদিকে ঘোরানো। এই ক্ষেত্রে "দুনিয়া" হ'ল আপনার কেবলমাত্র অবজেক্টগুলি: আয়তক্ষেত্র এবং বল। আপনি আয়তক্ষেত্রটি এর কেন্দ্রের চারপাশে ঘোরান যতক্ষণ না এর সীমাগুলি x- / y- অক্ষের সাথে একত্রিত হয়, তারপরে আপনি একই পরিমাণে বলটি ঘোরান।

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

তারপরে আপনি সংঘর্ষের জন্য যেমন পরীক্ষা করতে পারেন ঠিক তেমন কোনও অন্য-আবর্তিত আয়তক্ষেত্রের সাথে আপনারও।


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


1

আমি আমার গণনায় স্থির কোণগুলি ব্যবহার করেছি তবে এটি আপনাকে কিছুটা সহায়তা করবে help

void Bullet::Ricochet(C_Rect *r)
{
    C_Line Line;
    //the next two lines are because I detected 
    // a collision in my main loop so I need to take a step back.

    x = x + ceil(speed * ((double)fcos(itofix(angle)) / 65536));
    y = y + ceil(speed * ((double)fsin(itofix(angle)) / 65536));
    C_Point Prev(x,y);

    //the following checks our position to all the lines will give us
    // an answer which line we will hit due to no lines
    // with angles > 90 lines of a rect always shield the other lines.

    Line = r->Get_Closest_Line(Prev);    
    int langle = 0;
    if(!Line.Is_Horizontal())   //we need to rotate the line to a horizontal position
    {
        langle = Line.Get_Point1().Find_Fixed_Angle(Line.Get_Point2());
        angle = angle - langle;  //to give us the new angle of approach
    }
    //at this point the line is horizontal and the bullet is ready to be fixed.
    angle = 256 - angle;
    angle += langle;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.