Sunday, October 3, 2010

XNA: Lesson6: اكتشاف التصادم بين كائنات اللعبة

الدرس السادس: اكتشاف التصادم بين كائنين
Coding for collision detection between two objects


بسم الله و الصلاة و السلام علي رسول الله ... اللهم لا سهل الا ما جعلته سهلا و انت تجعل الحزن اذا شئت سهلا ...


تعلمنا في الدرس السابق كيف نكتشف تصادم الكائن بحدود شاشة اللعبة بحيث نقرر اذا كان سيرجع مرة اخري الي اللعبة ام مسموح باختفائه ...

في هذا الدرس ان شاء الله سوف نتعلم كيف نكتشف تصادم كائنين في اللعبة ببعضها البعض ... طيب و ما فائدة هذا ؟؟؟

استطيع ان اقول لكم ان هذا يمثل لب اللعبة نفسها يعني بها نعرف مثلا كيف تصطدم طائرة بالجبل مثلا داخل اللعبة او نعرف اذا اصاب الرمح العدو فاماته ام لا ... و نعرف بها مثلا اذا كانت الكرة دخلت المرمي ام لا تخيلوا لعبة كرة بلا اهداف J ...

هناك خوارزميات كثيرة لاكتشاف التصادم منها المعقد و منها البسيط ...

المعقد مثلا انك تطابق كل بكسل في الصورة بالبكسل المقابل لها بالصورة المقابلة و هذا ليس مناسب و يحدث في حدود بعيدة و للحصول علي الدقة العالية فيه يتطلب اجهزة عالية المستوي جدا .....

و منها البسيط الذي سنستخدمه هنا و هو خوارزم او اسلوب الصندوق او "Bounding Boxes" و هو مطابقة اطار الصورة الاولي باطار الصورة الثانية فاذا تداخلوا فهذا يعني تصادم مثلا الصورة التالية:


ماذا نلاحظ ؟؟؟
قسمنا الصور الي مربعان كبيران ليغطوا كل الصورة ... و بالتالي معنا الان طائرتان نريد ان نكتشف التصادم الخاص بهم ... بمنتهي البساطة اذا تلاقت حدود الطائرة الاولي مع حدود الطائرة الثانية فهذا يعني تصادم ...






-          الان دعونا نطبق مثال علي التصادم:
o       اولا سنقوم بتحميل الصورة التالية و التي ستكون صورة الكائن الذي سنحركه من الرابط التالي:
o       http://lh3.ggpht.com/_60yQUD53BPE/TKfftPYXVgI/AAAAAAAAA0k/KZoc6ed01BE/ball.pngافتح تطبيق الدرس الخامس (الأخير).
o       اضف الصورة التي قمت بتحميلها الي الفولدر Content كما تعلمنا مسبقا ...
o       افتح الكلاس clsSprite.
o       و سنضيف دالة اكتشاف التصادم بين كائنين و هي ستكون كالتالي:


        public bool Collide(clsSprite otherSprite)
        {
            Rectangle thisRec = new Rectangle((int)this.position.X, (int)this.position.Y,
                this.texture.Width, this.texture.Height);

            Rectangle otherSpriteRec = new Rectangle((int)otherSprite.position.X, (int)otherSprite.position.Y,
                otherSprite.texture.Width, otherSprite.texture.Height);

            if (otherSpriteRec.Intersects(thisRec))
            {
                return true;
            }

            return false;
        }



الدالة اسمها Collide يعني تصادم  و ترجع بنعم او لا يعني اذا حدث تصادم ترجع ب true و اذا لم يحدث تصادم ترجع ب false ...

الدالة تستقبل parameter من نوع clsSprite و هو الكائن الاخر الذي سنفحص تصادمه مع هذا الكائن ...

كما ذكرنا مسبقا نحن سنستخدم الجوريزم اكتشاف التصادم بين الكائنين باستخدام اسلوب الصندوق المحيط بالصورة و بالتالي يجب ان نحدد الصندوق او المربع حول كل صورة كالتالي:

Rectangle thisRec = new Rectangle((int)this.position.X, (int)this.position.Y,
                this.texture.Width, this.texture.Height);
قمنا بتعريف مربع يحتوي علي ابعاد الصورة الاولي ...

Rectangle otherSpriteRec = new Rectangle((int)otherSprite.position.X, (int)otherSprite.position.Y,
                otherSprite.texture.Width, otherSprite.texture.Height);
قمنا بتعريف مربع يحتوي علي ابعاد الصورة الثانية...

if (otherSpriteRec.Intersects(thisRec))
{
            return true;
}

return false;
قمنا باستخدام دالة Intersects و الموجودة ضمن العنصر Rectangle و هي تقوم باكتشاف اذا كان هناك تداخل بين مربعين و قمنا باعطاء الدالة مربع الصورة الاخري لكي تطابق بينه و بين مربع الصورة الاولي .... فاذا كانت ابعادهم متداخلة ستعطي true و اذا كانت ابعادهم غير متداخلة ستعطي false...

و بهذا انتهت دالة اكتشاف التصادم و هذه الدالة باسلوب تطابق المربعات او ال Bounding Boxes .... و هذا الاسلوب ليس دقيق مائة في المائة لان هناك ابعاد دائرية مثل حالة الكرة هنا لكنها حتي الان تفي بالغرض و سنتعلم طرق اكثر تعقيدا فيما بعد ...




  • دعونا الان ننتقل الي الملف Game1.CS:
    • نعرف كائنين clsSprite كما بالاتي:
clsSprite sprite1;
clsSprite sprite2;


    • نعدل ابعاد الشاشة في ال Constructor Game1 كالاتي:
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            graphics.PreferredBackBufferWidth = 900;
            graphics.PreferredBackBufferHeight = 600;
        }


    • ثم نذهب الي حدث ال LoadContent و نحمل الكائنات:
            sprite1 = new clsSprite(Content.Load<Texture2D>("ball"),
                    Vector2.Zero,
                    graphics.PreferredBackBufferWidth,
                    graphics.PreferredBackBufferHeight);

            sprite1.velocity = new Vector2(2, 2);

            sprite2 = new clsSprite(Content.Load<Texture2D>("ball"),
                new Vector2(300, 300),
                graphics.PreferredBackBufferWidth,
                graphics.PreferredBackBufferHeight);

            sprite2.velocity = new Vector2(3, 3);

و ذلك كما تعلمنا مسبقا طبعا .... قمنا بتعريف كائنين في موضعين مختلفين ... و بسرعات مختلفة ...



ثم نذهب الان الي الحدث Update و نعدله ليصبح كالاتي:
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here
            sprite1.Move();
            sprite2.Move();

            if (sprite1.Collide(sprite2))
            {
                Vector2 tempVelocity = sprite1.velocity;
                sprite1.velocity = sprite2.velocity;
                sprite2.velocity = tempVelocity;
            }

            base.Update(gameTime);
        }


هنا قمنا بتحريك العنصرين ثم اضفنا كود اكتشاف التصادم حيث نفذنا الدالة collide و اعطيناها الكائن الاخر لكي تفحص التصادم فاذا حدث التصادم نعكس السرعات بحيث ياخذ كل كائن سرعة الكائن الاخر و يمشي عكسه .............





  • تطبيق الدرس:
قم بانشاء كائن ثالث في اللعبة و اكتب كود التصادم بحيث لا يصطدم الثلاث كائنات ببعضهم البعض ...
رابط حل التطبيق:
http://www.mediafire.com/?l8hg68gl4dpnzzq

  • ملاحظة:
نلاحظ ان الصورة التي نستخدمها هي صورة كرة و لكن اكتشاف التصادم لا يتم بالدقة الكافية بحيث يتعامل مع الصورة علي انها مربع و بالتالي في بعض الاحيان يكتشف التصادم في اماكن تكون بعيدة عن الكرة و لهذا حل ان شاء الله و هو اكتشاف التصادم بين الكائنات المدورة مثل الكرة مثلا و ان شاء الله في الدرس القادم سنتعلم كيف نطبقه ...............


No comments:

Post a Comment