المحتوى عن 'شخصيات'.



مزيد من الخيارات

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المُحتوى


التصنيفات

  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • نصائح وإرشادات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • التجارة الإلكترونية
  • مقالات ريادة أعمال عامة

التصنيفات

  • PHP
    • Laravel
    • ووردبريس
  • جافاسكريبت
    • Node.js
    • jQuery
    • AngularJS
    • Cordova
  • HTML5
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • سي شارب #C
    • منصة Xamarin
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • برمجة أندرويد
  • لغة Swift
  • لغة R
  • لغة TypeScript
  • سير العمل
    • Git
  • صناعة الألعاب
    • Unity3D
  • مقالات برمجة عامة

التصنيفات

  • تجربة المستخدم
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
    • كوريل درو
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • مقالات تصميم عامة

التصنيفات

  • خواديم
    • الويب HTTP
    • قواعد البيانات
    • البريد الإلكتروني
    • DNS
    • Samba
  • الحوسبة السّحابية
    • Docker
  • إدارة الإعدادات والنّشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • مقالات DevOps عامة

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات

التصنيفات

  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • مقالات عمل حر عامة

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
  • أندرويد
  • iOS
  • macOS
  • ويندوز

التصنيفات

  • شهادات سيسكو
    • CCNA
  • شهادات مايكروسوفت
  • شهادات Amazon Web Services
  • شهادات ريدهات
    • RHCSA
  • شهادات CompTIA
  • مقالات عامة

أسئلة وأجوبة

  • الأقسام
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة البرمجة
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات
    • أسئلة الشهادات المتخصصة

التصنيفات

  • ريادة الأعمال
  • العمل الحر
  • التسويق والمبيعات
  • البرمجة
  • التصميم
  • DevOps

تمّ العثور على 4 نتائج

  1. إني أوجه مقالي هذا لسعيد وعمر وخديجة وليلى الذين قد تكون أنت واحداً منهم. وكما ترى فإن سعيد وعمر وخديجة وليلى هي شخصيات افتراضية تم اصطناعها بمساعدة البيانات الأولية والتخمينات وهي تمثل شرائح قراء مدونتك، وقد تمثلك أنت شخصية سعيد، بينما تعبر شخصية خديجة عن زميلتك في العمل. وفي الواقع هذه التخطيطات تقدم معيارًا يساعدك على خلق المحتوى، فعندما تضيف أسماء وخلفيات للناس الذين يقرؤون ما تكتب فإنك ستتمكن من تلبية احتياجاتهم أكثر، وينطبق هذا الأمر على التسويق والمبيعات، علماً أن اصطناع الشخصيات للعملاء المستهدفين يمكن أن يساعدك على حل المشاكل التي تواجه العملاء، وعملية اصطناع الشخصيات تستحق الوقت الذي ستمضيه عليها. وسنقدم إليك في هذه المقالة مخططاً ودليلاً للمبتدئين ليساعدك في البدء. القوالب الأساسية لتحديد شخصية العميل المستهدفأحب هذا الوصف لتحديد شخصية العميل المستهدف من فريق krux: لذا كم من هذه "الشخصيات البشرية" عليك أن تصطنع؟ من الموصى به أن تصطنع ما بين 3 و5 شخصيات وهمية لتعبر عن عملائك المستهدفين. وهذا العدد كبير بما فيه الكفاية ليُحدّد أغلب عملائك ولكنه يبقى قليلاً ليعبر عن كل الحالات الخاصة. ويقدم موقع Hubspot الكثير من الأمثلة من الشركات التي قامت باصطناع شخصيات لتحديد شخصية العميل المستهدف، ويوجد عدد كبير من القوالب التي بإمكانك استخدامها لنشاطك التّجاري الخاص. العديد من هذه القوالب تتضمن نفس المعلومات الأساسية، فأنت تريد أن تعرف من يكون العميل وماهي قِيمُه وماهي الطريقة الأفضل في مخاطبته. وهذه نظرة عامة على ما يجب أن تحتويه قوالب اصطناع الشخصيات الافتراضية للعملاء: اسم الشخصية العمل المعلومات الأساسية عن الشركة التي يعملون بها (حجم الشركة ونوعها...)تفاصيل عن دورهم الوظيفيالمعلومات الديموغرافية: العمرالجنسالدخلمكان السكن ( المدن- الضواحي- الريف)المستوى التعليميالوضع العائليالأهداف والتحديات الأهداف الرئيسيةالأهداف الثانويةكيف يمكن أن تساعد العميل على تحقيق أهدافهالتحديات الرئيسيةالتحديات الثانويةكيف يمكنك أن تساهم في حل المشاكلالقِيَم والمخاوف القِيَم الرئيسيةالاعتراضات المعتادة أثناء عملية البيعالرسالة التسويقية Elevator pitch أو حديث المصعد لا تقلق إن لم تكن كل هذه الأمور واضحة كما يجب بالنسبة لك إذ أننا سنأتيك بالأمثلة بعد قليل. معلومات إضافية محددة يمكن أن تضيفها لشخصية عميلك الافتراضيةبالإضافة إلى المعلومات الأساسية فإنك ستجد أن طبيعة عملك قد تتطلب معلومات خاصة، فالشخصيات الافتراضية للعملاء المستهدفين تختلف من عمل لآخر ومن مجال لآخر. فشركة لأخبار الإنترنت ستتطلب معلومات عن عملائها تختلف عن شركة لتزويد المعدات الطبية، والشخصيات الافتراضية التي يتم اصطناعها لشركة تتخصّص في بيع المداخن ستختلف عن تلك المصطنعة من أجل مدونة. وبأخذ هذا في عين الاعتبار فإنه هناك أجزاء أخرى متنوعة من المعلومات عليك إضافتها عندما تصطنع شخصيتك عميلك المستهدف الافتراضية. الهواياتمقتطفات حقيقية من مقابلات مع العملاءالإلمام بالحاسوبمن أين يحصل العملاء على الأخبارالمدونات التي يقرؤونهاكيف تحدد شخصية عميلك المستهدفمن أين تحصل على كل المعلومات التي تسمح لك باصطناع شخصية عميلك المستهدف؟ يوجد الكثير من مصادر المعلومات عن عملائك انطلاقًا من بيانات موقعك واستخدام خدمات متابعة الزيارات وسلوك المستخدم إلى المحادثات الحقيقية على أرض الواقع مع العملاء. وإليك ثلاثة أماكن يمكنك أن تستقي منها معلوماتك: تصفح بيانات موقعكمن خلال تصفح خدمات تحليل بيانات الموقع يمكنك أن تعرف من أين يأتي أغلب زوارك وماهي الكلمات المفتاحية التي يستخدمونها ليجدوا الموقع وكم من الوقت يمضون في الموقع عندما يبدؤون تصفحه. وهذه البيانات هامة جدًّا لتحديد شخصية العميل المستهدف إذ أنها يمكن أن تخبر عن الرغبات التي دفعت بعملائك لتصفح موقعك وعن الأدوات التي يستخدمونها للوصول إليه. اجعل فريقك يشارك في اصطناع شخصيات عملائك الافتراضيين اجمع فريقك بكل أقسامه ولا نقصد قسم التسويق فقط بل قسم خدمة الزبائن وأقسام التنمية والتطوير وغيرها، ويجب أن تدعو كل من يتعامل مع العملاء أو على صلة بهم ليشارك بوجهة نظره حول ما يمكن أن يجذب العملاء. البحث في مواقع التواصل الاجتماعييمكنك أيضًا أن تجري بعض البحث في مواقع التّواصل الاجتماعي استخدم موقع social media listening لتعرف ماهي الأسئلة التي يسألها عملاؤك غالبًا أو ماهي المشاكل التي يطرحونها والتي يمكن أن يقدم متجرك حلولاً لها على فيس بوك وتويتر ولينكدإن، وحتى يمكنك أن تجرب Pinterest for retail-oriented insights. وجه الأسئلة لعملائكمن قد يعرف عمليك أكثر مما يعرف هو نفسه؟ غالباً ما تشكل الإحصاءات والمقابلات عناصر حاسمة في اصطناع شخصيات افتراضية فعالة للعملاء المستهدفين. وتلعب المقابلات بشكل خاص دورًا كبيرًا في هذا الإطار لأنك تستطيع أن تحلل إجاباتهم وتكتشف من خلالها أهدافهم وقيمهم والنقاط التي تزعجهم الأمر الذي سيؤدي إلى الحصول على أفضل النتائج معهم. ولجعل تحديد شخصية العملاء المستهدفين أداة نافعة من الأفضل أن ترتكز على المقابلات التي تم جمعها من الباعة ومن تفاعل قسم خدمة الزبائن معهم ومن العملاء أنفسهم. دليلك خطوة بخطوة لملء قوالب تحديد شخصية العميل المستهدفأصبحت الآن تعرف من أين يجب أن تبدأ مع شخصية العميل المستهدف، والخطوة التالية هي إنشاء ملف التعريف الشخصي بشكل فعلي. وهنا خطوات ملء القالب أعلاه في "مخزن مؤقت" للمساعدة في إيجاد العملاء الأساسيين والتواصل معهم، دعنا نلقي نظرة على كل حقل ونتحدث كيف نملأه: - إعطاء اسم للشخصية الافتراضية: يمكنك أن تختار أي اسم، لكن اجعله اسمًا حقيقيًا لتشعر أن الشخصية الافتراضية شخص حقيقي. - تحديد عمل ووظيفة وشركة الشخصية الافتراضية: إن أعظم مصدر لتحديد وظائف شخصياتك الافتراضية هو على الأرجح استطلاعات العملاء، عند إنشاء استطلاع يمكنك إنشاء حقل عن عنوان الوظيفة وحجم الشركة وطبيعة العمل. على سبيل المثال، أظهرت دراسة حديثة لـ Buffer أن نسبة كبيرة من أصحاب الأعمال الصغيرة هم مالكون وموظّفون في نفس الوقت، أو فرق مكونة من شخص واحد، وهؤلاء يمكن أن يتلاءموا معًا في شخصية افتراضية واحدة. - اكتشاف المعلومات الديموغرافية: للحصول على المعلومات الديموغرافية يمكنك جمع بعض المعلومات الواضحة والدقيقة من Google Analytics، بالإضافة إلى أفضل "تخميناتك" ونتائج الاستطلاعات. ويمكنك التنقل داخل إحصائيات Google Analytics من مشاهدة أين يعيش زوارك فضلاً عن أعمارهم وجنسهم و(وانتماءاتهم) والتقنيات التي يستخدمونها. انتقل إلى قسم الجمهور في Google Analytics لمعرفة كل هذا وأكثر: هذه عينة من اهتمامات زوار موقعك التي يمكنك مشاهدتها في Google Analytics (إذا لم تستطيع مشاهدة معلومات ديموغرافية معينة ربما تحتاج إلى تفعيل الميزة أو الاتصال بمدير التحليلات) بالنسبة للعناصر التي لا يمكنك إيجادها في Google Analytics، يمكنك إكمالها من نتائج الاستطلاعات. وتقدم لك العديد من الأدوات مثل Survey monky اقتراحات فيما يتعلق بكتابة أسئلة ديموغرافية محددة لضمان الحصول على ردود دقيقة ومنعاً لحصول أي التباس. من خلال هذه النقطة ربما تتساءل: "هل هذه المعلومات ضرورية حقاً؟" ربما تبدو كمعلومات تافهة لكن تفاصيل مثل هذه تخدم أغراضاً هامة (وهذا ما كتبه جيمس هميتون لـ Tronving group) التعبير البصري والغوص في عمق الشخصية الافتراضية يمكن أن يكون المحفزّ الذي يحول "الخطوط الخام" إلى صورة حقيقية. الأهداف والتحديات والقيم والمخاوفمقابلات الزبائن على أرض الواقع ستكون مساعدة في تحديد الهدف هنا. خلال المقابلات اسأل أسئلة مشابهة للتالي هذه القائمة تعتمد على مبدأ التسويق التفاعلي، إذ أن هكذا أسئلة تجعلك تفهم أهداف عميلك والتحديات التي تواجهه. ماهو المهم بالنسبة لهم ومالذي يقودهم نحو التغيير؟مالذي يعيق التغيير ومالذي يقود التغيير؟كيف يسيرون باتجاه التغيير؟مالذي يحتاجون معرفته لتحقيق التغيير المطلوب؟إلى من يلجؤون عند الحاجة إلى معلومة أو نصيحة؟ماهي الفائدة التي يجنونها عند اتخاذ القرار؟من هم أولئك الذين يتوجب عليهم دفع ثمن التغيير ليحصلوا عليه؟مالذي قد يجعل الحاجة للتغيير تفقد مكانتها كأولوية؟عندما تصل إلى معرفة هذه الأهداف والتحديات يمكنك أيضاً أن تحدد الطرق التي يمكنك من خلالها مساعدة العملاء لمعرفة هذه الأهداف والقضاء على التحديات. وحدسك هنا قد يكون مساعدًا حاول أن تضع نفسك في مكان العميل وحاول أن تجد حلولاً لمشاكله بتعاطف، خذ بعين الاعتبار الاعتراضات المألوفة التي تحدث أثناء عملية البيع، مالذي قد يمنعك من إتمام الصفقة؟ ثم قم باستخدام التحليل الذهني الأمر الذي قد يكون مساعدًا أيضًا. الرسالة التسويقية elevator pitch أو حديث المصعدهذا الجزء يعتمد عليك تمامًا. استخدم معلوماتك وخبرتك لتلبي احتياجات العميل، في هذه المرحلة تشير "الرسالة" إلى كيف يمكنك أن توصف منتجك هذا لهذا النوع من الناس تحديدًا. هل لديك وسيلة تقدم خدمات التواصل الاجتماعي ؟ هل تقدم أداة لإدارة مشاريع العملاء؟ بعدها يمكنك أن تناقش رسالتك التسويقية بالتفاصيل وأن تقوم بصياغة رسالة تمكنك من بيع منتجك للزبون. أمثلة على تحديد شخصية العميل المستهدفكما ذكرنا سابقًا فإن تحديد شخصية العميل المستهدف يختلف من شركة لأخرى وكل مكان له خصوصيته. وبالطبع هناك نقاط عامة مشتركة تطبق عليها جميعاً. ويحدث الاختلاف بالتفاصيل فقط، وبالطبع يوجد الكثير من النماذج الجاهزة على الإنترنت حيث قامت بعض الشركات بمشاركة شخصيات عملائهم الافتراضية. وإليك بعضها في هذين الرابطين: Hubspot و Buyer Persona. الخلاصة يساعدك اصطناع شخصيات افتراضية لعملائك المستهدفين في تحديد عملائك وفي حل مشاكلهم بطريقة أفضل. وبالطبع عندما تحل مشاكلهم سيكون الجميع رابحاً عندئذ. اجعل كل فريقك يشارك في اصطناع شخصيات عملائك الافتراضية وتأكّد من أن الجميع يعبرون عن وجهات نظرهم المختلفة ويضيفون معلومات إضافية إلى القوالب الموجودة. وعندما تحصل على الشكل النهائي لشخصية عميلك الافتراضية تفاعل معها باستخدام رسائل محددة من المحتوى الذي تملكه وتعاطف مع عملائك عندما يتعاملون معك. وسينتج عن كل هذا تجربة أفضل للعميل وعدد أكبر من مستخدمي الخدمات التي يقدمها عملك. ماهي تجربتك مع تحديد شخصية العميل المستهدف؟ وماهي العناصر الأكثر فائدة في قوالب الشخصيات التي قمت باصطناعها؟ إننا متحمسون لمعرفة تجربتك في هذا المجال ومالذي وجدته نافعاً بالإضافة لمعرفة مالذي تنوي تجربته عند تحديد شخصية عميلك الافتراضية القادمة. ترجمة -وبتصرّف- للمقال Marketing Personas: The Complete Beginner’s Guide لصاحبه Kevan Lee. حقوق الصورة البارزة: Designed by Freepik.
  2. منذ 15 عاما، تخرجت من الكلية مع حلم أن أصبح مدرسة في التاريخ في المدرسة الثانوية شبيهة بأولئك الذين تعودت مشاهدتهم في الأفلام. لكنني وللأسف اصطدمت بالواقع حيث وجدت نفسي وجها لوجه مع 186 طالبا متحمسا مصحوبين بأولياء أمورهم المثيرين جدا للاهتمام. بعد أربع سنوات، قررت أن أصبح منسقة أحداث خاصة في ملجأ محلي للمتشردين إلى جانب مدير حريص يراقبك مراقبة دقيقة. ثم عملت في سمفونية مع مديرة كانت على العكس تماما: غائبة تماما. فانتهى بي الأمر أقوم بعملي مع حصة جيدة من راتبها (دون راتب خاص). وفي ذلك الوقت كنت قد بدأت بتكوين أسرتي الصغيرة، وقررت أن أنتقل للكتابة لحسابي الخاص لأهتم بصغاري وأضمن مدخولا ماديا (وهذا ما أبقاني على تحد دائم وعاقل في تسيير العمل). كنت دوما أفكر: " آه، إنه حقا منعش! فقط أنا والكمبيوتر وشغفي بالكتابة" نعم، لقد كنت حقا بهذه المثالية ولكن غير مدركة للأمر. الآن بعد خمس سنوات، عملت مع العديد من الشركات وعلمت أن كل شخص لديه نمط مختلف من العمل، وفلسفات إدارة فريدة وتوقعات فردية لكل مشروع. كعاملين مستقلين ولحسابنا الخاص، نحن لسنا موهوبين فقط في مهنتنا بل خضعنا لتدريبات لنتحول إلى خبراء في مجالنا فنحن نتحول كالحرباء بين الشركات والوسطاء المعلنين ونحاول يائسين استباق رغبات وحاجات عملائنا. لا زلنا صامدين ونرتد للوراء بسرعة من الخسائر التي تلحقنا جراء وقف مشروع فجأة للعمل على التالي بسرعة. وهذا يكون صعبا خصوصا إن كنت تتعامل مع عدة عملاء كل يوم. كيف من المفترض للعاملين المستقلين حول العالم أن يعملوا بسلاسة مع مجموعة متنوعة من العملاء الذين لديهم مجموعات مختلفة من التوقعات والأدوات المطلوبة لإنجاز العمل؟ هنا أربع طرق لإدارة تنوع شخصيات العملاء وتوقعات طلباتهم التي من شأنها أن تنفع في التعامل معهم. 1. تعلم أن تكون مرناتعتبر كل شركة لغزا مختلفا وأنت القطعة المفقودة لاستكمال الصورة. ومع ذلك، يمكن للقطعة ألا تصلح في كل لغز، لهذا تحتاج للتكيف مع متطلبات الوظيفة (بعد كل شيء، هم ليسوا مجبرين على تغيير عادات عملهم.... بل المجبر هو أنت). على سبيل المثال، أكتب عادة المحتوى وأستخدم جوجل لتحميل المستندات ولمراسلة عملائي. ومع ذلك، كان هنالك عميل يود الدردشة لمدة نصف ساعة كل ليلة لتبادل الأفكار حول كيفية إعادة تنظيم موقعه الإلكتروني. فعلنا ذلك لأربعة أسابيع! هو يتحدث وأنا أستمع. ربما كتبت حوالي 400 كلمة، لكنني وصفت له العلاج.... أعنى به التحرير. فكرة موجزة: عامل كل عميل على أنه عميلك الوحيد فبعض العملاء يفضلون التواصل الدائم وبعضهم يفضل الرسائل الأسبوعية. فلتقم بأفضل ما يمكنك من أجلهم. قم بتصنيف العملاء وقم بتدوين ملاحظات حول توقعاتهم، عادات العمل لديهم، والفروق الدقيقة. إن العمل الحر رقصة معقدة ولكل شريك في الرقصة إيقاعه الخاص به. 2. محرك البحث الخاص بك أفضل صديق لكيميل العملاء إلى إعطاءك الوظيفة لكنهم يتوقعون منك أن تمتثل لجميع بنود الاتفاق الخاص به. كان لدي عميل قال لي " فلتفتح حسابا على جوجل ولتنشر عملك على جوجل+ وسأقوم بالدفع لك على باي بال." لم تكن هنالك وسيلة لأقول "لا" أو أن أسأل: " كيف أفعل ذلك؟" ها هو ذا يوتيوب، محرك البحث الخاص بك، أو الأيقونة الصغيرة المسماة " المساعدة" موجودة. فالتكنولوجيا تتحرك كسرعة الضوء والعديد من الشركات تسير جنبا إلى جنب معها. لحسن الحظ، يمكنك أن تجد كل المعلومات والتعليمات الخاصة بالمواد التي تحتاجها على الإنترنت. بحيث يمكنك تدريب نفسك بنفسك دون أن تكون عبئا على العميل الخاص بك، مما يجعلك من أكثر المرغوب فيهم للمشاريع المستقبلية. والمكسب الكبير الآخر هم أصدقاءك، عائلتك، والعاملين المستقلين الآخرين. فقبل بضع سنوات مضت وعندما كانت " سحابة الإنترنت" الكلمة الطنانة طوال اليوم، كان مطلوبا مني أن أكتب عدة قطع حيال ذلك ولحسن الحظ، كان أخ زوجي مهووسا كبيرا بذلك فساعدني في ذلك. 3. اعلم متى يجب عليك أن تتخلى عن الأمور ومتى يجب عليك أن تهرب منهايوجد أحيانا عملاء لا يعجبهم العجب ولا يرضيهم أي شيء. لا شيء مما تقوم به يكون صحيحا في نظرهم، وهذه إهانة من قبلهم، لدرجة أنك صرت تشعر بالاستياء من سماع صوت تنبيه رسائلهم الإلكترونية خوفا. إذا قمت بكل ما في وسعك لمعرفة رؤيتهم وتطلعاتهم وعادات العمل الخاصة بهم لكنك لا زلت بائسا فلتقطع علاقة العمل معهم. يُمكن تجنّب مثل هذه المشاكل عبر التّفاهم وكتابة عقد من البداية. لا تتصرف بتهور، تقول Maria Malidaki بخصوص هذا الأمر: فرصة واحدة وأخيرة: أخيرا، فلتقاسمهم إحباطك، واسمح لهم بشرح وجهة نظرهم، ومن ثم امنحهم فرصة للإقرار بأخطائهم وتحسين الوضع. وإن كان كل هذا غير مفيد، فلتستكمل المشاريع غير المنجزة والتي تم دفع ثمنها مسبقا أو تسليم المعلومات البحثية. فلتبذل قصارى جهدك لإنهائه بشروط جيدة. إن كنت لا ترغب في الحصول على سمعة سيئة في عالم الشبكات الاجتماعية التي قد تضر بقدرتك في الحصول على عملاء جدد في المستقبل. 4. فلتعلم ما أنت مقدم عليه أولايمكنك أن تعرف الكثير عن شخص ما من مكالمة عشر دقائق. هل اتصل بك في الوقت المتفق عليه؟ هل بدا مُرتبكّا؟هل ركّز حول الأسباب التي دفعت بالكّتاب الثلاثة السّابقين إلى عدم توفير مُحتوى مُناسب؟ هل تحدث طوال الوقت وهل سألك عن خبرتك وأسلوب كتابتك؟ بالتأكيد هنالك علامات تحذير، لذا فعليك البحث عنها. يمكنك أيضا التحقق من موقع الشركة على الإنترنت، أو حسابه الشخصي على لينكدإن أو مواقع التواصل الاجتماعي لتعرف أكثر حول العميل. وكلما علمت أكثر كلّما كنت أكثر جاهزية لقبول أو رفض مشروع. وأخيرا، تذكّر بأنّه لا يجب عليك أن تقبل كل وظيفة تُرسل إليك أو أن تتعامل مع عميل صعب المزاج. مع العمل المستقل يمكنك العثور على وظيفة من خلال الوسائل المتوفرة كـمنصّة مُستقل، وانتقائها واختيار المهام المناسبة لك. فأنت عندما تعمل بسعادة تكتب بسعادة. ترجمة -وبتصرف- للمقال: Going with the flow; how to work with a plethora of client personalities لصاحبته: Christina Morales. حقوق الصورة البارزة: Designed by Freepik.
  3. قمنا في الدرس السابق من هذه السلسلة بتجهير مشهد اللعبة و بناء الأرضية والخلفية إضافة إلى إعداد الكاميرا. الآن ننتقل إلى المكونات الرئيسية للعبة وهي الوحدات البنائية كالصخور والحجارة وأيضا الخصوم. ملاحظة: يمكن تحميل الملفات المصدرية لكامل هذه السلسلة عبر حساب أكاديمية حسوب على Github، يمكن أيضا تحميل ملف APK لتجريب اللعبة على أجهزة Android. إنشاء الوحدات البنائية للعبةالنوع الثاني من الكائنات التي سنقوم بإنشائها هي الوحدات البنائية التي تتكون منها المراحل. هذه الوحدات عبارة عن أشكال هندسية منها مربعات ومثلثات ومستطيلات ودوائر. هذه الأشكال أيضا تتميز بأنها مصنوعة من مواد مختلفة، فيمكن أن تكون من المعدن أو الصخر أو الخشب أو الزجاج أو المواد المتفجرة، وهذه الأنواع كلها متوفرة بكل الأشكال في مجموعة الصور. هذه المواد تتفاوت في الوزن والصلابة، إضافة لأن المواد المتفجرة حين تتحطم تحدث انفجارا يؤثر في الوحدات المجاورة و الخصوم. لنبدأ أولا بحصر الأشكال التي سنستخدمها، ومن ثم نرى ما الذي يتوفر لدينا من صور لكل من هذه الأشكال، وبالتالي نتعرف على طريقة صناعة القوالب الخاصة بكل شكل. قوالب الأشكال هذه ستشكل العنصر الرئيسي الذي سنبني منه المراحل المختلفة. إذا استعرضت أحد مجلدات الوحدات البنائية ستجد مجموعة كبيرة من الأشكال المختلفة، مثلا الصورة في الأسفل توضح لنا محتويات المجلد Metal elements والذي يحتوي على صور الوحدات البنائية المعدنية: لاحظ أن هناك مجموعة أشكال رئيسية، وكل واحد منها يأتي مرة فارغا من المنتصف ومرة ممتلئا. إضافة إلى ذلك فإن هناك عدة مراحل لتشقق كل وحدة قبل تحطمها نهائيا. اختصارا للوقت سأختار مجموعة صغيرة من هذه الأشكال وهي الموجودة في الصورة التالية: سنتعرف الآن على الخطوات اللازمة لتحويل كل صورة من هذه الصور إلى وحدة بنائية ذات خصائص فيزيائية، إضافة لجعلها قابلة للتحطم عبر تلقيها للضربات أو تصادمها مع غيرها أو سقوطها على الأرض أو تأثرها بالانفجارات. سأبدأ مع المثلثات لأنها حالة خاصة تحتاج لعناية عند بناء القالب الخاص بها، بينما ستكون الأشكال التالية أسهل. لبناء قالب المثلث متساوي الضلعين والذي تراه أيمن الصورة، علينا أولا أن نضيف كائنا فارغا ونسميه Triangle ومن ثم نضيف إليه المكوّن Sprite Renderer ومكوّن التصادم المسمى Polygon Collider 2D والذي سيظهر مبدئيا على شكل خماسي كما توضح الصورة في الأسفل. بعد إضافة مكوّن التصادم يمكننا سحب صورة المثلث إلى داخل الخانة Sprite في المكوّن Sprite Renderer. أنوه هنا إلى أنه من الضروري إضافة مكوّن التصادم قبل تحديد الصورة، وذلك لأن Unity سيحاول تغيير شكل مكوّن التصادم ليطابق شكل الصورة وهو ما لا يتم بدقة. سنقوم الآن بتغيير شكل مكوّن التصادم يدويا وذلك عبر الضغط على الزر Edit Collider. عند تغيير شكل مكوّن التصادم فإنه يمكننا اختيار أي نقطة من النقاط الخمسة وتحريكها، كما يمكننا اختيار نقطة وحذفها بضغط المفتاح Delete. سنحتاج لحذف نقطتين من الخمسة ومن ثم مطابقة النقاط الثلاث المتبقية على زوايا المثلث ليصبح كما ترى في الصورة، وبطبيعة الحال كلما قربت الصورة أثناء مطابقة الزوايا حصلت على نتيجة أدق وأفضل. بعد أن انتهينا من تجهيز شكل مكوّن التصادم يمكننا تثبيته بالضغط مجددا على Edit Collider ليتم حفظ الشكل الجديد. أصبح لدينا الآن مثلث يمكن أن تصطدم به الأجسام الأخرى، إلا أنه نفسه ثابت ولا يتأثر بأي عوامل فيزيائية. لنجعله نشطا فيزيائيا علينا أن نضيف مكوّن الجسم الصلب المسمى Rigid Body 2D، وهو المكوّن المسؤول عن وضع الكائن تحت تحكم المحاكي الفيزيائي الخاص بمحرك Unity، مما يجعله يتأثر بالجاذبية وقوى الدفع وغيرها. هذا المكوّن يحتوي على مجموعة خصائص أذكر هنا أهمها بالنسبة لنا: الكتلة Mass: كلما زادت يصبح تحريك الجسم أصعب لأن إزاحته ستحتاج لقوة أكبر، لكن هذا لا يؤثر على سرعة سقوطه.مقاومة الهواء لحركة الجسم Linear Drag: كلما زادت سيصبح توقف الجسم عن الحركة بعد زوال القوى الخارجية عنه أسرع.مقاومة الهواء للدوران Angular Drag: كلما زادت سيصبح توقف الجسم عن الدوران بعد زوال القوى الخارجية عنه أسرع.معامل الجاذبية Gravity Scale: الجاذبية الافتراضية هي 9.8 كما هو الحال مع الجاذبية الأرضية، وسيتم ضرب هذه القيمة بالمعامل لحساب الجاذبية الخاصة بهذا الكائن تحديدا.سنقوم بتعديل هذه القيم من أجل تمييز أنواع الوحدات البنائية عن بعضها؛ فمثلا الوحدات المعدنية يجب أن تكون أكبر كتلة من مثيلاتها الخشبية وهكذا. بقي الآن أن نجعل هذه الوحدات تتأثر بالصدمات وتتحطم بعد تلقيها عددا معينا منها؛ وهذه الآلية تتم عبر عدة بريمجات سنتعرف عليها. البداية ستكون مع البريمج الذي يحدد مدى قوة تحمل الوحدة البنائية وسنسميه Breakable. مهمة هذا البريمج هي تلقي الصدمات وإنقاص صحة الكائن بناء عليها؛ ومن ثم تدميره حين تصل صحته إلى صفر. السرد التالي يوضح البريمج المذكور. using UnityEngine; using System.Collections; public class Breakable : MonoBehaviour { //مقدار الصحة الأولية للكائن public float initialHealth = 100; //متغير داخلي لمتابعة تغير قيمة صحة الكائن private float health; //تستدعى مرة واحدة عند بداية التشغيل void Start () { health = initialHealth; } //تستدعى مرة عند تصيير كل إطار void Update ( } //تقوم باستقبال الضربات وإنقاص الصحة بناء عليها public void TakeDamage(float amount){ //الصحة منتهية فلا يمكن تلقي المزيد من الضربات if (health <= 0.0f) { return; } if(health <= amount){ //في هذه الحالة تم تدمير الكائن health = 0.0f; SendMessageUpwards("BreakableDestroyed"); Destroy(gameObject); return; } //قم بتقليل قيمة الصحة بمقدار قوة الضربة health -= amount; //أرسل رسالة تخبر بتغير الصحة SendMessage("DamageTaken", health); } } كل ما يفعله هذا البريمج البسيط هو تخزين قيمة الصحة الأولية في متغير خاص داخلي وذلك ليمنع البريمجات الأخرى من تغييرها (تذكر فصل الاهتمامات). يمكن إنقاص الصحة عن طريق إرسال رسالة لهذا البريمج اسمها TakeDamage والتي تأتي مرفقة بمقدار قوة الضربة التي تلقاها الكائن. تقوم الدّالة باستقبال هذه الرسالة وإنقاص قوة الضربة من صحة الكائن، فإذا وصلت صفرا أو أقل من ذلك تقوم بتدميره. ترسل هذه الدّالة رسالتين هما DamageTaken حين تلقي الضربة وترفق معها قيمة الصحة الجديدة بعد إنقاصها. الرسالة الأخرى هي BreakableDestroyed والتي يتم إرسالها عند وصول الصحة إلى صفر أي عند تدمير الكائن. بالعودة إلى مجموعة الصور، لنتذكر ما قلناه عن الصور المشققة والتي تمثل مراحل تحطم الوحدة البنائية. مثلا بالنسبة للمثلث الذي نستخدمه حاليا لدينا الصورة الأصلية (السليمة) إضافة لصورتين تمثلان المرحلة الأولى والثانية للتشقق كما هو موضح في الصورة التالية: ما سنقوم به الآن هو كتابة بريمج آخر يقوم بالربط بين مقدار صحة الكائن والصورة المعروضة. بما أن لدينا ثلاث صور فإن كل واحدة منها ستمثل ثلث الصحة. فإذا كانت الصحة الكاملة 60 مثلا، فإن الصورة الأولى ستبقى ظاهرة طالما أن الصحة بين 60 و40، فإذا قلّت عن 40 ستظهر الصورة الثانية، وإذا قلّت عن 20 ستظهر الثالثة. وبهذه الطريقة نعطي اللاعب فكرة عن قرب تحطم هذه الوحدة. البريمج المسؤول عن هذا الأمر هو BreakableDislay والموضح في السرد التالي: using UnityEngine; using System.Collections; public class BreakableDislay : MonoBehaviour { //مصفوفة لتخزين صور جميع مراحل التدمير //مرتبة من الحالة الأسوأ للحالة الأفضل public Sprite[] destructionStages; //مرجع لبريمج الوحدة البنائية private Breakable brk; //مرجع لمكوّن تصيير الصورة private SpriteRenderer sr; //متغير لتخزين صحة الكائن الأصلية في البداية private float fullHealth; //يتم استدعاؤها مرة واحدة عند بداية التشغيل void Start () { brk = GetComponent<Breakable>(); fullHealth = brk.initialHealth; sr = GetComponent<SpriteRenderer>(); UpdateDisplay (fullHealth); } //يتم استدعاؤها مرة واحدة عند تصيير كل إطار void Update () { } //تقوم باستقبال رسالة تلقي الضربة وتحديث الصورة بناء على قيمة الصحة الجديدة void DamageTaken(float newHealth){ UpdateDisplay(newHealth); } //تقوم بتغيير الصورة المعروضة بناء على قيمة الصحة المزودة void UpdateDisplay(float health){ //قم بتغيير مرحلة التدمير بناء على //قيمة الصحة الجديدة float healthRatio = health / fullHealth; int maxIndex = destructionStages.Length - 1; int matchingIndex = (int)(healthRatio * maxIndex); sr.sprite = destructionStages[matchingIndex]; } } الدّالة الأهم في هذا البريمج هي ()UpdateDisplay، والتي تقوم باختيار صورة مرحلة التشقق الملائمة لمقدار الصحة المتبقية. لنفترض أن لدينا 3 مراحل مختلفة كما هو الحال مع المثلث الذي نعمل عليه. عندما تتغير صحة الكائن نتيجة لتلقيه ضربة معينة، سيقوم بإرسال الرسالة DamageTaken مرفقا معها قيمة الصحة الجديدة. عند استقبال هذه الرسالة من قبل البريمج BreakableDisplay يقوم باستدعاء الدّالة ()UpdateDisplay مباشرة ويزودها بقيمة الصحة الجديدة، عندها تقوم الدّالة بقسمة الصحة الجديدة على الصحة الكاملة التي سبق تخزينها في fullHealth. بقسمة الرقمين نحصل على نسبة الصحة الجديدة من الصحة الكاملة، ومن ثم نقوم بتحويل هذه النسبة إلى عدد صحيح يمثل القيمة الأقرب لها إذا ما قسمناه على عدد العناصر الكلي في مصفوفة صور مراحل التشقق. مثلا إذا كانت الصحة الكاملة هي 100 والجديدة هي 25 وعدد المراحل 3. فإن 0.25 * 2 = 0.5 وبتحويله إلى عدد صحيح (دون جبر الكسر) سيصبح الناتج صفرا أي صورة آخر مرحلة للتشقق قبل التدمير. البريمجان اللذان أضفناهما حتى الآن يعملان على حساب صحة الكائن وعرض صورة درجة التشقق بناء عليها. وكما رأينا فحين تصل صحة الكائن إلى صفر سيتم تدميره وحذفه من المشهد. حذف الكائن من المشهد سيؤدي إلى اختفائه عن الشاشة بشكل فجائي، وهو أمر غير محبذ حيث لا بد أن نعطي اللاعب شعورا أن الوحدة البنائية قد تحطمت إلى قطع صغيرة. لحسن الحظ فإن مجموعة الصور التي استخدمناها تحتوي على صور قطع حطام لجميع أنواع المواد المستخدمة، وما علينا سوى استخدامها بالطريقة الصحيحة. لنبدأ أولا بضبط الخصائص الفيزيائية لهذه القطع ومن ثم نصنع منها قوالب بعد أن تصبح جاهزة للاستخدام. لنبدأ مع القطع الثلاث الخاصة بالمعدن، والتي ستكون أجزاء الحطام لكل من الوحدات المعدنية والمتفجرة. صور هذه الأجزاء موجودة في المجلد Explosive elements وهي موضحة في الصورة التالية: سنصنع قالبا واحدا بحيث يمكننا استخدامه لجميع صور القطع، ومن ثم نقوم بتحديد الصورة التي سنضعها عليه من خلال البريمج الذي سنراه بعد قليل. ما يلزمنا في قالب القطع المتناثرة مكوّنان: الأول هو Sprite Renderer والذي سيعرض الصورة كما نعرف،والمكوّن الآخر هو الجسم الصلب Rigid Body 2D والذي سيمكننا من إضافة قوة دافعة لتحريك القطعة.بعد إضافة هذين المكوّنين أصبح القالب المطلوب جاهزا ويمكننا إضافته للمشروع. الصورة التالية توضح القيم المفترضة للجسم الصلب الخاص بهذا القالب (لاحظ أننا لم نضف مكوّن تصادم، وذلك لأننا لا نريد أن تصطدم هذه القطع بأي شيء بل نريدها أن تتناثر وتسقط فحسب). البريمج الثالث الذي سنضيفه للقالب هو BreakablePieces، ومهمته استقبال الرسالة BreakableDestroyed والتي تخبر بأن الكائن قد تم تدميره، وبناء عليها يقوم بإضافة مجموعة من قطع الحطام للمشهد وتحريكها في اتجاهات متباعدة. ليس هذا فقط، بل إن هذا البريمج سيكون مسؤولا عن إحداث الانفجار في حالة المواد المتفجرة. لنلق نظرة على البريمج أولا في السرد أدناه، ومن ثم نتناول أهم خطواته ببعض الشرح. using UnityEngine; using System.Collections; public class BreakablePieces : MonoBehaviour { //قالب كائن قطع الحطام public GameObject piecePrefab; //الصور المستخدمة لقطع الحطام public Sprite[] piecesSprites; //كم عدد القطع التي سيتم إنشاؤها؟ public int pieceCount; //مقدار تصغير أو تكبير قطع الحطام الناتجة public float scale = 1.0f; //ما هي قوة الانفجار الناتجة من تناثر القطع؟ //القيمة صفر تعني عدم وجود انفجار public float explosionForce = 0.0f; //تستدعى مرة واحدة عند بداية التشغيل void Start () { } //تستدعى مرة واحدة عند تصيير كل إطار void Update () { } //BreakableDestroyed تقوم باستقبال الرسالة public void BreakableDestroyed(){ //قم بجلب مكوّن التصادم Collider2D myCollider; myCollider = GetComponent<Collider2D>(); //قم بإيجاد حدود مكوّن التصادم Bounds myBounds = myCollider.bounds; //قم بإنشاء العدد المطلوب من قطع الحطام for(int i = 0; i < pieceCount; i++){ GameObject piece = (GameObject) Instantiate(piecePrefab); //قم بوضع الصورة التالية على القطعة الجديدة int index = i % piecesSprites.Length; SpriteRenderer sr = piece.GetComponent<SpriteRenderer>(); sr.sprite = piecesSprites[index]; //قم بتوليد موقع عشوائي ضمن حدود مكوّن التصادم float posX = Random.Range(myBounds.min.x, myBounds.max.x); float posY = Random.Range(myBounds.min.y, myBounds.max.y); //قم بوضع قطعة الحطام في الموقع العشوائي piece.transform.position = new Vector2(posX, posY); //قم بتحديد الكائن الأب لقطعة الحطام بحيث //يكون الكائن الأب للوحدة البنائية التي تم تدميرها piece.transform.parent = transform.parent; //قم بتغيير حجم القطعة بالمقدار المطلوب piece.transform.localScale *= scale; //قم بجلب مكوّن الجسم الصلب لقطعة الحطام Rigidbody2D rb = piece.GetComponent<Rigidbody2D>(); //قم بإضافة قوة دفع صغيرة //لتحريك قطعة الحطام بحيث يكون اتجاه القوة من مركز //الجسم الأصلي إلى الموقع العشوائي حيث القطعة Vector2 force = piece.transform.position - transform.position; if(explosionForce == 0.0f){ //لا يوجد انفجار rb.AddForce (force, ForceMode2D.Impulse); } else { //يوجد انفجار rb.AddForce(force * explosionForce, ForceMode2D.Impulse); } //احذف قطعة الحطام من المشهد بعد 5 ثوان Destroy(piece, 5.0f); } if (explosionForce > 0.0f) { //تأثير الانفجار على الأجسام الأخرى //قم بحساب نصف قطر مجال تأثير الانفجار float radius = myBounds.max.magnitude * 2.0f; //قم بإيجاد جميع الوحدات البنائية والأجسام القابلة للتحطيم Breakable[] breakables = FindObjectsOfType<Breakable>(); //قم بإرسال قوة الانفجار كمقدار تدمير للأجسام الواقعة في محيط التأثير foreach (Breakable target in breakables) { //استثن الكائن نفسه الذي نتج عنه الانفجار if (target.gameObject != gameObject) { //قم بحساب المسافة بين الكائن وموقع الانفجار وقارنها بنصف قطر محيط التأثير float dist= Vector2.Distance( transform.position, target.transform.position); if (dist <= radius) { //قم بإضافة قوة الانفجار كمقدار للتدمير target.TakeDamage(explosionForce / dist); //قم بحساب مقدار واتجاه قوة دفع الانفجار Vector2 expDir = target.transform.position - transform.position; expDir = expDir * (explosionForce / radius); //قم بإضافة قوة الانفجار للكائن Rigidbody2D targetRB = target.GetComponent<Rigidbody2D>(); targetRB.AddForce(expDir, ForceMode2D.Impulse); } } } } } } يحتاج هذا البريمج حتى يعمل إلى قالب يستخدمه من أجل إنشاء قطع الحطام المطلوبة، إضافة إلى قائمة بالصور التي يمكنه استخدامها لتمثيل هذه القطع. بطبيعة الحال ستختلف قائمة الصور هذه تبعا لمادة الوحدة البنائية الأصلية؛ فالكائن المعدني سينتج قطعا معدنية والخشبي قطعا خشبية وهكذا. إضافة لذلك يمكننا تحديد عدد القطع التي ستنتج عن تحطيم كل وحدة بنائية وحجم هذه القطع. هذه الأرقام ستمكننا مع ضبط عدد وحجم القطع بما يتناسب مع حجم الشكل الأصلي. أخيرا يمكننا اختيار وجود انفجار من عدمه، ومدى قوة الانفجار إن وجد. هذا يجعل البريمج قابلا للاستخدام مع الوحدات المتفجرة أيضا. كل خطوات هذا البريمج مرتبطة باستقبال الرسالة BreakableDestroyed التي سبق ذكرها. عند استقبال الرسالة يقوم البريمج باستخراج مكوّن التصادم ومن ثم استخراج حدود هذا المكوّن، وهي نفسها حدود الكائن. بعد ذلك يدخل في حلقة تكرارية لإنتاج العدد المطلوب من القطع، حيث يقوم في كل مرة بإنشاء قطعة جديدة واختيار صورة لها بالتسلسل. لاحظ استخدام باقي ناتج القسمة من أجل ضمان العودة من بداية قائمة الصور في حال كان عدد القطع المطلوبة أكبر من الصور المتوفرة. بعدها يتم توليد موقع عشوائي لوضع قطعة الحطام، شرط أن يكون ضمن الحدود التي سبق استخراجها من مكوّن التصادم. بما أنّ الكائن الأصلي سيتم حذفه في نهاية الإطار الحالي، فإنه لا يصلح ليكون أبا لقطع الحطام لأنها ستحذف معه في هذه الحالة. بالتالي نأخذ أب الكائن الأصلي ونحدده كأب لقطع الحطام. كذلك يتم تغيير حجم القطعة بالمقدار المطلوب scale، حيث نحتاج أحيانا لجعلها أكبر أو أصغر من حجمها في الصورة الأصلية. بعد أن تصبح قطعة الحطام جاهزة وفي مكانها الصحيح، سنحتاج لإضافة قوة فيزيائية تحركها بعيدا عن مركز القطعة الأصلية. نقوم أولا باستخراج مكوّن الجسم الصلب Rigid Body 2D وهو المسؤول عن الخصائص الفيزيائية لقطعة الحطام، ومن ثم نحسب المتجه المطلوب لهذه القوة وذلك بطرح موقع قطعة الحطام من موقع الكائن الأصلي. إذا كانت قوة الانفجار تساوي صفرا فلن نحتاج سوى لإضافة هذه القوة للجسم الصلب على شكل قوة اندفاع Impulse. أما في حالة وجود انفجار فالأمر أكثر تعقيدا، حيث يتوجب علينا أولا ضرب القوة الدافعة بمقدار قوة الانفجار مما ينتج عنه اندفاع الحطام بسرعة أكبر ولمسافة أبعد. إضافة لذلك سيكون علينا إحداث تأثير على القطع المجاورة وهذا الأمر يتم عن طريق حساب نصف قطر محيط تأثير الانفجار، والذي اخترناه هنا ليكون طول متجه الحد الأقصى مضروبا في 2. نقوم بعدها باستخدام الدّالة ()FindObjectsOfType من أجل البحث عن جميع الكائنات التي تحتوي على البريمج Breakable (أي الوحدات البنائية)، وأي واحد من هذه الوحدات يقع في محيط التأثير يجب أن تضاف له قوة الانفجار الدافعة متناسبة عكسيا مع المسافة بين مركز الانفجار في الجسم المدمر وبين الوحدة المستهدفة. قوة الانفجار الدافعة ستقوم فقط بتحريك الوحدة البنائية، لكننا نريد أيضا إنقاص صحتها بسبب الانفجار ولذلك نستدعي ()TakeDamage. بعد إضافة البريمجات أصبح الكائن جاهزا لنصنع منه قالب المثلث المعدني. لكون عدد قوالب الأشكال كبيرا نسبيا، من الأفضل وضع كل مجموعة في مجلد خاص بها. مثلا مجلد Metal للأشكال المعدنية و Wood للخشبية وهكذا. بعد صناعة القالب يمكنك أن تغير الكائن نفسه وتغير اسمه ومن ثم تسحبه مرة أخرى إلى مستعرض المشروع لصناعة قالب جديد. مثلا يمكنك استبدال صورة المثلث بالدائرة ومن ثم تغيير الاسم إلى Circle. أيضا سيتوجب عليك تغيير شكل مكوّن التصادم عن طريق إزالة المكوّن Polygon Collider 2D وإضافة المكوّن Circle Collider 2D لأنه الأنسب للدائرة. وبعد صناعة قالب الدّائرة نضيف واحدا آخر للمستطيل مع تغيير مكوّن التصادم مرة أخرى ليصبح Box Collider 2D وهكذا حتى ننجز الأشكال التي نرغب بها. أثناء عملك راعي الأمور التالية: لحذف مكوّن موجود على كائن، قم بالضغط على رمز الترس في أعلى يمين المكوّن في نافذة الخصائص ومن ثم اختر Remove Component.هناك بعض الأشكال مثل المثلث القائم تحتوي على صور لمرحلتي تشقق فقط بينما الأشكال الباقية تحتوي على 3 مراحل. هذا يؤثر فقط على عدد عناصر المصفوفة destructionStages ولا يلزمنا تغيير أي شيء في الكود.مقدار الكتلة للمواد هي 6 للمعدن والمواد المتفجرة و2.5 للزجاج و5 للصخور و1 للخشب.مقدار الصحة الافتراضية هي 100 للمعدن و 45 للمواد المتفجرة و20 للزجاج و 80 للصخور و 35 للخشب.بعد الانتهاء من الوحدات البنائية علينا أن نحل مشكلة صغيرة ستطرأ الآن. تذكر أن الكائنات الموجودة في المشهد حاليا هي الخلفية والأرضية والوحدات البنائية، وجميع هذه الكائنات تحتوي على مكوّنات تصادم بغض النظر عن أشكالها. معنى هذا أن Unity سيقوم باكتشاف التصادمات بين هذه الكائنات مع بعضها، وهذا ما نريده بالنسبة للأرضية والوحدات البنائية التي ستوضع فوقها، لكننا لا نريده للخلفية. فإذا تصادمت الوحدات البنائية مع الخلفية سيختل منطق المشهد تماما. لحل هذه المشكلة يوفر لنا Unity نظام الطبقات Layers والذي يمكننا من خلاله فصل الكائنات إلى طبقات بحيث يمكننا لاحقا التحكم بعلاقات هذه الطبقات مع بعضها. فمثلا يمكن أن نحدد للكاميرا ما هي الطبقات التي يمكنها أن تراها، كما يمكننا أن نحدد أي الطبقات تتصادم مع بعضها البعض. إذن لحل هذا الإشكال علينا أن نضيف طبقة جديدة مخصصة للخلفية، ونمنعها من التصادم مع الطبقة الافتراضية التي تنتمي إليها باقي الكائنات. لإضافة طبقة جديدة قم باختيار قالب الخلفية BGElement ومن ثم افتح القائمة Layer الموجودة في أعلى يمين نافذة الخصائص واختر Add Layer كما ترى في الصورة: ستظهر لك نافذة فيها مصفوفة بجميع الطبقات الافتراضية حيث يمكنك من خلالها إضافة طبقات جديدة خاصة بك. لنقم بإضافة طبقة جديدة اسمها Background، ومن ثم نقوم بتغيير القالب BGElement ليصبح ضمن هذه الطبقة كما ترى في الصورتين التاليتين: بعدها علينا أن نطلب من محاكي الفيزياء الخاص بالمحرك أن يهمل التصادمات الحاصلة بين الطبقة الافتراضية Default وطبقة الخلفية Background بحيث لا تتصادم عناصر الأرضية أو الوحدات البنائية مع الخلفية. لتنفيذ هذا الأمر اذهب إلى القائمة: Edit > Project Settings > Physics 2D حيث ستجد في أسفل نافذة الخصائص مصفوفة تصادم الطبقات Layer Collision Matrix والتي تحتوي على جميع الطبقات الموجودة في المشروع منتظمة في صفوف وأعمدة. في كل نقطة تقاطع بين صف وعمود ستجد مربعا يمكنك تفعيله أو تعطيله. إذا قمت بتعطيل أحد هذه المربعات فإن التصادم الحاصل بين الطبقتين المتقاطعتين فيه سيتم إهماله. بالتالي ما نريده هو تعطيل المربع الذي تتقاطع فيه الطبقة Default مع الطبقة Background كما ترى في الصورة أدناه: بعد تجهيز قوالب الوحدات البنائية يتبقى علينا إضافة قالب قطع الحطام للبريمج BreakablePieces، كما أن علينا تحديد صور القطع الخاصة بكل وحدة بنائية وتحديد عددها وأحجامها. لاختصار الوقت سأعتمد قيما ثابتة لجميع الوحدات البنائية، وهو 5 قطع حطام لكل وحدة وتحجيم بمقدار 0.5 (صور قطع الحطام موجودة في مجلد يسمى Debris). للوقوف على التقدم في بناء قالب الوحدة البنائية، يفترض أن يكون ما أنشأناه حتى الآن شبيها بما تراه في الصورة أدناه: السؤال التالي الذي نريد الإجابة عليه هو: كيف تتناقص قيمة صحة هذه الوحدات البنائية عند سقوطها أو اصطدامها ببعضها البعض أو بمقذوفات اللاعب؟ يساعدنا Unity بالإجابة على هذا السؤال حيث أنه يوفر لنا رسائل إعلام بحدوث أي عمليات تصادم بين الكائنات المختلفة. سنقوم الآن بكتابة بريمج يستقبل رسائل التصادم هذه ويقوم بتحليل محتوياتها وحساب مقدار التدمير الذي يجب أن يتم على كل وحدة بنائية. هذا البريمج هو CollisionDamageTaker، وهو موضح في السرد التالي: using UnityEngine; using System.Collections; public class CollisionDamageTaker : MonoBehaviour { //متغير لتخزين آخر عملية تصادم //يساعد هذا على منع تكرار التصادمات private float lastCollisionTime = 0.0f; //يتم استدعاؤها مرة واحدة عند بداية التشغيل void Start () { } //يتم استدعاؤها مرة عند تصيير كل إطار void Update () { } //يتم استدعاؤها عند حدوث تصادم بين هذا الكائن وكائن آخر void OnCollisionEnter2D(Collision2D col) { if (Time.time - lastCollisionTime < 0.25f) { //لم يمر وقت كاف منذ آخر تصادم، قم بإهمال هذا التصادم ولا تفعل شيئا return; } //قم بتسجيل وقت حدوث التصادم lastCollisionTime = Time.time; //قم باستخراج مكوّن الموقع من الكائن الآخر الذي حدث معه التصادم Transform otherObject = col.transform; //احسب ارتفاع الكائنين المتصادمين float myHeight = transform.position.y; float otherHeight = otherObject.position.y; //ما هو مقدار قوة الإصابة التي تم تلقيها؟ float damageAmount = 1.0f; //قم بحساب قوة الإصابة بناء على موقع //الكائن الآخر if (myHeight < otherHeight) { //سقط كائن آخر فوق هذا الكائن //كم كانت سرعة الجسم الساقط حين اصطدامه؟ float fallVelocity = col.relativeVelocity.magnitude; //اضرب مقدار الإصابة بسرعة الاصطدام damageAmount *= fallVelocity; //ما هي كتلة الكائن الذي سقط فوق هذا الكائن؟ Rigidbody2D otherRB = otherObject.GetComponent<Rigidbody2D>(); float otherMass = otherRB.mass; //اضرب مقدار الإصابة مرة أخرى بالكتلة damageAmount *= otherMass; //قم أخيرا بمضاعفة مقدار الإصابة لأن الكائن الآخر جاء من مكان أعلى damageAmount *= 2.0f; } else { //الكائن الحالي هو الذي سقط //الكائنات الساقطة بسرعة أكبر ستحصل على إصابة أكبر float myFallVelocity = col.relativeVelocity.magnitude; //اضرب مقدار الإصابة بسرعة الاصطدام damageAmount *= myFallVelocity; } //قم بإرسال رسالة لإنقاص الصحة بمقدار الإصابة المحسوبة SendMessage("TakeDamage", damageAmount); } } كما ذكرت فإنّ هذا البريمج يعمل على تقليل صحة كائن الوحدة البنائية بناء على اصطدامها بالكائنات الأخرى في المشهد. المتغير الوحيد الذي عرفناه هنا هو lastCollisionTime والذي يخزن الوقت الذي تم فيه إنقاص الصحة آخر مرة. الهدف من استخدام هذا المتغير هو منع الاصطدامات المتتالية والتي قد تحدث في إطار واحد أو إطارين متتابعين من إنقاص الصحة بسرعة كبيرة، حيث أننا هنا نسمح بإنقاص الصحة مرة كل ربع ثانية فقط. عند تصادم كائنين مع بعضهما يقوم محرك Unity بإرسال الرسالة OnCollisionEnter إلى هذين الكائنين في نفس الوقت، ويرفق مع هذه الرسالة متغيرا من نوع Collision2D والذي يحتوي على معلومات حول التصادم، إضافة لأنه يحتوي على مرجع للكائن الآخر بالتالي يمكن لكل منهما التعرف على الكائن الآخر الذي اصطدم به وخصائصه. الخطوة الأولى للدّالة ()OnCollisionEnter هي أن تتأكد من مرور ربع ثانية على الأقل منذ آخر مرة تم فيها إنقاص صحة الكائن، فإن لم يتحقق هذا الشرط سيتوقف تنفيذ الدّالة على الفور. طريقة حساب مقدار الإصابة (المقدار الذي سيتم إنقاصه من الصحة) يعتمد على عدة عوامل ويبدأ من قيمة افتراضية هي 1. العامل الأول هو ارتفاع كل من الكائنين المتصادمين. لنفترض أن الدّالة اكتشفت أثناء التنفيذ أن الكائن الآخر otherObject ذو ارتفاع أعلى من الكائن الحالي. هذا الأمر يفسر على أن الكائن الآخر قد سقط فوق الكائن الحالي واصطدم به، بالتالي يجب أن يكون مقدار الإصابة أعلى. من أهم المعلومات التي تحملها الرسالة هي col.relativeVelocity، والتي تحسب السرعة النسبية بين الكائنين لحظة الاصطدام. منطقيا يجب أن يتناسب مقدار هذه السرعة طرديا مع قوة الإصابة، لذا فإننا نقوم باستخراج هذا المقدار relativeVelocity.magnitude (السرعة هنا هي متجه لذلك نستخرج مقدارها) وضربه بقيمة قوة الإصابة. بعد ذلك نقوم باستخراج مكوّن الجسم الصلب RigidBody2D من الكائن الآخر وضرب كتلته بمقدار الإصابة، حيث يجب أن تزيد الإصابة كلما كان الكائن الذي سقط ذا كتلة أكبر. أخيرا نقوم بمضاعفة القيمة النهائية التي حسبناها؛ وذلك لجعل سقوط كائن فوق آخر ذا تأثير أكبر من سقوط الكائن نفسه على الأرض أو على جسم آخر. الاحتمال الآخر هو أن يكون الكائن الحالي ذا ارتفاع أعلى من الكائن الآخر الذي سقط فوقه، بالتالي لا حاجة لنا بأخذ أية معلومات من هذا الجسم الآخر. كل ما سنفعله في هذه الحالة هو ضرب قيمة الإصابة بسرعة الاصطدام، مما يجعل سقوط الجسم نفسه أقل أذى من سقوط جسم آخر فوقه. بعد المرور على أحد هذين الاحتمالين نحصل على قيمة الإصابة النهائية في المتغير damageAmount وبالتالي نرسل الرسالة TakeDamage ونرفق معها القيمة المحسوبة. لاحظ أن البريمج المرسل CollisionDamageTaker والمستقبل Breakable موجودان على نفس الكائن، ولا يوجد أي كائن آخر مهتم باستقبال هذه الرسالة. لهذا السبب استخدمنا الدّالة()SendMessage في عملية الإرسال. بقي علينا خطوة واحدة لإكمال قالب الوحدة البنائية، وهي الصوت الذي سيصدر من الوحدة البنائية حين تحطمها. هذا الصوت سيختلف باختلاف مادة الوحدة البنائية؛ فصوت تحطم الزجاج ليس كالحجر وليس كالمعدن أو الخشب. هذا الاختلاف سينعكس على ملف الصوت المستخدم، إلا أن التقنية ستكون نفسها وستعمل كلها باستخدام نفس البريمج وهو BreakableSounds. سيعمل هذا البريمج على إصدار صوت في حالتين: عند تلقي إصابة بمقدار قوي، وعند تحطم الوحدة البنائية نهائيا. الهدف من حصر الصوت الأول بالإصابات ذات المقدار القوية هو أن عددا كبيرا من التصادمات يمكن أن يحدث في نفس الإطار مما سينتج عنه أصوات كثيرة مزعجة وهي نتيجة ليست مرضية على الإطلاق. هذا البريمج موضح في السرد التالي: using UnityEngine; using System.Collections; public class BreakableSounds : MonoBehaviour { //يتم تشغيل هذا الصوت عند تلقي إصابة public AudioClip damageSound; //يتم تشغيل هذا الصوت عند تحطم الوحدة البنائية public AudioClip destructionSound; //الحد الأدنى لمقدار الإصابة التي تؤدي لتشغيل الصوت public float minDamage = 25.0f; //المدة الزمنية التي يمنع خلالها تشغيل أي صوت من قبل هذا الكائن private float suspensionTime = 0.0f; //الوقت الذي بدأ فيه تشغيل آخر صوت من قبل هذا الكائن private float playTime = 0.0f; //تستدعى مرة واحدة عند بداية التشغيل void Start () { } //تستدعى مرة عند تصيير كل إطار void Update () { } //DamageTaken تقوم باستقبال رسالة الإصابة void DamageTaken(float amount) { //سيتم تشغيل الصوت فقط للإصابات التي //يزيد مقدارها عن الحد الأدنى if (amount >= minDamage) { CheckAndPlay(damageSound); } } //BreakableDestroyed تقوم باستقبال رسالة تدمير الوحدة البنائية void BreakableDestroyed() { AudioSource.PlayClipAtPoint(destructionSound, transform.position); } //تقوم بحساب الوقت الذي يمنع فيه تشغيل ملف الصوت وتقرر بناء عليه تشغيل الملف مجددا من عدمه void CheckAndPlay(AudioClip clip) { if (Time.time - playTime > suspensionTime) { AudioSource.PlayClipAtPoint(clip, transform.position, 0.25f); playTime = Time.time; suspensionTime = clip.length + 0.5f; } } } لعل المهام الرئيسية لهذا البريمج واضحة: فهو يستقبل الرسالتين DamageTake و BreakableDestroyed من البريمج Breakable ويقوم بناء عليها بتشغيل واحد من ملفي الأصوات المحددين وهما من نوع AudioClip، واللذين يمكننا اختيارهما من نافذة الخصائص كما سنرى بعد قليل. المتغير minDamage يمكننا من اختيار الحد الأدنى للإصابة التي ستؤدي إلى تشغيل ملف الصوت، وهو افتراضيا 25. لاحظ أن تشغيل صوت الإصابة يتم بطريقة تختلف عن تشغيل صوت التدمير؛ ذلك أن الأخير لا يمكن أن يتكرر كما هو الحال في الأول. بطبيعة الحال فإن تلقي عدة إصابات في فترة قصيرة أمر ممكن، لذلك علينا أن نمنع تكرار تشغيل ملف الصوت مرات متتابعة بشكل مزعج. لأجل ذلك نقوم عند تشغيل ملف صوت الإصابة بحساب طول الملف وإضافة نصف ثانية إليه، ومن ثم تخزين الناتج في المتغير suspentionTime. عند محاولة تشغيل ملف صوت الإصابة مرة أخرى نقوم بمقارنة الوقت المنقضي منذ آخر تشغيل بوقت منع التشغيل suspentionTime. إذا كانت هذه المدة أقل من وقت المنع فلن يتم تشغيل الملف. هذه الخطوات تقوم بها الدّالة ()CheckAndPlay. بعد إضافة هذا البريمج لقالب الوحدة البنائية، سيظهر المتغيران damageSound و destructionSound في نافذة الخصائص على شكل خانات يمكن أن تضيف إليها ملفات صوتية. لكل نوع من أنواع الوحدات البنائية الخمسة (المعدن والمتفجرات والحجر والخشب والزجاج) سيكون هناك ملفات مختلفة. هذه الملفات تم جلبها من مواقع مختلفة حيث لا يتوفر دائما مكتبة صوتية شاملة يمكن الاعتماد عليها كمصدر لكل المؤثرات الصوتية، أو على الأقل لا تتوفر مجانا. كما ذكرت سابقا تم وضع الملفات في مجلدات تحمل أسماء المواقع التي تم إحضارها منها، مع الإبقاء على اسم الملف الأصلي كما هو في الموقع دون تغيير. الصورة التالية توضح شكل البريمج BreakableSounds لكائنين أحدهما وحدة بنائية خشبية والأخرى حجرية. وبهذا نكون قد انتهينا من قوالب الوحدات البنائية بشكل عام. الصورة الأخيرة في الأسفل توضح الشكل العام لقوالب الوحدات البنائية مع كافّة المكوّنات اللازمة، والتي تم إغلاقها اختصارا للمساحة. بقي أمر واحد سنضيفه كلمسة جمالية على لعبتنا، وهي حدوث انفجار مرئي عند تحطم الوحدات البنائية المتفجرة. هذا الانفجار موجود في الحزمة Explosion Pack في موقع kenney.nl والذي سبق وضع روابطه، وهو يحمل الاسم Regular Explosion. الانفجار عبارة عن 9 صور متتابعة كما ترى في الصورة في الأسفل: ما يتوجب فعله الآن هو أن نصنع قالبا خاصا بالانفجار بحيث يعرض هذه الصور التسعة بشكل متتابع، ومن ثم نقوم بكتابة بريمج يعمل على إنشاء كائن من هذا القالب في حال تحطم أحدى الوحدات البنائية المتفجرة. لنبدأ مع قالب الانفجار والذي سيحتوي على مكوّن واحد هو SpriteRenderer إضافة للبريمج SpriteAnimator الموضح في السرد التالي، والذي سيعمل على عرض الصور بشكل متتابع. using UnityEngine; using System.Collections; public class SpriteAnimator : MonoBehaviour { //مصفوفة تحتوي على اللقطات التي تشكل الحركة public Sprite[] frames; //سرعة التحريك مقدرة بعدد اللقطات في الثانية public float framesPerSecond = 16.0f; //هل يجب أن يتم تدمير الكائن وحذفه بعد انتهاء التحريك؟ public bool destroyOnCompletion = true; //متغير لتسجيل الوقت الذي تم فيه تغيير اللقطة آخر مرة private float lastChange = 0.0f; //متغير مرجعي لمكوّن تصيير الصور ثنائية الأبعاد private SpriteRenderer renderer; //موقع اللقطة المعروضة حاليا في مصفوفة اللقطات private int currentFrame = 0; //يتم استدعاؤها مرة واحدة عند بداية التشغيل void Start () { renderer = GetComponent<SpriteRenderer>(); } //يتم استدعاؤها مرة عند تصيير كل إطار void Update () { Animate(); } //تقوم بعملية التحريك عن طريق عرض اللقطات بشكل متتابع void Animate() { //احسب المدة التي يجب أن تقضيها اللقطة الواحدة float frameTime = 1.0f / framesPerSecond; //قم بالتبديل للإطار التالي في حال انقضى الوقت اللازم للقطة السابقة if (Time.time - lastChange > frameTime) { lastChange = Time.time; currentFrame = (currentFrame + 1) % frames.Length; renderer.sprite = frames[currentFrame]; if (currentFrame == 0 && destroyOnCompletion) { Destroy(gameObject); } } } } ببساطة شديدة يقوم هذا البريمج عند تصيير كل إطار باستدعاء الدّالة Animate، والتي تقوم بحساب الوقت اللازم لعرض كل لقطة عن طريق قسمة الرقم 1 على السرعة. بعد ذلك تقارن الوقت المنقضي منذ تم التبديل للقطة الحالية مع الوقت اللازم للقطة الواحدة، فإذا انقضى هذا الوقت تقوم بالتبديل إلى اللقطة التالية في المصفوفة frames. من البديهي هنا أن تتم إضافة لقطات الانفجار بشكل مرتب إلى المصفوفة frames وذلك حتى تظهر بالتتابع الصحيح كما هو موضح في الصورة التالية. لاحظ أخيرا أننا نقوم بتدمير الكائن بعد انتهاء عرض اللقطات لأننا لا نريد تكرار مشهد الانفجار سوى مرة واحدة. بعد إنشاء قالب الانفجار علينا أن نربط إنشاء الانفجار بتدمير الوحدة البنائية المتفجرة. هذه عملية بسيطة لا تتطلب أكثر من استقبال الرسالة BreakableDestroyed ومن ثم إنشاء كائن جديد من قالب الانفجار في نفس موقع الوحدة البنائية التي تم تدميرها. هذه المهمة يقوم بها البريمج BreakableSpawn والموضح في السرد التالي: using UnityEngine; using System.Collections; public class BreakableSpawn : MonoBehaviour { //قالب الكائن الذي سيتم إنشاؤه بعد التدمير public GameObject prefab; //يتم استدعاؤها مرة عند بداية التشغيل void Start () { } //يتم استدعاؤها مرة عند تصيير كل إطار void Update () { } //BreakableDestroyed تقوم باستقبال رسالة تدمير الوحدة البنائية void BreakableDestroyed() { //قم بإنشاء كائن جديد كم القالب وضعه في نفس موقع الكائن الحالي الذي تم تدميره GameObject newObject = (GameObject)Instantiate(prefab); newObject.transform.position = transform.position; newObject.transform.parent = transform.parent; } } إنشاء كائنات الخصومكما تعلم تتكون المرحلة الواحدة في هذه الألعاب من العناصر البنائية والخصوم ومقذوفات اللاعب التي يطلقها على هذه الوحدات والخصوم التي تحتمي بها. بالتالي فالعنصر الثاني الذي يلزمنا بعد تجهيز الوحدات البنائية هو شخصيات الخصوم. بالاطلاع على المجلد Aliens في مجموعة الصور، تلاحظ وجود خمسة أنواع من الكائنات بأشكال غريبة، بعضها مربع الشكل والآخر دائري، وبعضها يرتدي ما يشبه الخوذة. من ناحية السلوك الفيزيائي لا تختلف كائنات الخصوم عن الوحدات البنائية؛ حيث أنها تمتلك صحة محددة تنقص بتلقي الضربات، كما أنها تتأثر بالانفجارات والتصادمات وما شابه. هذا يعني – لحسن الحظ – أن المجهود الذي بذلناه في كتابة البريمجات السابقة الخاصة بقوالب الوحدات البنائية سيعطي ثماره في هذه المرحلة، حيث سنعيد استخدام تلك البريمجات من أجل صنع قوالب الخصوم، ولن نحتاج لكتابة أي بريمج جديد باستثناء واحد سنتحدث عنه بعد قليل. كل ما علينا هو إضافة البريمجات Breakable و BreakablePieces و CollisionDamageTaker و BreakableSounds، ومن ثم تحديد القيم المناسبة لكل نوع من أنواع الوحوش. اختصارا للوقت سأعتبر الأشكال الأربعة ذات نفس الخصائص، إضافة لمنح الوحوش التي تحتوي على خوذة مقدارا أعلى من الصحة. ستكون صحة الوحشين المربع والدائري هي 50، بينما الوحش ذو الخوذة ستكون صحته 100. وهذا سينطبق على الألوان الخمسة للوحوش. بطبيعة الحال علينا أيضا إضافة مكوّن الجسم الصلب RigidBody2D و أحد مكوّني التصادم BoxCollider2D أو CircleCollider2D وذلك حسب شكل الوحش. الشكل التالي يوضح القالب الخاص بأحد الوحوش التي ترتدي خوذة. يمكنك الاطلاع على قوالب الوحوش في المجلد Prefabs\Enemies: هناك اختلافات أخرى يجب مراعاتها بين الوحدات البنائية والوحوش، فهناك ملفات صوتية مختلفة للإصابة والتدمير، إضافة لأن تدمير الوحوش ينتج عنه نجوم بدلا من قطع الحطام. صور النجوم هذه موجودة في المجلد PhysicsPack\Others وهي موضحة في الشكل التالي. لاحظ أيضا أن عدد النجوم الناتجة كبير نسبيا وهو 10: كل الفروق السابقة بين الوحدات البنائية والوحوش هي فروق شكلية، لكن الفرق الأهم هو أن نكون قادرين على التمييز بينهما برمجيا؛ وذلك لأن تدمير الوحوش يختلف عن تدمير الوحدات البنائية وهو ذو علاقة مباشرة بحالة اللعبة. فتدمير جميع الوحوش في المشهد سيؤدي لفوز اللاعب بالمرحلة وانتقاله للمرحلة التالية، إلا أن هذا ليس هو الحال بالنسبة للوحدات البنائية. ولأن تدمير الوحوش أمر مهم، علينا أن نضيف لقالب كل وحش منها بريمجا يقوم بإرسال رسالة للكائن الجذري حين تدمير كائن الوحش، وسيتكفل بريمج آخر سنأتي عليه بعد حين بمهمة استقبال الرسالة وعمل ما يلزم حيالها. ما يهم الآن هو أن نضيف البريمج Enemy والموضح في السرد التالي لكل قوالب الوحوش التي أنشأناها. using UnityEngine; using System.Collections; public class Enemy : MonoBehaviour { //يتم استدعاؤها مرة عند بداية التشغيل void Start () { } //يتم استدعاؤها مرة عند تصيير كل إطار void Update () { } //ومن ثم BreakableDestroyed تقوم باستقبال الرسالة //ترسل رسالة للأعلى أي للكائن الجذري بأن الوحش تم تدميره void BreakableDestroyed() { SendMessageUpwards("EnemyDestroyed"); } }:بهذا أصبح لدينا كل ما يلزم لبناء مشهد، وما عليك سوى رص الوحدات البنائية والوحوش بأي ترتيب ترغب به من أجل صنع مرحلة كما في الصورة التالية .وبهذا نكون انتهينا من تجهيز مشهد اللعبة. سنقوم في الدرس القادم ببناء واجهة المستخدم والشاشة الرئيسية للعبة
  4. سنتعلم في هذا الدرس كيفية تصميم شخصيات لعبة Angry Birds اللطيفة، باستخدام برنامج Photoshop وبخطوات بسيطة. وهذه نتيجة درسنا اليوم: افتح مشروع جديد على Photoshop بالإعدادات التالية: الأبعاد: 900x900pixels.الدقة: Resolution 720Dpi.نمط الألوان: Color Mode RVB8bit.نضيف طبقة لون متدرج: Menu > Layer > New Fill Layer > Gradient باستعمال أداة الفرشاة (Brush) نضيف بعض السحب كما في الصورة: ثم نأخذ أداة القلم Pen Tool باستعمال اللون # d5002c نرسم الشكل التالي: وفي خصائص الدمج Blending Options الخاصة بالشكل نضيف محيط Storke: في طبقة جديدة أخرى نقوم برسم قطعتين في أعلى الشكل: بنفس الطريق السابقة نضيف منقار الطائر باللون الأصفر #fbba20: ثم في طبقة جديدة يكون ترتيبها أسفل طبقة المنقار نرسم بأداة القلم الشكل المبين في الصورة باللون #e2c4a8: باستعمال أداة الشكل الدائري (U) نرسم دوائر باللون #a80026: بنفس الطريقة نرسم دائرتين باللون الأبيض تمثلان عيني الطائر: إلى خصائص الدمج Blending Options: بعد ذلك نحدد جميع الطبقات وندمجها في طبقة واحدة (Ctrl+E) ثم باستعمال أداة الكثافة (O) نضيف بعض الظلمة في أماكن العلامة +: نقوم بعمل طبقة Layer جديدة وذلك بالنقر على Ctr+Shift+N ثم باستعمال أداة الفرشاة وأشكال السحاب نرسم أشكال وتموجات كما في الصورة: نضيف طبقة جديدة أخرى وبفرشاة الشكل الدائري باللون الأخضر #25c60a نرسم في الأسفل: نضيف الأعشاب والحشائش باللون الأخضر (الفرش تأتي منصبة مع برنامج Photoshop): نضيف طبقة أخرى بلون متدرج من نوع Gradient Map وذلك بالذهاب إلى: Menu > Layer > New Layer Adjustment > Gradient Map نغير في قيمة الشفافية Opacity إلى القيمة 57 وMode إلى Screen: في طبقة جديدة وبفرشاة دائرية سوداء اللون نرسم في جنبات الشكل: ثم خصائص الدمج: لنحصل على النتيجة النهائية: ترجمة -وبتصرّف- للدّرس: http://www.tutsps.com/index.php?post/2012/10/19/Creer-un-des-personnages-d-angry-birds-avec-photoshop.