এক্সএনএ-তে পিক্সেল-নিখুঁত সংঘর্ষ সনাক্তকরণের জন্য কি কোনও ভাল উপায় আছে?


12

এক্সএনএ-তে পিক্সেল-নিখুঁত সংঘর্ষ সনাক্তকরণের জন্য কি কোনও সুপরিচিত উপায় (বা সম্ভবত কোডের পুনরায় ব্যবহারযোগ্য বিট) রয়েছে?

আমি অনুমান করি যে এটি প্রথম-পাসের জন্য বহুভুজ (বাক্স / ত্রিভুজ / চেনাশোনা), সংঘর্ষের জন্য দ্রুত-পরীক্ষা এবং যদি সেই পরীক্ষাটি সংঘর্ষের ইঙ্গিত দেয়, তবে এটি প্রতি পিক্সেলের সংঘর্ষের জন্য অনুসন্ধান করবে would

এটি জটিল হতে পারে, কারণ আমাদের স্কেল, আবর্তন এবং স্বচ্ছতার জন্য অ্যাকাউন্ট করতে হবে।

সতর্কতা: আপনি যদি নীচের উত্তর থেকে লিঙ্কটি থেকে নমুনা কোডটি ব্যবহার করছেন, তবে সচেতন হোন যে ম্যাট্রিক্সের স্কেলিংটি সঠিক কারণে মন্তব্য করা হয়েছে। কাজের স্কেলিং করতে আপনার এটিকে কোনও অসুবিধে করার দরকার নেই।


2
বহুভুজ নাকি স্প্রাইটস?
ডপপেলগ্রিনিয়ার

আমি নিশ্চিত নই. এক্সনা দুজনকে সাপোর্ট করে? আমার সম্পাদনা উভয়ের সংমিশ্রণের উল্লেখ করে, যেহেতু বাউন্ডিং-বাক্স পরীক্ষাগুলি প্রথম প্রথম পাস।
ashes999

1
আপনি 3 ডি / 2 ডি মডেল বা স্প্রাইট ব্যবহার করছেন কিনা তার উপর নির্ভর করে সংঘর্ষ সনাক্তকরণটি পৃথক হবে। একটিতে পিক্সেল রয়েছে। অন্যটির শীর্ষ এবং প্রান্ত রয়েছে।
ডপপেলগ্রিনিয়ার

ঠিক আছে, আমি দেখতে পাচ্ছি আপনি এখন কী পাচ্ছেন। আমি স্প্রাইট ব্যবহার করছি। যদিও আমি বিশ্বাস করি XNA এগুলি একটি টেক্সচার্ড বহুভুজ হিসাবে প্রয়োগ করে।
ashes999

উত্তর:


22

আমি দেখতে পাচ্ছি যে আপনি প্রশ্নটিকে 2 ডি হিসাবে ট্যাগ করেছেন, তাই আমি এগিয়ে গিয়ে আমার কোডটি ফেলে দেব:

class Sprite {

    [...]

    public bool CollidesWith(Sprite other)
    {
        // Default behavior uses per-pixel collision detection
        return CollidesWith(other, true);
    }

    public bool CollidesWith(Sprite other, bool calcPerPixel)
    {
        // Get dimensions of texture
        int widthOther = other.Texture.Width;
        int heightOther = other.Texture.Height;
        int widthMe = Texture.Width;
        int heightMe = Texture.Height;

        if ( calcPerPixel &&                                // if we need per pixel
            (( Math.Min(widthOther, heightOther) > 100) ||  // at least avoid doing it
            ( Math.Min(widthMe, heightMe) > 100)))          // for small sizes (nobody will notice :P)
        {
            return Bounds.Intersects(other.Bounds) // If simple intersection fails, don't even bother with per-pixel
                && PerPixelCollision(this, other);
        }

        return Bounds.Intersects(other.Bounds);
    }

    static bool PerPixelCollision(Sprite a, Sprite b)
    {
        // Get Color data of each Texture
        Color[] bitsA = new Color[a.Texture.Width * a.Texture.Height];
        a.Texture.GetData(bitsA);
        Color[] bitsB = new Color[b.Texture.Width * b.Texture.Height];
        b.Texture.GetData(bitsB);

        // Calculate the intersecting rectangle
        int x1 = Math.Max(a.Bounds.X, b.Bounds.X);
        int x2 = Math.Min(a.Bounds.X + a.Bounds.Width, b.Bounds.X + b.Bounds.Width);

        int y1 = Math.Max(a.Bounds.Y, b.Bounds.Y);
        int y2 = Math.Min(a.Bounds.Y + a.Bounds.Height, b.Bounds.Y + b.Bounds.Height);

         // For each single pixel in the intersecting rectangle
         for (int y = y1; y < y2; ++y)
         {
             for (int x = x1; x < x2; ++x)
             {
                 // Get the color from each texture
                 Color a = bitsA[(x - a.Bounds.X) + (y - a.Bounds.Y)*a.Texture.Width];
                 Color b = bitsB[(x - b.Bounds.X) + (y - b.Bounds.Y)*b.Texture.Width];

                 if (a.A != 0 && b.A != 0) // If both colors are not transparent (the alpha channel is not 0), then there is a collision
                 {
                     return true;
                 }
             }
         }
        // If no collision occurred by now, we're clear.
        return false;
    }

    private Rectangle bounds = Rectangle.Empty;
    public virtual Rectangle Bounds
    {
        get
        {
            return new Rectangle(
                (int)Position.X - Texture.Width,
                (int)Position.Y - Texture.Height,
                Texture.Width,
                Texture.Height);
        }

    }

সম্পাদনা করুন : যদিও এই কোডটি প্রায় স্বচ্ছ ব্যাখ্যাযোগ্য, আমি মন্তব্য না করার জন্য খারাপ অনুভব করেছি, তাই আমি কিছু যুক্ত করেছি;) আমি বিটওয়াইজ অপারেশন থেকেও মুক্তি পেয়েছি কারণ এটি কালার.এর সম্পত্তি আরও জটিল পদ্ধতিতে যা করে তা করছিল since ;)


কোনও মন্তব্য বা ব্যাখ্যা ছাড়াই একটি কোড ডাম্পের পক্ষে ভোট দিন।
অ্যাটাকিংহোব

12
যে কোনও ব্যাখ্যা কেবল কোডটি পুনরুদ্ধার করবে এবং কোডটি মোটামুটি সোজা।

2
আমি জানি আমি আমার প্রশ্নে এটি উল্লেখ করেছি, তবে আমার আবার তা বলা দরকার: এই হ্যান্ডেলটি কী স্কেলিং এবং ঘূর্ণন করে? দুটি স্কেলড, ঘোরানো স্প্রিটগুলি সঠিকভাবে ছেদ করতে পারে? (যদিও আমি দ্রুত বাউন্ডিং-বাক্সে প্রথম পাস যোগ করার ব্যবস্থা করতে পারি)) বা এটি Boundsকি কল দিয়ে আচ্ছাদিত ?
ashes999

1
হ্যাঁ, আমি সে সম্পর্কে ভুলে গেছি! কোডটি রূপান্তরকে বিবেচনায় নেয় না। এই মুহূর্তে আমি সম্পাদনা করতে সময় নেই, কিন্তু আপনি সংঘর্ষজনিতএকত্রিকরণ রূপান্তরিত নমুনা কটাক্ষপাত থাকতে পারে যতক্ষণ না আমি কি: create.msdn.com/en-US/education/catalog/tutorial/...
pek

1
কেবলমাত্র পেডেন্টিক হচ্ছে, তবে আপনার কেবল প্রয়োজন: CollidesWith(Sprite other, bool calcPerPixel = true);:)
জনাথন কনেল

4

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

http://xbox.create.msdn.com/en-US/education/catalog/tutorial/collision_2d_perpixel_transformed

আমি রিমার গ্রুটজানসকে তার 2 ডি শুটারের খেলায় আকর্ষণীয়ভাবে দেখতে পেয়েছি। http://www.riemers.net/eng/Tutorials/XNA/Csharp/series2d.php

(এটি পেতে এটি কিছুটা সময় নেয় ... http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series2D/Coll_Dtetection_Overview.php ... তবে আপনি এটি দেখতে অনুসরণ করতে পারেন সমস্যা সে সমাধান করছে)

তবে আমি আপনাকে সতর্ক করে দিচ্ছি যে রিমার্সের নমুনাটি এক্সএনএ 4.0 নয় এবং এটি চালানোর জন্য আপনাকে কিছুটা কাজ করতে হতে পারে। এটি অবশ্য জটিল বা রহস্যজনক কাজ নয়।


দুর্দান্ত লিঙ্ক, তবে পুরানো লিঙ্কগুলি; আমি এগুলি ইতিমধ্যে আমার সমাধানের জন্য ব্যবহার করেছি।
ashes999

1
অসাধারণ. আমি যখন চিত্র অনুসন্ধান করি তখন তারা আপনার প্রশ্নটি খুঁজে পেতে পারে এবং তাদের আরও সংস্থান থাকবে I
ক্রিস গোমেজ

0

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

এটি একটি সংঘর্ষের ম্যাট্রিক্স ব্যবহার করার মতো তবে আরও উন্নত এবং আপনি এটি রূপান্তর করতে পারেন! আপনার যদি প্রয়োজন হয় তবে একটি সংঘর্ষের মানচিত্রের জেনারেটর সরঞ্জাম তৈরি করার কথা বিবেচনা করুন। আপনি যদি এটি কাজ করে থাকেন তবে দয়া করে কোডটি অন্যদের সাথে ভাগ করুন!

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