اذهب إلى المحتوى

البحث في الموقع

المحتوى عن '3d'.

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

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

نوع المحتوى


التصنيفات

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

التصنيفات

  • مقالات برمجة عامة
  • مقالات برمجة متقدمة
  • PHP
    • Laravel
    • ووردبريس
  • جافاسكربت
    • لغة TypeScript
    • Node.js
    • React
    • Vue.js
    • Angular
    • jQuery
    • Cordova
  • HTML
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • لغة C#‎
    • ‎.NET
    • منصة Xamarin
  • لغة C++‎
  • لغة C
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • لغة Rust
  • برمجة أندرويد
  • لغة R
  • الذكاء الاصطناعي
  • صناعة الألعاب
  • سير العمل
    • Git
  • الأنظمة والأنظمة المدمجة

التصنيفات

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

التصنيفات

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

التصنيفات

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

التصنيفات

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

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
    • بريستاشوب
    • أوبن كارت
    • دروبال
  • الترجمة بمساعدة الحاسوب
    • omegaT
    • memoQ
    • Trados
    • Memsource
  • برامج تخطيط موارد المؤسسات ERP
    • تطبيقات أودو odoo
  • أنظمة تشغيل الحواسيب والهواتف
    • ويندوز
    • لينكس
  • مقالات عامة

التصنيفات

  • آخر التحديثات

أسئلة وأجوبة

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

التصنيفات

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

ابحث في

ابحث عن


تاريخ الإنشاء

  • بداية

    نهاية


آخر تحديث

  • بداية

    نهاية


رشح النتائج حسب

تاريخ الانضمام

  • بداية

    نهاية


المجموعة


النبذة الشخصية

  1. ملاحظة: يمكن تحميل الملفات المصدرية لكامل هذه السلسلة عبر حساب أكاديمية حسوب على Github، يمكن أيضا تحميل ملف APK لتجريب اللعبة على أجهزة Android. استقبال مدخلات شاشة اللمساستقبال المدخلات من شاشة اللمس تختلف عن استقبال مدخلات الفأرة أو لوحة المفاتيح. فأنت هنا تتعامل مع شاشة تستقبل عدة لمسات، وتتعامل مع أحداث مثل وضع الإصبع وتحريكه ورفعه، أو وضع أصبعين وتقريبهما أو إبعادهما عن بعضهما. كل هذه الأنماط من الإدخال سيكون عليك التعرف عليها وتنفيذ ما يناسبها من أوامر. لنبدأ أولا مع مدخلات عناصر واجهة المستخدم مثل الأزرار. ما الذي يجب علينا فعله لاستقبال المدخلات على هذه العناصر؟ لا شيء! فهذا الأمر يقوم به محرك Unity تلقائيا. أي أنك عندما تلمس زرا على الشاشة سيتعرف التطبيق على هذا الأمر كأنك ضغطت على الزر وينفذ الأمر أو الأوامر المرتبطة به. لننتقل الآن للمدخلات الخاصة باللعبة. تذكر أننا قمنا بكتابة 3 بريمجات لاستقبال مدخلات الفأرة، وسنحتاج الآن لكتابة 3 مقابلها لاستقبال مدخلات شاشة اللمس. هذه البريمجات الثلاث هي: CameraMouseInput والذي أضفناه لقوالب عناصر الخلفية والأرضية من أجل تحريك الكاميرا والتحكم بتقريبها وإبعادها.LauncherMouseInput والذي أضفناه على قالب المقلاع بحيث يستقبل مدخلات اللاعب على المقذوفات ويحدد اتجاه التصويب وشدته ويطلق المقذوف حين إفلاته.SpecialAttackMouseInput والذي أضفناه على قوالب المقذوفات من أجل تنفيذ الهجوم الخاص عند الضغط على زر الفأرة بعد الإطلاق.الموضوع ببساطة شديدة أننا مقابل كل بريمج إدخال من الفأرة سنكتب بريمج إدخال من شاشة اللمس ونضيفه على نفس القالب. القاسم المشترك بين قوالب استقبال مدخلات اللمس أنها ستقوم بالتحقق من بيئة تشغيل اللعبة، فإذا وجدت أن نظام التشغيل هو Android ستقوم بتدمير بريمجات استقبال مدخلات الفأرة الموجودة معها على نفس الكائن. أهمية هذه الخطوة تكمن في أن Unity يحاول محاكاة وجود فأرة على شاشات اللمس عن طريق تحويل اللمسات إلى مدخلات فأرة. هذا الأمر يؤدي إلى سلوك غير مرغوب لا يفيد في لعبتنا، لذا نتجنبه عن طريق حذف أي بريمج يقرأ من الفأرة. لنبدأ مع بريمج التحكم بالكاميرا CameraTouchInput والذي سنضيفه على قالبي عنصري الخلفية والأرضية حيث يوجد CameraMouseInput أيضا. هذا البريمج موضح في السرد التالي: using UnityEngine; using System.Collections; public class CameraTouchInput : MonoBehaviour { //سرعة تحريك الكاميرا public float movementSpeed = 0.0075f; //سرعة التقريب والإبعاد public float zoomingSpeed = 0.00075f; //هي يلمس اللاعب الشاشة حاليا بإصبع واحد؟ private bool singleTouch = false; //هل يلمس اللاعب الشاشة حاليا بأصبعين private bool doubleTouch = false; //مرجع لبريمج التحكم بالكاميرا CameraControl camControl; //تستدعى مرة عند بداية التشغيل void Start() { //قم بتدمير بريمج استقبال مدخلات الفأرة إن تم اكتشاف نظام تشغيل الهاتف الذكي if (Application.platform == RuntimePlatform.Android) { CameraMouseInput mouseInput = GetComponent<CameraMouseInput>(); Destroy(mouseInput); } camControl = FindObjectOfType<CameraControl>(); } //يتم استدعاؤها مرة عند تصيير كل إطار في وقت متأخر void LateUpdate() { UpdateSingleTouch(); UpdateDragging(); UpdateDoubleTouch(); UpdateZooming(); } //تتأكد من كون اللاعب يلمس الشاشة بإصبع واحد void UpdateSingleTouch() { if (Input.touchCount == 1) { Touch playerTouch = Input.touches[0]; if (playerTouch.phase == TouchPhase.Began) { //قام اللاعب للتو بوضع إصبعه على الشاشة //هل تم وضع الإصبع على هذا الكائن تحديدا؟ Vector2 touchPos = Camera.main.ScreenToWorldPoint(playerTouch.position); //اجلب مكوّن التصادم الخاص بهذا الكائن Collider2D myCollider = GetComponent<Collider2D>(); //قم بتوليد شعاع قصير جدا ابتداء من موقع اللمس وباتجاه الأعلى واليمين //ومن ثم تحقق من كون هذا الشعاع قد اصطدم بمكوّن التصادم الخاص بهذا الكائن RaycastHit2D hit = Physics2D.Raycast(touchPos, Vector2.one, 0.1f); if (hit.collider == myCollider) { //نعم لقد قام اللاعب بلمس هذا الكائن بإصبع واحد singleTouch = true; } } else if (playerTouch.phase == TouchPhase.Ended || playerTouch.phase == TouchPhase.Canceled) { //قام اللاعب للتو برفع إصبعه عن الشاشة singleTouch = false; } } else { //عدد الأصابع على الشاشة لا يساوي 1 أي أنه //لا يوجد هناك لمسة بإصبع واحد singleTouch = false; } } //تقوم بفحص تحريك اللاعب لإصبع واحد على الشاشة void UpdateDragging() { if (singleTouch) { Touch playerTouch = Input.touches[0]; camControl.Move(playerTouch.deltaPosition * -movementSpeed); } } //تقوم بفحص قيام اللاعب باللمس بأصبعين void UpdateDoubleTouch() { //تأكد من عدم وجود لمسة بإصبع واحد حاليا if (!singleTouch) { if (Input.touchCount == 2) { doubleTouch = true; } else { doubleTouch = false; } } } //تقوم بتحديث التقريب والإبعاد مستخدمة حركة الأصبعين على الشاشة void UpdateZooming() { if (doubleTouch) { //على الشاشة A, Bمواقع الأصبعين المسميين //في كل من الإطار الحالي 2 والإطار السابق 1 Vector2 posA1, posA2, posB1, posB2; Touch a, b; a = Input.touches[0]; b = Input.touches[1]; posA2 = a.position; posB2 = b.position; posA1 = a.position - a.deltaPosition; posB1 = b.position - b.deltaPosition; //تأكد من كون المسافة بين الأصابع قد زادت أو قلت منذ //الإطار السابق float currentDist = Vector2.Distance(posA2, posB2); float prevDist = Vector2.Distance(posA1, posB1); //طرح المسافة السابقة من الحالية سيعطينا //الإشارة الصحيحة للتقريب أو الإبعاد camControl.Zoom((currentDist - prevDist) * zoomingSpeed); } } } آلية عمل هذا البريمج تعتمد على أربعة خطوات رئيسية: التحقق من لمس الشاشة بإصبع واحد.ثم التحقق من تحريك الكاميرا باستخدام الإصبع.ثم التحقق من لمس الشاشة بأصبعين.وأخيرا التأكد من تنفيذ التقريب والإبعاد باستخدام الأصبعين.قراءة مدخلات شاشة اللمس تتم كالآتي: أولا نتعرف على عدد اللمسات على الشاشة عن طريق المتغير Input.touchCount، فإذا كان عدد اللمسات يساوي واحدا، فإن هذا يعني أن اللاعب يضع إصبعا على الشاشة واحتمال أن يقوم بتحريك الكاميرا وارد. نستخدم هنا المتغيرين singleTouch و doubleTouch من أجل تخزين عدد اللمسات التي اكتشفناها. هذه اللمسات تكون مخزنة في المصفوفة Input.touches وهي مصفوفة تحتوي على عناصر من نوع Touch. هذا النوع من المتغيرات يحتوي على معلومات عن كل لمسة على الشاشة. أول هذه المعلومات التي سنتعامل معها هي Touch.phase والتي تمثل المرحلة التي تمر بها اللمسة. فبمجرد أن يضع اللاعب إصبعه على الشاشة ستكون المرحلة هي TouchPhase.Began. اللحظة الأولى للمس الشاشة مهمة جدا، حيث أنها اللحظة التي يجب علينا أن نتحقق من كون اللاعب قد وضع إصبعه على عنصر الخلفية أو الأرضية، وبالتالي نحدد إذا ما كنا سنسمح له بتحريك الكاميرا. فنحن لا نرغب بتحريك الكاميرا إذا كان اللاعب قد وضع إصبعه على المقذوف أو على زر الخروج مثلا. التحقق من كون اللاعب قد وضع يده على عنصر الخلفية أو الأرضية يتم عبر الدّالة ()UpdateSingleTouch، حيث علينا أن نقوم أولا بتحويل موقع الإصبع من إحداثيات الشاشة إلى إحداثيات المشهد تماما كما سبق وفعلنا مع مؤشر الفأرة. بعد ذلك نقوم باستخراج مكوّن التصادم الخاص بهذا العنصر ومن ثم نستخدم بث الأشعة Ray Casting. بث الأشعة طريقة يستخدمها محرك الفيزياء من أجل الكشف عن تقاطع خط مستقيم مع كائن ما في المشهد، وسنستخدمها هنا لنرسم خطا قصيرا جدا من موقع اللمس إلى نقطة شديدة القرب منه، ونرى إن كان هذا الخط يتقاطع مع مكوّن التصادم الذي استخرجناه. يتم تنفيذ بث الأشعة عن طريق الدّالة ()Physics2D.Raycast والتي تأخذ 3 متغيرات: المتغير الأول هو موقع بداية الشعاع، والمتغير الثاني هو الاتجاه الذي سيسير فيه هذا الشعاع، بينما يحدد المتغير الثالث وهو قيمة رقمية أقصى مسافة يمكن أن يقطعها هذا الشعاع. وهنا تلاحظ استخدامنا لمسافة قصيرة جدا، وهي كافية حين يكون موقع البداية موجودا أصلا داخل مكوّن التصادم الذي يتم فحص التصادم معه. القيمة التي ترجعها هذه الدّالة هي من نوع RaycastHit2D، وهي تحتوي على متغير لتخزين مكوّن التصادم الذي اصطدم به الشعاع. بعد ذلك نفحص إذا ما كان المكوّن الذي اصطدم به الشعاع هو نفسه مكوّن التصادم الذي استخرجناه من العنصر الحالي، وإذا تحقق هذا الأمر فإننا نعتمد هذا اللمسة من قبل اللاعب على الخلفية أو الأرضية ونسمح له بالتالي بتحريك الكاميرا عن طريق تغيير قيمة singleTouch إلى true. في حالة كانت اللمسة في مرحلة أخرى مثل TouchPhase.Ended أو TouchPhase.Canceled، فإن هذا يعني أن اللاعب قد رفع إصبعه عن الشاشة، وبالتالي نعيد قيمة singleTouch إلى false. الأمر نفسه سيحدث في حال اكتشفنا أن عدد الأصابع الموجودة على الشاشة Input.touchCount لا يساوي واحدا، بالتالي لن نسمح للاعب في هذه الحالة بتحريك الكاميرا. الدّالة ()UpdateDragging هي المسؤولة عن تحريك الكاميرا، لذا عليها أن تتأكد أولا من قيمة singleTouch وبعد ذلك تقوم بتحريك الكاميرا بالمقدار playerTouch.deltaPosition مضروبا في سرعة الحركة. لاحظ أننا هنا لا نحتاج لتخزين موقع اللمسة السابق حيث أن قيمة الإزاحة تأتينا مباشرة بعكس ما كان عليه الحال حين التعامل مع مؤشر الفأرة. بعد ذلك تقوم الدّالة ()UpdateDoubleTouch بالتحقق من كون اللاعب يضع أصبعين على الشاشة، وفي هذه الحالة تقوم مباشرة بتغيير قيمة doubleTouch إلى true. لاحظ أن اللمس بأصبعين ليس له أي مدلول في اللعبة سوى التقريب والإبعاد بخلاف اللمسة الواحدة التي يمكن أن تستخدم لأكثر من غرض. ولهذا السبب لا نحتاج للتحقق من مواقع الأصبعين بل يكفي وجودهما لمنع أي مدخلات أخرى غير التقريب والإبعاد. أخيرا تقوم الدّالة ()UpdateZooming بالتأكد من وجود أصبعين على الشاشة عبر المتغير doubleTouch وبناء عليها تحسب 4 مواقع وهي كالتالي: posA1: موقع الإصبع الأول خلال الإطار السابق.posA2: موقع الإصبع الأول خلال الإطار الحالي.posB1: موقع الإصبع الثاني خلال الإطار السابق.posB2: موقع الإصبع الثاني خلال الإطار الحالي.لاحظ أننا قمنا بطرح الإزاحة من مواقع الأصابع الحالية حتى نحصل على مواقع الأصابع في الإطار السابق، وذلك لأننا لم نقم بتخزين هذه المواقع من الأساس. بعد ذلك نحسب المسافة بين الأصبعين في الإطار السابق prevDist والإطار الحالي currentDist. تذكر أن الدّالة ()Zoom في البريمج CameraControl تقوم بالتقريب إذا أعطيناها قيمة سالبة وبالإبعاد إذا أعطيناها قيمة موجبة. من أجل ذلك نقوم بطرح المسافة السابقة من المسافة الحالية وضرب الناتج في سرعة التقريب والإبعاد zoomingSpeed. بهذه الطريقة نضمن الحصول على قيمة موجبة إذا حرك اللاعب أصبعيه بعيدا عن بعضهما مما يؤدي للتقريب وقيمة سالبة إذا قرب اللاعب أصبعيه من بعضهما مما يؤدي للإبعاد، وهذا السلوك بطبيعة الحال هو المعتاد عند مستخدمي الهواتف الذكية والأجهزة اللوحية. البريمج الثاني الذي سنتناوله في موضوع استقبال مدخلات شاشة اللمس هو الخاص بإطلاق المقذوفات. تذكر أننا قمنا بإضافة بريمج يسمى LauncherMouseInput على قالب مقلاع إطلاق المقذوفات. البريمج الجديد يسمى LauncherTouchInput وسنقوم بإضافته على نفس القالب من أجل تمكين اللاعب من إطلاق المقذوفات عن طريق اللمس. السرد التالي يوضح هذا البريمج: using UnityEngine; using System.Collections; public class LauncherTouchInput : MonoBehaviour { //مرجع لبريمج إطلاق المقذوفات private Launcher launcher; //تستدعى مرة واحدة عند بداية التشغيل void Start () { //تقوم بتدمير بريمج قراءة مدخلات الفأرة في حال اكتشاف نظام تشغيل الهاتف if (Application.platform == RuntimePlatform.Android) { LauncherMouseInput mouseInput = GetComponent<LauncherMouseInput>(); Destroy(mouseInput); } launcher = GetComponent<Launcher>(); } //تستدعى مرة عند تصيير كل إطار void Update () { UpdateTouchStart(); UpdateDragging(); UpdateRelease(); } //تقوم بالتحقق من كون اللاعب قد وضع اصبعا واحدا //على المقذوف الحالي void UpdateTouchStart() { Projectile currentProj = launcher.currentProjectile; if (currentProj == null) { //لا يوجد ما يمكن فعله return; } if (Input.touchCount == 1) { Touch playerTouch = Input.touches[0]; if (playerTouch.phase == TouchPhase.Began) { //قام اللاعب للتو بلمس الشاشة // تحقق من كون عملية اللمس تمت داخل حدود المقذوف Vector2 touchPos = Camera.main.ScreenToWorldPoint(playerTouch.position); //استخرج مكوّن التصادم الخاص بالمقذوف الحالي Collider2D projectileCollider = currentProj.GetComponent<Collider2D>(); if (projectileCollider.bounds.Contains(touchPos)) { //تمت عملية اللمس داخل حدود المقذوف بالتالي يجب إمساكه launcher.HoldProjectile(); } } } } //تقوم بالتحقق من تحريك اللاعب لإصبعه على الشاشة أثناء إمساك المقذوف void UpdateDragging() { if (Input.touchCount == 1) { Vector2 touchWorldPos = Camera.main.ScreenToWorldPoint(Input.touches[0].position); launcher.DragProjectile(touchWorldPos); } } //تتحقق من رفع اللاعب إصبعه عن الشاشة void UpdateRelease() { if (Input.touchCount == 1) { Touch playerTouch = Input.touches[0]; if (playerTouch.phase == TouchPhase.Ended || playerTouch.phase == TouchPhase.Canceled) { launcher.ReleaseProjectile(); } } } } ينفذ هذا البريمج ثلاث خطوات في كل عملية تحديث: الخطوة الأولى عبر الدّالة ()UpdateTouchStart والتي تتحقق من كون اللاعب قد لمس الشاشة للتو مستخدما إصبعا واحدا. في هذه الحالة تقوم الدّالة بحساب موقع اللمسة في فضاء المشهد ومن ثم فحص ما إذا كان هذا الموقع ضمن حدود مكوّن التصادم الخاص بالمقذوف الحالي المتواجد على مقلاع الإطلاق. إذا كانت هذه اللمسة فعلا داخل حدود المقذوف فهذا يعني أن اللاعب يريد إمساكه، وبالتالي تقوم الدّالة بإمساك المقذوف عبر استدعاء ()HoldProjectile من البريمج Launcher.الخطوة الثانية التي تنفذ عبر ()UpdateDragging تتعلق بوجود إصبع واحد على الشاشة، حيث تقوم بحساب موقع الإصبع في فضاء المشهد وتطلب من البريمج Launcher تحريك المقذوف الحالي إلى هذا الموقع. تذكر أن الأمور الأخرى مثل التأكد من وجود مقذوف أو إذا ما كان ممسوكا أو تم إطلاقه تتم من خلال البريمج Launcher نفسه بالتالي لا نحتاج لفحصها هنا، ولعلك تذكر أننا لم نفحصها أيضا في بريمج قراءة مدخلات الفأرة.أخيرا تقوم الدّالة ()UpdateRelease بالتحقق من كون اللاعب قد رفع إصبعا واحدا عن الشاشة، وذلك من خلال فحص مرحلة اللمس playerTouch.phase إذا ما كانت تساوي Ended أو Canceled وهما الحالتان المتوقعتان حال رفع الإصبع. عند التأكد من هذا الأمر تقوم باستدعاء دالّة إطلاق المقذوف ()ReleaseProjectile.البريمج الأخير الذي يقرأ مدخلات شاشة اللمس هو البريمج الخاص بتنفيذ الهجوم الخاص للمقذوف بعد إطلاقه. هذا الهجوم يتم عبر لمس الشاشة مرة واحدة في أي موقع بعد إطلاق المقذوف. هذا البريمج يسمى SpecialAttackTouchInput ويجب أن تتم إضافته لجميع قوالب المقذوفات التي أنشأناها. هذا البريمج موضح في السرد التالي: using UnityEngine; using System.Collections; public class SpecialAttackTouchInput : MonoBehaviour { //تستدعى مرة واحدة عند بداية التشغيل void Start () { //قم بتدمير بريمج قراءة مدخلات الفأرة في حال اكتشاف نظام تشغيل الهاتف if (Application.platform == RuntimePlatform.Android) { SpecialAttackMouseInput mouseInput = GetComponent<SpecialAttackMouseInput>(); Destroy(mouseInput); } } //تستدعى مرة واحدة عند تصيير كل إطار void Update () { if (Input.touchCount == 1) { Touch playerTouch = Input.touches[0]; if(playerTouch.phase == TouchPhase.Began) { SendMessage("PerformSpecialAttack"); } } } } يمكنك ملاحظة مدى بساطة هذا البريمج، حيث أن كل ما يفعله هو إرسال الرسالة PerformSpecialAttack في حال قام اللاعب بلمس الشاشة مرة واحدة. بهذا تكون اللعبة مكتملة لأجهزة الحاسب والهواتف الذكية، وبقي علينا تصديرها على شكل تطبيق مستقل. تصدير اللعبة بعد إكمالهايوفر محرك Unity إمكانية تصدير الألعاب على مجموعة كبيرة من المنصات، وما يهمنا منها الآن هو منصتا الحاسب الشخصي والهواتف الذكية وتحديدا الأجهزة التي تعمل بنظام Android. تصدير اللعبة يتم عن طريق النافذة التي حددنا منها ترتيب المشاهد وهي: File > Build Settings بالنسبة للتصدير للحواسيب وأجهزة Mac اختر من القائمة اليسرى PC, Max & Linux Standalone لتظهر أمامك الخيارات التالية: أهم هذه الخيارات هو Target Platform والذي تحدد من خلاله نظام التشغيل المستهدف وخيار Architecture والذي يحدد نوع النظام التشغيل سواء كان 32 أو 64 بت. من المهم الانتباه إلى أن الخيار x86_64 يجعل اللعبة تعمل فقط على أنظمة 64 بت حيث أن وجود x86 في الاسم قد يضلل أحيانا فتظن أنه يشمل النظامين. إن كنت تستهدف النظامين 32 و 64 فابق على الخيار الأول x86. بعد ذلك يمكنك الضغط على Build ثم تختار مكان التخزين لتبدأ بعدها عملية التصدير. بالنسبة للتصدير للهواتف الذكية الموضوع أصعب قليلا. سأتحدث هنا بالتفصيل عن طريقة التصدير لمنصة Android فقط لأنني للأسف لا أملك خبرة في التعامل مع أنظمة iOS. قبل التصدير لهذا النظام علينا القيام بتجهيز بعض الأدوات. الخطوة الأولى هو تحميل وتثبيت Android SDK وستحتاج هنا للإصدار الخامس حيث أن الإصدار الخامس من محرك Unity يحتاج لهذه النسخة. يمكنك تحميل المكتبات اللازمة من هذا الرابط https://developer.android.com/sdk/index.html#Other. عند التثبيت يفضل أن تختار موقعا سهلا مثل d:\AndroidSDK. بعد تثبيت Android SDK على جهازك عليك أن تقوم بتنزيل مكتبة واحدة على الأقل عن طريق تشغيل SDK Manager وهو التطبيق المصاحب لـ Android SDK. كل ما تحتاج إليه هنا هو اختيار SDK Platform للإصدار الأخير (حتى كتابة هذه الدروس الإصدار الأخير هو API22 5.1.1). وذلك موضح في الصورة التالة: بعد تنزيل وتثبيت المكتبة علينا أن نخبر Unity عن موقعها وذلك عبر الخيار: Edit > Preferences ومن ثم اختيار External Tools من القائمة اليسرى. بعدها يمكنك تحديد المجلد الذي قمت بتثبيت Android SDK فيه عن طريق الخيار Android SDK Location كما ترى هنا: بما أن اللعبة ستعمل على شاشة الهاتف، يجب علينا أن نجبر النظام على تشغيلها في الوضع الأفقي وليس العمودي. هذا الخيار يمكن ضبطه من خلال القائمة: Edit > Project Settings > Player ومن ثم اختيار رمز نظام Android وفتح مجموعة الإعدادات المسماة Resolution and Presentation. بعدها يجب ضبط Default Orientation على الخيار Landscape Left كما هو موضح في الصورة التالية: الخطوة الأخيرة قبل التصدير هي تحديد معرف الحزمة، وهو عبارة عن اسم على شكل عنوان موقع إنترنت معكوس يبدأ بعنوان موقع الناشر وينتهي باسم المنتج، مثل com.Hsoub.Academy.AngryAnimals. قد تبدو هذه الطريقة في التعريف غريبة بعض الشيء، لكنها موروثة من طريقة تعريف الحزم البرمجية بلغة Java والتي تعتبر اللغة الرئيسية لبرمجة التطبيقات على نظام Android. لا يشترط طبعا أن يكون موقع الإنترنت المستخدم حقيقيا، لكن المهم هو أن تتبع هذا التنسيق في تعريف الحزمة. لإضافة معرّف الحزمة ادخل إلى القائمة: Edit > Project Settings > Player ومن ثم اختر رمز نظام Android من نافذة الخصائص وافتح مجموعة الإعدادات المسماة Other Settings كما هو موضح في الصورة التالية: يمكنك بعدها كتابة معرّف الحزمة في الخانة PlayerSettings.bundleIdentifier كما يمكنك تحديد الإصدار الأدنى الذي يدعمه التطبيق. يستحسن أن تضبط التوافق على الإصدار 4.0 من النظام حيث أنه لا زال شائعا في معظم الأجهزة المتوفرة. بعدها يمكنك أخيرا العودة لشاشة التصدير: File > Build Settings واختيار Android من القائمة اليسرى ومن ثم الضغط على Build واختيار موقع التصدير. سيكون الملف الناتج من نوع APK والذي يمكنك نسخه لجهازك المحمول وتنزيله وتشغيله. قد تضطر لتغيير إعدادات الجهاز حتى يسمح بتنزيل تطبيقات مجهولة المصدر (أي من مصدر غير متجر Google Play) وهذه الإعدادات تختلف من جهاز لآخر. بالنسبة لأجهزة Samsung ستجد هذا الخيار في أعدادات الحماية تحت بند إدارة الجهاز كما هو موضح هنا: تهانينا! لقد قمت ببناء وتصدير لعبة كاملة على هاتفك الذكي أو جهازك اللوحي، ويمكنك الاستمتاع بلعبها ومشاركتها مع أصدقائك.
  2. سنتعلم طريقة تصميم علبة حليب ثلاثية الأبعاد وسنعتمد على أداة 3d box tool والخطوط الوهمية التي تسمى بالأدلة Guide مع بعض الأدوات الأخرى لنحصل في النهاية على هذه النتيجة. أداة الصندوق ثلاثي الأبعاد 3d box tool هناك عدة طرق لنحصل على رسومات ثلاثية الأبعاد في إنكسكيب دون الحاجة فعليا لهذه الأداة، إلا أن هناك الكثير من زوايا النظر التي يصعب تنفيذها بغير هذه الأداة. لو رسمت صندوقا عن طريق الأداة، ستلاحظ أن الصندوق محاط بمجموعة من الخطوط، وما يهمنا معرفة في هذا المقال عن هذه الأداة ما يلي: الخطوط الملوّنة المحيطة بالشكل يمثل كلا منها بعدا ويرمز لكل بعد بالرمز (X, Y, Z) بتحريكنا لهذه الأبعاد الثلاثة يمكن أن نحصل على زوايا وأشكال مختلفة ومتعددة للصندوق. في الشريط العلوي للأداة سنلاحظ خانات للأبعاد الثلاثة لكتابة زاوية كل بعد وبجانب كل خانة علامة التناظر || ، عند تفعيل هذه العلامة فإن الخطين التابعين للبعد لن يلتقيا، وعند إلغائها سنلاحظ نقطة تدعى بنقطة التلاشي حيث يلتقي خطّا البعد عند نقطة معينة. خطوات رسم علبة الحليب ارسم صندوقا بأداة 3d box tool وستلاحظ مجموعة من الخطوط التي تحيط به بتحريكها سنصل للشكل المطلوب. إن لم تكن حصلت على الشكل المبدئي الذي حصلنا عليه فتأكد من كون البعد Y بزاوية 90 وأن خيار التناظر مفعّلا فيه فقط وليس مفعّلا مع البعدين الآخرين، وأن الخطوط الصفراء تقع يمين الصندوق وتمتد من حافته اليمنى، بينما تمتد الخطوط الحمراء من الحافة اليسرى لجهة اليسار. تحريك العقدة التي تمثل نقطة التلاشي أو الالتقاء لكل بُعْد تؤدي لتغيير زاوية الرؤية للصندوق، بينما تحريك العقد المحيطة بالصندوق نفسه اليمنى يمينا أو يسارا أو للأعلى والأسفل يؤدي لتغيير حجم الصندوق (ستحتاج للقليل من التجارب في بداية استخدامك للأداة لذا لا تقلق إذا لم تصل سريعا للشكل المطلوب). لا تجعل الصندوق بطول علبة الحليب التي نرغب برسمها بل يكفي تكوين الجزء العلوي منه والباقي سنكمله بطريقة أخرى لتسهيل عملية الحصول على الشكل المطلوب. إذا وصلنا للزاوية والشكل المناسب للجزء العلوي من علبة الحليب سنحول الصندوق لمسار عن طريقة خيار Object to Path من قائمة المسار Path من الشريط العلوي للقوائم، ثم نفك التجميع عن الصندوق، وبهذا لا يكون بالإمكان التعديل على الشكل بنفس الآلية السابقة إذ ستختفي تلك الخطوط الملوّنة المحيطة بالصندوق. نختار أداة التحرير Node tool بينما ما زالت قطع الصندوق محدّدة، ثم نسحب مؤشر السهم حول العقد السفلية للصندوق لتحديدها. نسحب العقد للأسفل مع الضغط على Ctrl للمحافظة على محاذاتها إلى أن نصل للطول الذي نرغب به للعلبة. نعود لأسهم التحديد ثم من الشريط العلوي نعكس العلبة أفقيا. من الشريط العلوي فعّل خيار Snap cusp Nodes للالتقاط العقد الحادة. من المسطرة العلوية لشاشة الرسم نضع مؤشر الفأرة ثم نسحب منه خطا وهميا يسمى دليل. نسحب الدليل للأسفل إلى أن تلتقط العقدة الموجودة فيه العقدة بين المضلعين وسط العلبة. اضغط على زر Shift لتظهر علامة التدوير عند المرور على الدليل وقم بتدوير الخط إلى أن يلتقط العقدة اليسرى للعلبة، وذلك بتقريب مؤشر الفأرة أثناء التدوير عند الحافة اليسرى للعلبة. كرّر نفس الأمر مع الجهة السفلية اليسرى للصندوق، بسحب دليل جديد وتدويره بما يتناسب مع الحافة السفلية اليسرى للصندوق، ليتشكل لنا دليلان يمتدان من يسار الصندوق ويلتقيان عند نقطة معينة. كرّر الخطوات نفسها مع جهة اليمنى، ولتميز الأدلة الجديدة؛ سنلوّنها بلون مختلف عن طريق الضغط على الدليل مرتين متتاليتين، ومن النافذة المنبثقة نغير اللون للأحمر. لو قمنا بتصغير الشاشة عن طريق زر – من لوحة المفاتيح للاحظنا التقاء الخطوط عند نقطة معينة، ويمكننا اعتبار الجهة اليمنى ممثلة للبعد z والجهة اليسرى ممثلة للبعد x ، وسبب قيامنا بهذا هو مساعدتنا على رسم بقية التفاصيل بسهولة وبأبعاد مناسبة للعلبة. أضف دليلا جديدا واسحب عقدته لنقطة التقاء الخطين الأحمرين، ولوّنه باللون الأخضر لتمييزه، ثم قم بتدويره إلى أعلى الدليل الأحمر العلوي إلى أن تصل للارتفاع الذي ترغب أن يكون عليه الشكل المثلث أو الشبيه بالخيمة أعلى علبة الحليب. استخدم أداة الرسم المنحني Bezier tool لرسم المضلع المشكل لرأس العلبة بالاستعانة بالدليلين الأحمر والأخضر. بأداة الرسم المنحني ارسم مثلثا في طرف الصندوق الأيسر بالاستعانة بالشكل الذي رسمناه توًا. أضف دليلا جديدا فوق الدليل الأخضر السابق مع جعله بارتفاع أقل، لنرسم مضلعا جديدا تمثل القطعة التي تقع أعلى علبة الحليب. يمكنك التعديل على العقد عن طريق أداة التحرير بتحريكها لتنطبق مع العقد التي تقع أسفلها لضبط الشكل. كرّر المثلث مجددا واسحب عقدته العلوية إلى الأسفل واجعلها ملاصقة لضلع المثلث الأصل الأيمن. قم بإخفاء الأدلة مؤقتا عن طريق قائمة العرض View ثم أزل علامة صح عند خيار الأدلة Guide. لوّن العلبة باللون الذي ترغب به مع تغيير الدرجة لكل قطعة للحصول على التأثير المناسب. ستظهر بعض الزوائد للقطع الخلفية للصندوق، والتي تستطيع الوصول لها عن طريق الضغط على زر Alt بتحديد الشكل الذي يتقدمها ثم تحديدها مجددا في الجهة التي تقع فيها إلى أن تصل لها ثم احذفها. أعد الأدلة من قائمة العرض مجددا بوضع علامة صح عندها، وقم بالتخلص من الألة الخضراء التي رسمناها سابقا من أجل رأس العلبة لأننا لم نعد بحاجتها. أضف دليلا جديدا لوّنه باللون الأصفر، وبنفس الطريق السابقة اجعله ينطلق من نقطة التقاطع للأدلة الحمراء وقم بتدويره إلى داخل العلبة حيث المكان الذي ترغب أن تضع فيه الشريط الورقي لبيانات الحليب. أضف دليلا أصفر آخر بنفس الطريقة وقم بتدويره إلى أن تصل للارتفاع الذي ترغب أن يكون عليه الشريط الورقي. من المسطرة اليسرى التي تقع يسار مساحة الرسم اسحب دليلا جديدا وضعه في منتصف العلبة ولوّنه باللون الأخضر لتمييزه. أضف دليلين جديدين وليكونا باللون البنفسجي يمتدان من نقطة الالتقاء x للخصوص الزرقاء مع مراعاة التقاء كل دليل مع الدليل الأصفر الذي يقابله عند نقطة التقائهما مع الدليل الأخضر عند تدويرهما. ارسم بأداة الرسم المنحني مضلعا في الجهة اليمنى مستعينا بالخطوط الوهمية الصفراء اليمنى مع جعل حدوده اليسرى زائدة عن العلبة لترتيبها بطريقة أسهل في الخطوة القادمة. كرّر المضلع الأصل الرمادي الذي رسمنا الشكل الجديد فوقه، ثم حدّده هو والمضلع الجديد، ومن قائمة المسار Path اختر أمر التقاطع Intersection. لوّن الشكل الناتج باللون المناسب، واخترنا هنا درجة من درجات اللون الوردي، ثم أعد نفس الخطوات مع الجهة اليسرى ولوّن القطعة بدرجة أقتم، ثم أخفي الأدلة مجددا. ارسم في رأس العلبة دائرة كاملة الاستدارة بالضغط على Ctrl أثناء الرسم، لتتكون منها فتحة الحليب. اضغط على الدائرة بأسهم التحديد مرتين لتظهر أسهم التدوير، ثم مع الضغط على Ctrl اسحب السهم الأيمن المتوسط خطوة للأسفل، ولونها باللون الوردي القاتم. كرّر الدائرة مجددا ولونها باللون الفاتح وصغّرها قليلا واسحبها لليمين وللأعلى قليلا حيث ارتفاع الغطاء. فعّل من الشريط العلوي خيار التقاط المسار Snap to Path ثم بأداة الرسم المنحني ارسم مضلعا يصل بين الدائرتين من عند الحواف الجانبية التي لا يظهر معها انثناءات الدائرة عند توحيد المضلع مع الدائرة السفلية. في الخطوة الأخيرة نقوم بتوحيد المضلع مع الدائرة السفلية القاتمة لتكتمل غطاء فتحة الحليب. النتيجة النهائية
  3. أرسل لي أحد القراء بريدًا إلكترونيًا يقترح عمل درس تعليمي قائم على رسم أحد الخطوط ويسمى بـ Manrope). العمل المذكور يتضمن مجموعة من الأحرف مع أشكال ثلاثية الأبعاد بارتفاعات مختلفة مجتمعة بكثافة في المشهد. ويتضح أنه قد تم استخدام بعض برمجيات تشكيل الأجسام ثلاثية الأبعاد للحصول على المفهوم الأصلي، ولكنني جربت أدوات 3D الموجودة في Photoshop لرؤية ما إذا يمكن عمل نفس التأثير. اتبع درس اليوم لتعلم كيفية استخدام قدرات Photoshop لعمل التأثيرات ثلاثية الأبعاد بنفسك. العمل الذي سننشئه في هذا الدرس التعليمي يوضح مجموعة من أشكال الأحرف المرتبة بارتفاعات مختلفة، وذلك بمجرد استخدام بعض خيارات ومزايا Photoshop ثلاثية الأبعاد، بعدها أحضر التأثير للحياة مع مفهوم واقعي، ظلال وإضاءة. أنشئ ملفًا جديدًا قياسه حوالي 2000*2000 بكسل. اضبط أول الحروف لتكون عناصر نص فردية باستخدام الخط الذي تختاره. الضغط على زر Uppercase سيسهل تعديل الأحرف المتتالية بدون الحاجة إلى الضغط على Shift لوضع الحرف الأكبر. اختر أداة Move واضغط على Alt ثم اسحب نسخة مكررة من النص إلى أي مساحة فارغة. انقر نقرًا مزدوجًا لتعديل المحتوى وتغيير الحرف. استمر بفعل هذا حتى الإنتهاء من كل الأحرف الأبجدية. رتب الأحرف بإتقان لتكون متقاربة، ويمكن إضافة الأرقام لملئ الفجوات. اجمع كل الأحرف في طبقة واحدة عن طريق تفعيل أعلى طبقة، والضغط على Shift ثم اختيار آخر طبقة. استخدم E+CMD لدمج الطبقات ثم أعد تسميتها ب 'Letters'. ولتحويل هذا العمل إلى ثلاثي الأبعاد، اذهب إلى 3D ‏> New 3D Extrusion من الطبقة المحددة. ثم ستتحول مساحة العمل في Photoshop إلى وضع 3D. في لوحة 3D فعّل الأحرف، ثم في لوحة Properties اجعل قيمة دوران X تصبح 90 تحت قسم Coordinates. فعّل Current View في لوحة 3D، ثم في لوحة Properties اختر Top من لائحة View. استخدم أدوات التصفح في شريط الأدوات الموجود في الأعلى لتعديل مدار وشدة وحجم المنظر لوضع النص في زاوية مناسبة. وبشكلٍ افتراضي، فإن العمل المُنشأ هو منظر نصي، ولكن تحديد خيار Perspective في لوحة Properties ينتج تأثيرًا مماثلًا. حدد الأحرف مرة أخرى في لوحة 3D ثم اذهب إلى قائمة 3D واختر Split Extrusion لتقسيمها إلى أحرف منفردة. انقر على كل حرف حرف بالدور واستخدم رأس السهم الأزرق لأداة 3D لتحريك الأحرف للأعلى أو الأسفل على محور X. حرك كل حرف عشوائيًا لتكون الأحرف بارتفاعات غير منتظمة. وللتأكد بأنه لا يوجد أحرف عائمة، اضغط على Shift وانقر بالفأرة لتحديد كل الأحرف في لوحة 3D، بعدها انقر على زر Move to Ground في قسم Coordinate من لوحة Properties. فعّل Current View مرةً أخرى وأعد ضبط المشهد إذا لزم الأمر لتوسيط المنظر ثلاثي الأبعاد في اللوحة. حدد عنصر Infinite Light من لوحة 3D وحرك المقبض الأصغر للأيقونة الموجودة على الشاشة لإعادة ضبط مكان الضوء. وفي لوحة Properties، زد Softness الخاصة بالظل لتصبح 70٪ تقريبًا. عد إلى لوحة 3D واختر First Front Inflation Material، ثم اضغط على Shift وانقر على Last Back Inflation Material لتحديد كل واحدة بينها. غير لون Specular من لوحة properties إلى اللون الأبيض وخفض قيمة Shine لتصبح 0٪. ولتجنب عمل أي تغيير على طبقة 3D، استخدم E+Shift+CMD لعمل نسخة مدمجة من العمل في طبقة جديدة. النتيجة النهائية هي تركيب ثلاثي الأبعاد لأشكال الأحرف مع تأثيرات حقيقية للظلال والإضاءة: وقد تم ترك هذا العمل ليكون بلونٍ رمادي أساسي، ولكن يمكن استخدام أدوات تعديل الألوان في Photoshop أو التأثيرات السطحية البديلة لتعزيز التأثير. ترجمة - وبتصرف - للمقال How to create a stack of 3D characters in Adobe Photoshop
  4. نكمل في هذا الجزء الأخير باقي خطوات تصميم يد تحكم باستخدام برنامج أدوبي إلستريتور. رابط الجزء الثاني من الدرس. 41. باستخدام الأداة (Rectangle Tool (M نرسم مستطيلا مقاسه: 39x25px بعدها نحذف نقطة الزاوية اليسرى العلوية ثم نسحب النقطة اليسرى السفلية إلى الأعلى مسافة 13px. نحدد الشكل الناتج ثم نتبع المسار التالي: Effect > Stylize > Round Corners ونختار القيمة 6px لـ: Radius ثم نضغط على زر موافق ونختار له اللون R=3, G=3, B=4. 42. نحدد المثلث الدائري الذي تحصلنا عليه ونتبع المسار التالي: Object > Transform > Transform Each ثم نختار نفس القيم الموجودة في الصورة أدناه ونضغط Copy. نقوم بعمل نسخة للشكل الجديد ونسحبها إلى الأعلى مسافة 5px ثم نغير لونها إلى R=35, G=31, B=32. نضاعف الشكل مرة واحدة ونخفي النسخة، بعدها نحدد الشكلين ونطبق خاصية blend بينهما: 43. نضغط على (Ctrl +Alt +3) لإظهار الشكل الذي قمنا بإخفائه ثم نغير لونه إلى R=75, G=74, B=76. بعدها وباستخدام أداة (Pen Tool (P نرسم مسارين منحنيين كما يظهر في الصورة، ثم نحدد المسار الأحمر ونقوم بإلغاء التعبئة اللونية أما قيمة stroke فنحددها بـ: 1pxواللون (R=109, G=110, B=113)، بعدها نطبق النمط Width Profile 1 على الشكل الناتج ثم نجمع كل الأشكال بدءا من الخطوة 41 بالضغط على (Ctrl +G). 44. نضع المجموعتين الجديدتين في مكانهما المخصص كما يظهر في الصورة، بعدها نختار أداة الكتابة (Type Tool (T ثم نضغط على: Window > Type > Character ونحدد نفس القيم التي في الصورة ونكتب الكلمات التي تظهر في الصورة أيضا: تصميم Analog Sticks45. باستخدام الأداة (Ellipse Tool (L نرسم دائرة بالمقاسات: 124x115px ثم نقوم بتدويرها بزاوية 20درجة، بعدها نملأها بالتدرج اللوني الخطي linear gradient كما يظهر في الصورة: 46. نضاعف الشّكل مرتين (Ctrl +C ثم Ctrl +F ثم Ctrl +F) ثم نخفي إحدى النسخ (Ctrl +3)، نحدد النسخة المتبقية ونغير لونها إلى التدرج اللوني linear gradient. نسحب الشكل الناتج مسافة 36px إلى الأسفل و 5px إلى اليمين، ثم نضغط على (Ctrl +Left Square Bracket) لوضعه في الخلف. نحدد الشكلين الجديدين ونطبق الخاصية blend بينهما لدمجهما: 47. نضغط على (Ctrl +Alt +3) لإظهار الشكل الذي قمنا بإخفائه ونغير لونه إلى linear gradient، نحدد الشكل ثم نتبع المسار التالي: Object > Path > Offset Path ونغير قيمة Offset إلى -1px ثم نضغط على OK. ونغير لون الشكل الجديد إلى linear gradient. 48. نضاعف الشكل الذي قمنا بعمله في الخطوة السابقة ونغير لونه إلى linear gradient. ثم نحدد قيمة التأثير Feather بـ: 6px ونخفض قيمة الشفافية Opacity إلى 50%. نقوم بعمل نسخة للشكل الجديد ثم وباستخدام لوحة تحديد المسارات Appearance نقوم بحذف خاصية Feather. نتأكد بأن الشكل الجديد محدد ثم نضغط على: Effect > Texture > Grain ونختار نفس القيم الموضحة في الصورة ونضغط على زر موافق، بعدها نغير خاصية Blending Mode للشكل الجديد إلى Soft Light مع تخفيض قيمة الشفافية إلى 60%. 49. لإضافة بعض التفاصيل نرسم شكلا مثل الذي في الصورة ونملأه بالتدرج اللوني الخطي linear gradient. 50. نحدد الشكل الذي في الصورة الثانية في الخطوة 48 ثم نتبع المسار التالي: Object > Path > Offset Path ونحدد قيمة Offset بـ: -12px ونضغط على OK. نستمر في تحديد الشكل الجديد ثم وباستخدام لوحة Appearance نحذف تأثير Grain. الخطوة التالية هي تغيير خاصية Blending Mode للشكل الجديد إلى Normal وقيمة Opacity إلى 100% ثم نغير اللون إلى radial gradient بعدها نحدد قيمة التأثير Feather بـ: 5px. 51. نحدد الشكل الذي قمنا بعمله في الخطوة السابقة ثم نتبع المسار التالي: Object > Path > Offset Path ونحدد قيمة Offset بـ: -2px ثم نضغط على زر موافق. نقوم بحذف التأثير Feather من الشكل الجديد ونغير لونه إلى R=5, G=5, B=5. 52. نحدد الشكل الجديد ونتبع المسار التالي: Object > Path > Offset Path ثم نحدد قيمة Offset بـ: -4px ونضغط على زر موافق ثم نسحب الشكل الجديد مسافة 1px إلى الأسفل. نضاعف الشكل الذي تحصلنا عليه ثم نقوم بسحب النسخة مسافة 13px إلى الأعلى و 2px إلى اليسار ونغير لونها إلى R=65, G=64, B=66 ثم ننسخ النتيجة التي تحصلنا عليها ونخفيها. بعدها نحدد الدائرتين الجديدتين ونطبق خاصية blend بينهما. 53. نضغط على (Ctrl +Alt +3) لإظهار الدائرة التي قمنا بإخفائها، نقوم بمضاعفتها ونخفي النسخة الجديدة. ثم نحدد الدائرة الأصلية ونسحبها مسافة 4px إلى الأسفل مع تغيير لونها إلى R=28, G=28, B=30 أما قيمة Feather فنحددها بـ 10px. الآن نضغط على (Ctrl +Alt +3) ونُظهر الدائرة. ثم نغير لونها إلى التدرج اللوني الخطي radial gradient، ونحدد قيمة stroke بـ: 2px واللون (R=33, G=32, B=35). ننسخ الشكل الذي تحصلنا عليه ونتبع المسار التالي: Effect > Texture > Texturizer ثم نختار نفس القيم التي تظهر في الصورة ونضغط على زر موافق، أخيرا نقوم بتغيير خاصية Blending Mode إلى Multiply ونخفض قيمة Opacity إلى 20%. 54. سنحاول إضافة بعض اللمسات لجعل الشكل أكثر واقعية، حيث نقوم أولا برسم ثلاث مسارات منحنية باستخدام أداة (Pen Tool (P كما هو موضح في الصورة، ثم نحدد المسار الذي يظهر باللون الأخضر ونلغي تعبئته اللونية أما قيمة stroke فنحددها بـ: 2px ونختار اللون (R=100, G=103, B=110)، بعدها نختار النمط Width Profile 1 للشكل الناتج ونطبق عليه التأثير Gaussian Blur بقيمة: 2px. الآن نحدد بقية المسارات ونلغي التعبئة اللونية أما قيمة stroke فنحددها بـ: 3px واللون (R=128, G=130, B=133) بعدها نطبق النمط Width Profile 1 على الشكل الناتج والتأثير Gaussian Blur بقيمة: 3px. آخر خطوة هي جمع الأشكال الثلاثة الجديدة في طبقة واحدة (Ctrl +G). 55. نحدد الشكل الذي يظهر في الصورة الثالثة والذي قمنا بعمله في الخطوة 53 ونضاعفه مرة واحدة، ثم نضع النسخة في الواجهة، نتأكد من أن الشكل لا يزال محددا ونزيل التأثير Texturizer وفي المقابل نقوم بتغيير خاصية Blending Mode إلى Normal مع تحديد قيمة Opacity بـ: 100%. الآن نحدد الشكل الجديد ونضغط بشكل مستمر على المفتاح Shift ثم نضغط على المجموعة الجديدة التي قمنا بعملها ونتبع المسار التالي: Object > Clipping Mask > Make Ctrl +7 56. نحدد جميع الأشكال بدءا من الخطوة 45 ونجعها في طبقة واحدة (Ctrl + G)، ثم نتبع المسار التالي: (;+View > Guides > Show Guides (Ctrl لإظهار الخط التوجيهي العمودي والذي قمنا بإخفائه في الخطوة 11. الآن نحدد مجموعة الأشكال الجديدة ونضغط على (Reflect Tool (O، نضغط باستمرار على المفتاح Alt ونحدد الخط التوجيهي العمودي. بعدها وفي علبة Reflect التي تظهر لنا نعين القيمة Vertical ونضغط على Copy آخر خطوة هي الضغط على (Ctrl +;) لإخفاء الخط التوجيهي. إضافة تأثير الظل Shadows57. في هذه الخطوة سنقوم بعمل تأثير الظل على يد التحكم لجعلها تظهر بشكل ثلاثي الأبعاد. فنقوم أولا برسم شكل مثل الذي في الصورة وذلك باستخدام أداة القلم (Pen Tool (P ثم نقوم بتعبئته باللون R=0, G=0, B=0 بعدها نطبق عليه التأثير Gaussian Blur بقيمة 5px ونحدد قيمة Opacity بـ: 90% ثم نضعه في الخلف. 58. باستخدام أداة (Pen Tool (P نرسم شكلا آخر كما يظهر في الصورة ثم نملأه باللون R=0, G=0, B=0، بعدها نطبق عليه التأثير Gaussian Blur بقيمة 18px ونحدد قيمة Opacity بـ: 80% ثم نضعه في الخلف. عمل الخلفية59. باستخدام الأداة (Rectangle Tool (R نرسم مستطيلا مقاسه 700x507px ونختار له اللون R=209, G=211, B=212. آخر شيء نقوم بعمله هو وضع يد التحكم التي قمنا بعملها في مكانها المناسب كما يظهر في الصورة الثانية: وبهذا نكون قد أنهينا آخر جزء من درسنا، وهذه هي النتيجة النهائية: ترجمة وبتصرّف للمقال How to Create a Realistic Game Controller in Adobe Illustrator لصاحبه Bao Nguyen.
  5. نبذة مختصرة عن صناعة الألعاب وتطويرها لعل صناعة الألعاب هي إحدى أصعب الصناعات في هذا العصر، وذلك من عدة نواح تبدأ بالتحديات التقنية، مرورا بجمهور صعب الإرضاء ولا يرحم حتى كبريات الشركات إن لم تكن منتجاتها بالمستوى المطلوب، وليس انتهاءا بالمنافسة الشرسة ونسب الفشل العالية وصعوبة تحقيق أرباح تغطي تكاليف الإنتاج المرتفعة. على الجانب الآخر يوجد ميزات لهذه الصناعة تجعل من النجاة فيها أمرا ممكنا، فعلى الجانب التقني مثلا، لا تخلوا الغالبية العظمى من الألعاب من وظائف متشابهة وأنماط متكررة من معالجة البيانات، مما يجعل إعادة استخدام الوحدات البرمجية للألعاب السابقة من أجل إنشاء ألعاب جديدة أمرا ممكنا، وهذا بدوره يساهم في تذليل العقبات التقنية واختصار الوقت والجهد. عندما تتحدث عن صناعة لعبة، فأنت هنا تذكر العملية الكبرى والتي تنطوي على عشرات وربما مئات المهام التي يجب أن تنجزها في مجالات عدة. فصناعة لعبة تعني إنتاجها وتسويقها ونشرها وكل ما يتعلق بهذه العمليات من إجراءات وخطوات إدارية وتقنية وفنية ومالية وقانونية. على أية حال فإن ما يهمنا في سلسلة الدروس هذه هو الجانب التقني وهو تطوير اللعبة، وهي عملية بناء المنتج البرمجي النهائي بكافة مكوّناته. هذه العملية لا تشمل بالضرورة تصميم اللعبة، حيث أن عملية التصميم ذات منظور أوسع وتركز على أمور مثل القصة والسمة العامة للعبة وأشكال المراحل وطبيعة الخصوم، بالإضافة إلى قواعد اللعبة وأهدافها وشروط الفوز والخسارة. بالعودة لعملية تطوير اللعبة، نجد أن العديد من الاختصاصات والمهارات تساهم في هذه العملية، فهناك الرسامون ومصممو النماذج وفنيو التحريك ومهندسو الصوت والمخرج، إضافة – بالطبع – للمبرمجين. هذه النظرة الشاملة مهمة لنعرف أن دور المبرمج في إنتاج اللعبة ليس سوى دورا مكمّلا لأدوار غيره من أعضاء الفريق، ولو أن هذه الصورة بدأت تتغير بظهور المطورين المستقلين Indie Developers والذين يقومون بالعديد من المهام إلى جانب البرمجة. لماذا نستخدم محركات الألعاب؟ لو أردنا الحديث بتفصيل أكبر عن دور المبرمجين في صناعة الألعاب، سنجد أنه حتى على مستوى البرمجة نفسها هناك أدوار عديدة يجب القيام بها: فهناك برمجة الرسومات وهناك أنظم الإدخال وأنظمة استيراد الموارد والذكاء الاصطناعي ومحاكاة الفيزياء وغيرها مثل مكتبات الصوت والأدوات المساعدة. كل هذه المهام يمكن إنجازها على شكل وحدات برمجية قابلة لإعادة الاستخدام كما سبق وذكرت، وبالتالي فهذه الوحدات تشكل معا ما يعرف بمحرك الألعاب Game Engine. باستخدامك للمحرك والمكتبات البرمجية التي يتكون منها، فأنت تختصر على نفسك الجهد اللازم لبناء نظام الإدخال والإخراج والاستيراد ومحاكاة الفيزياء، وحتى جزء من الذكاء الاصطناعي. وما يتبقى عليك هو كتابة منطق لعبتك الخاصة وإبداع ما يميزها عن غيرها من الألعاب. هذه النقطة الأخيرة هي ما ستدور حوله سلسلة الدروس القادمة، وبالرغم من أن المهمة تبدو صغيرة جدا مقارنة بتطوير اللعبة كاملة، إلا أنها على صغرها تحتاج لمجهود معتبر في التصميم والتنفيذ كما سنرى. خطوات سريعة لتبدأ مع محرك Unity إن لم تكن ذا خبرة سابقة بهذا المحرك يمكنك قراءة هذه المقدمة السريعة، كما يمكنك تخطيها إن كنت تعاملت مع هذا المحرك سابقا. لن أطيل شرح هذه الخطوات حيث هناك الكثير من الدروس سواء بالعربية أو الإنجليزية تتناولها، لكنها هنا لنتأكد من أن كل قارئ للسلسلة على نفس الدرجة من المعرفة الأولية قبل البدء. الخطوة الأولى: تحميل وتنصيب المحرك لتنزيل الإصدار الأحدث من المحرك وهو 5 ادخل مباشرة إلى الموقع http://unity3d.com ومن ثم قم بتحميل النسخة المناسبة لنظام التشغيل الذي تستخدمه، علما بأن النسخة المجانية من المحرك ذات إمكانات كبيرة وهي تفي بالغرض بالنسبة لمشروعنا في سلسلة الدروس هذه. الخطوة الثانية: إنشاء المشروع بمجرد تشغيل المحرك بعد تنصيبه ستظهر لك شاشة البداية، قم بالضغط على New Project لتظهر لك شاشة كالتي تراها في الصورة أدناه. كل ما عليك هو اختيار النوع 2D ومن ثم اختيار اسم وموقع المشروع الجديد الذي ستقوم بإنشائه، ومن ثم الضغط على Create Project. الخطوة الثالثة: التعرف على نوافذ البرنامج الرئيسية تهمنا في البداية 4 نوافذ رئيسية في محرك Unity، وفيما يلي ملخص لوظائفها: نافذة المشهد Scene: وهي التي تستخدمها لبناء مشهد اللعبة وإضافة الكائنات المختلفة إليه وتوزيعها في الفضاء ثنائي الأبعاد. تحتوي هذه النافذة مبدئيا على كائن واحد وهو الكاميرا. هرمية المشهد Hierarchy: تحتوي على ترتيب شجري يحوي كافة الكائنات التي تمت إضافتها للمشهد ويساعدك في تنظيم العلاقات بينها، حيث أنه من الممكن أن تضيف كائنات كأبناء لكائنات أخرى بحيث يتأثر الكائن الابن بالكائن الأب كما سنرى. تحتوي هذه النافذة مبدئيا على كائن واحد وهو الكاميرا. مستعرض المشروع Project: يقوم بعرض جميع الملفات الموجودة داخل مجلد المشروع، سواء تلك التي تمت إضافتها للمشهد أم التي لم تُضف. يحتوي المشروع مبدئيا على مجلد واحد يسمى Assets، وسنضيف داخله كافة الملفات والمجلدات الأخرى. نافذة الخصائص Inspector: عند اختيار أي كائن من هرمية المشهد أو نافذة المشهد أو مستعرض المشروع، فإن خصائصه ستظهر في هذه النافذة ويمكنك تغييرها من هناك. استعرضنا في هذا الدرس ما يظهر من واجهة Unity3D للوهلة الأولى، مع مقدمة بسيطة حول صناعة الألعاب، سنشرع في الدروس القادمة في مشروع عملي نتعلم من خلاله كيفية صناعة لعبة كاملة حقيقية. فترقبوا!
  6. هناك أكثر من طريقة لتطبيق تأثير القماش أو ما يسمى في برنامج 3DS MAX بتأثير الملابس Cloth، يوجد مُعدِّل جاهز لتطبيق هذا التأثير كما يوجد طريقة أخرى باستخدام أحد الإضافات في البرنامج وهو MassFX، فهذه الإضافة تُعدّ بديلًا عن Reactor الشهير الذي تم إيقاف العمل به في إصدار 2012 من البرنامج. ولكي نفهم أكثر كيفية تطبيق هذا التأثير، سنقوم بتصميم غطاء قماشي لطاولة، هذا المثال أسهل من تطبيق لباس كامل لشخصية مثالية حيث تحتاج هذه العملية إلى الكثير من العمل والجهد لتحقيقها، أمّا في مثال غطاء الطاولة فالأمر أسهل وأبسط للفهم. سنقوم بتجربة الطريقتين ولكن أولًا افتح برنامج 3DS Studio MAX ثم سنبدأ أولًا برسم الطاولة، وبما أننا نبحث عن البساطة فلن نصمم طاولة مزخرفة أو معقّدة، بل سنرسم طاولة أساسية بسيطة مؤلفة من قاعدة سفلية أرضية وعمود حامل لجسم الطاولة الرئيسي وأخيرًا جسم الطاولة الرئيسي. تصميم الطاولة انقر على زر رسم الأسطوانة Cylinder من لوحة Geometry الموجودة عادة يمين الشاشة (ستكون هناك ما لم تقم أنت بتعديلات على مظهر شاشة البرنامج) ثم انقر على Keyboard Entry حتى تفتح هذه الخيارات ونستطيع إدخال القيم التي نريدها بدون رسم الشكل يدويًّا، ثم أدخل القيمة 20 لنصف القطر والقيمة 5 للارتفاع مع الإبقاء على الاحداثيات على 0 ثم انقر على زر Create وسيتم إنشاء أسطوانة نصف قطرها 20 وارتفاعها 5 تقع في مركز موقع العمل عند النقاط 0 لجميع المحاور. والآن سنرسم العمود الحامل لجسم الطاولة الرئيسي. وحتى نرسم بدقة متناهية سنقوم باستخدام الطريقة السابقة ذاتها، انقر على زر الأسطوانة Cylinder ثم على Keyboard Entry ثم أدخل القيمة 5 للمحور Z وبهذا يتم رسم الأسطوانة الجديدة ابتداء من ارتفاع 5 على المحور الشاقولي لأن الأسطوانة السابقة كان ارتفاعها 5 وسنُبقي بقية المحاور عند 0 للمحافظة على المحاذاة عند مركز الاحداثيات الأفقية ثم ضع القيمة 10 لنصف القطر وأخيرًا ضع القيمة 100 للارتفاع ثم اضغط Create والنتيجة كما في الصورة. ولرسم جسم الطاولة الرئيسي والذي سيوضع عليه الغطاء القماشي، مجدّدًا انقر على Cylinder ثم Keyboard Entry وهذه المرة أدخل القيمة 105 للمحور Z (من المفترض أن طريقة احتساب قيم المحاور أصبحت معلومة) والمحاور الأخرى عند 0 وسنضع القيمة 100 لنصف القطر و5 للارتفاع وأخيرًا Create. أطلق على هذا العنصر اسم “Table” حتى يكون من السهل التعامل معه فيما بعد. لابد من أنك لاحظت أن حواف جسم الطاولة الرئيسي ليست دائرية كما يجب والسبب يعود إلى قلة عدد الجوانب Sides لهذه الأسطوانة ولتعديل ذلك حدّد عنصر الأسطوانة (Table) ثم اذهب إلى لوحة المُعدّلات Modify وهناك ستجد أن عدد جوانب هذه الأسطوانة هو 18 وللحصول على استدارة مثالية وناعمة زِد هذا الرقم إلى 30. ولنضفي بعض الجمالية على جسم الطاولة سنقوم بجعل الحافة العلوية ناعمة ولكن أولًا خفّف عدد Height Segments إلى 3 بدلًا من 5 ثم حدّد هذه الأسطوانة واضغط بالزر الأيمن عليها واختر Convert To > Convert to Editable Poly من القائمة المنبثقة لتحويل هذه الأسطوانة إلى عنصر Poly. والآن انقر على زر Vertex الموجود في لوحة Modify على الجهة اليمنى ثم استخدم المنظور الأمامي Front لتحديد الصفّين العلويين من النقاط في الأسطوانة. اختر أداة تغيير الحجم ومن خلال المنظور من الأعلى Top ضع المؤشر على المحاور حتى يصبح المحورين X وY باللون الأصفر ثم اضغط بزر الفأرة واسحب للداخل قليلًا حتى تصغّر حجم الأجزاء المحدّدة. والآن حدّد الصف الأول من الأعلى فقط من نقاط الأسطوانة ثم صغّر حجمها قليلًا بنفس النسبة التي صغّرنا بها في الخطوة السابقة. سنكتفي بهذا القدر من تصميم الطاولة. طبعًا هناك ملايين الطرق لتصميم طاولات رائعة ومذهلة وبطرق احترافية، ولكننا هنا لسنا في صدد درس تصميم طاولة بطريقة احترافية إنما صممنا الطاولة لتطبيق تأثير القماش عليها وهو محور درسنا اليوم. وأخيرًا سنضع العنصر الذي سيكون الغطاء الذي سيغطي الطاولة. اذهب إلى لوحة Geometry واختر منها العنصر Plane ثم انقر على Keyboard Entry وأدخل القيمة 120 للمحور Z وبقية المحاور 0 وأدخل القيمة 250 للطول والعرض. أطلق على هذا العنصر اسم "Cover". وللحصول على نتائج جيدة يجب أن نزيد من عدد قطاعات الطول والعرض لذلك حدّد هذا الغطاء واذهب إلى لوحة Modify ثم زِد كل من Length Segs وWidth Segs إلى القيمة 25 ثم أضف مُعدل TurboSmooth لزيادة نعومة العنصر. الطريقة الأولى سنقوم أولًا بتجربة الطريقة الأولى التي تعتمد على المُعدِّل Cloth لذلك حدّد عنصر الغطاء واذهب إلى لوحة Modify واختر المُعدّل Cloth ثم انقر على Object Properties لتفتح لك نافذة خيارات العناصر المشاركة في عملية تمثيل تأثير الملابس. ستلاحظ أن العنصر Cover وهو الغطاء موجود في القائمة والآن أضِف عنصر الطاولة Table من زر Add Object، الغطاء هنا سيسقط بفعل الجاذبية نحو الأسفل ولذلك سنقوم بتحديد عنصر الطاولة حتى يسقط الغطاء عليه ويتوقف عنده وإلا فإن الغطاء سيعبر من خلال الطاولة ويسقط وكأن الطاولة غير موجودة، الأمر ذاته ينطبق على ملابس الشخصيات حيث يجب تحديد جسم الشخصية حتى تسقط الملابس عليه وإلا فإن التأثير سيفشل والملابس ستسقط أرضًا وكأن الشخصية غير موجودة. ثم اختر العنصر Cover من القائمة وفعّل الخيار Cloth من اللوحة اليمنى واختر Cotton من قائمة Presets وذلك حتى يحاكي الغطاء قماش القطن، الآن حدّد عنصر Table من القائمة وفعّل الخيار Collision Object ثم انقر OK. ولاختبار التأثير انقر على الزر Simulate وبعد الانتهاء من العمل ستكون النتيجة بهذا الشكل. الطريقة الثانية طبعًا يجب أن نبدأ من عنصر غطاء جديد لم يُطبّق عليه أي تأثير، انقر في مكان فارغ في شريط الأدوات العلوي بالزر الأيمن للفأرة واختر من القائمة MassFX ليظهر شريط أدوات MassFX الذي سنعمل عليه لتطبيق التأثير. حدّد العنصر Table الطاولة ثم انقر مطولًا على رمز الكرة في شريط أدوات MassFX لتنبثق قائمة مؤلفة من ثلاثة خيارات واختر الخيار الأخير Set Selected as Static Rigid Body ليصبح هو العنصر المُؤثّر على الغطاء. حدّد عنصر الغطاء Cover ثم انقر على شكل القميص من شريط أدوات MassFX ليتم تطبيق تأثير الملابس على عنصر الغطاء. أبقِ الغطاء محدّدًا ومن لوحة Modify نجد المعدّل الجديد mCloth، ابحث في خصائصه في الأسفل عن Physical Fabric Properties واضغط على الزر Load واختر بعدها من النافذة التي ستفتح الخيار Cotton ثم اضغط Load ثم عُد إلى نفس الخصائص وفعّل الخيار Use Orhto Bending بدون تغيير أي قيم موجودة. الآن اضغط على الزر Start Simulation من شريط أدوات MassFX والذي يشبه شكل زر التشغيل Play لتبدأ عملية المحاكاة ويتم تطبيق التأثير. الخاتمة هذه خارطة الطريق لتطبيق هذا التأثير، ويوجد العديد من التعديلات التي يمكن أن نطبّقها على هذا التأثير كنوعية القماش ومدى تأثّره بالجاذبية أو بالرياح ويمكن استخدامه لصنع الأغطية والأعلام والملابس و....الخ. ومع وضع اللمسات الأخيرة من الخامات والمواد والاضاءة والموقع المحيط وغيرها من الأمور سنحصل على نتائج مثالية ومذهلة. هذا فيديو يظهر عملية المحاكاة وتطبيق التأثير. وهذه بعض التطبيقات العملية الاحترافية لهذا التأثير.
  7. بعد أن انتهينا من الكائنات والقوالب اللازمة للعبة، سنقوم بإضافة مشهد جديد للمشروع من أجل صنع القائمة الرئيسية، ومن ثم سنقوم بإضافة بعض النوافذ والأزرار التي تسمح للاعب بالتنقل بين اللعبة والقائمة الرئيسية. ملاحظة: يمكن تحميل الملفات المصدرية لكامل هذه السلسلة عبر حساب أكاديمية حسوب على Github، يمكن أيضا تحميل ملف APK لتجريب اللعبة على أجهزة Android. بناء الشاشة الرئيسية والواجهةلإضافة مشهد جديد اضغط Control+N ومن ثم قم بحفظ هذا المشهد باسم MenuScene. آلية التنقل بين المشاهد في محرك Unity تعتمد على رقم كل مشهد في ترتيب بناء اللعبة. هذا الترتيب يمكن الوصول إليه عن طريق القائمة: File > Build Settings النافذة التي ستظهر هي المسؤولة عن ترتيب المراحل في اللعبة وتصديرها. ما يهمنا الآن هو الترتيب. قم بسحب المشهدين MenuScene و GameScene من مستعرض المشروع إلى القائمة Scenes in Build كما ترى في الصورة التالية. من المهم هنا مراعاة الترتيب حيث يأخذ المشهد MenuScene الرقم 0 والمشهد GameScene الرقم 1. بعد إضافة المشاهد قم بإغلاق النافذة حيث سيتم الحفظ تلقائيا. بعد ذلك سنقوم ببناء القائمة الرئيسية للعبة، والتي ستحتوي على زرين هما "ابدأ اللعب" و "خروج". الأول سيعرض للاعب مجموعة من المراحل ليختار أحدها ليلعبها، والثاني سيخرج من البرنامج نهائيا. إضافة لذلك سنضيف نصا على الشاشة وهو اسم اللعبة وليكن "الحيوانات الغاضبة" مثلا. سنكرر هذا النص مرتين بحيث نضع نسخة أمام الأخرى ونصغرها ومن ثم نغير ألوانهما لدرجات مختلفة. هذا سيؤدي لأن يظهر النص الخلفي كأنه ظل. لنر الآن كيف تتم إضافة كائنات واجهة المستخدم في Unity. عناصر واجهة المستخدم في محرك Unity تندرج تحت القائمة: Game Object > UI لنبدأ أولا بصورة خلفية للشاشة الرئيسية. هذه الخلفية تتم إضافتها عن طريق لوح: Game Object > UI > Panel بعد أن تضيف هذا اللوح للمشهد، ستلاحظ أن Unity قد قام بإضافته كإبن لكائن جديد اسمه Canvas، وقام أيضا بإضافة كائن آخر اسمه EventSystem. هذان الكائنان جزء من الآلية المتبعة لبناء واجهة المستخدم، حيث يعتبر Canvas الكائن الجذري لجميع كائنات الواجهة، ويقوم EventSystem بتسهيل عملية استقبال مدخلات اللاعب على عناصر الواجهة بغض النظر عن نوع أداة التحكم التي يستخدمها. ما يهمنا الآن هو الكائن الذي أضفناه نحن وهو Panel والذي ستلاحظ أنه تلقائيا قد ملأ إطار الواجهة كاملا. وأنه يحتوي على مكوّن من نوع Image وهو عبارة عن صورة يتم عرضها على الواجهة. قبل الخوض في خطوات بناء الواجهة لنتعرف معا على الآلية المستخدمة للإبقاء على عناصرها في أماكنها وأحجامها الصحيحة بغض النظر عن قياس الشاشة التي تعرض اللعبة عليها. المكوّن المسؤول عن هذه الآلية هو RectTransform والذي ستراه في كائنات واجهة المستخدم بدلا من المكوّن Transform الموجود في كائنات المشهد الأخرى. هذا المكوّن موضح في الصورة التالية: أكثر ما يعنينا في هذا المكوّن هو متغيرا الحجم Scale على المحورين x و y، إضافة إلى نوع وموقع نقطة الارتكاز لكل عنصر من عناصر واجهة المستخدم. لنتحدث بقليل من التفصيل عن طريقة الارتكاز التي عن طريقها يتم تحديد موقع العنصر على الشاشة ولنطّلع أولا على الصورة التالية التي تمثل الخيارات المتوفرة للارتكاز: أول ما يمكن ملاحظته هو إمكانية تحديد نوع الارتكاز بشكل مختلف أفقيا وعموديا، حيث يمكننا استخدام التمدد stretch والذي يجعل العنصر مربوطا من زواياه الأربع وبالتالي يجب أن تبقى هذه الزوايا دائما في مواقعها بغض النظر عن حجم الشاشة. أما الخيارات الأخرى مثل left ،center ،right أفقيا أو top ،middle ،bottom عموديا، فهي تحدد نقطة ارتكاز العنصر بالنسبة للكائن الأب، فإذا حددت مثلا نقطة الارتكاز بأنها middle center، فإن العنصر سيحافظ على مسافة ثابتة من وسط الكائن الأب بغض النظر عن حجم هذا الأخير وحجم الشاشة. سنستخدم هذا الخيار عند إضافة أزرار القائمة الرئيسية كأبناء لكائن اللوح، وبذلك نضمن وجودها دائما في وسط الشاشة. بالعودة لخلفية القائمة، قم بسحب إحدى صور الخلفية المتوفرة إلى الخانة Source Image لتظهر هذه الصورة في خلفية الشاشة الرئيسية. افتراضيا سيقوم Unity بجعل كائن اللوح شفافا نسبيا مما يظهره بشكل معتم وهذا ما لا نريده. لنقم بإزالة هذه الشفافية عن طريق فتح لوح الألوان بالضغط على المستطيل الأبيض في الخانة Color، ومن ثم تحريك منزلق الشفافية A إلى أقصى اليمين كما ترى هنا: بعد ذلك قم بتغيير اسم الكائن من Panel إلى MainMenu. سنضيف لهذا اللوح ثلاثة أبناء: الأول هو ظل العنوان GameTitleShadow.الثاني والثالث هما الزران "ابدأ اللعب" NewGame و "خروج" Exit.لنبدأ أولا مع ظل العنوان: لماذا أضفت ظل العنوان قبل العنوان نفسه؟ السبب هو أن ترتيب تصيير عناصر واجهة المستخدم يقدّم تصيير الآباء على الأبناء. لذا سنضيف العنوان نفسه GameTitle كابن لظل العنوان GameTitleShadow. بعد ذلك قم بكتابة عنوان اللعبة "الحيوانات الغاضبة" داخل الخانة Text لكل من الظل والابن، ومن ثم غير ألوانهما للأخضر بحيث يبدو الظل أفتح من العنوان نفسه. وأخيرا قم بتصغير العنوان قليلا حتى يظهر الظل من خلاله. (استخدمت خطا يسمى HACEN PROMOTER LT ويمكن تحميله مجانا من الموقع hacen.net). الشكل التالي يوضح الإعدادات الكاملة لنص العنوان وظله: بالنسبة للنص العربي الذي يظهر مقطعا ومن اليسار لليمين: لا تقلق حيال هذا الأمر فالحل موجود وسهل وسنطبقه بعد قليل. أخيرا سيظهر شكل العنوان في الشاشة كما يلي: علينا بعد ذلك أن نقوم بإضافة كائنين من نوع Button أي أزرار، وسنضيفهما بشكل عمودي أحدهما فوق الآخر في منتصف الشاشة. لكن قبل ذلك لنضف بعض المصادر الجديدة ونقوم بإعدادها، وهذه المصادر هي عبارة عن صور ورموز لواجهة المستخدم تم استخراجها من المجموعتين التاليتين: http://www.kenney.nl/assets/ui-packhttp://www.kenney.nl/assets/game-iconsطبعا لن نحتاج لجميع محتويات المجموعتين، لكن سنكتفي بالعناصر الموضحة في الصورة التالية: لنبدأ أولا بإعداد صور الأزرار الستة: الثلاث الزرقاء والثلاث الحمراء. قم باختيار أحد الأزرار من مستعرض المشروع ومن ثم اضغط على الزر Sprite Editor في نافذة الخصائص. ستظهر لك نافذة تحرير الصورة Sprite Editor والتي تمكنك من تقطيع الصورة مستخدما نظام الأجزاء التسعة. هذا النظام يقوم على تقسيم أي صورة نريد استخدامها في واجهة المستخدم إلى 9 مناطق كما هو موضح في الصورة التالية: الهدف من هذا التقسيم هو جعل الصورة قابلة للتمدد أفقيا وعموديا، بحيث تبقى الزوايا دائما بحجمها الأصلي ويتم شد الأجزاء أفقيا وعموديا دون أن يؤثر ذلك سلبا على المظهر. يمكنك من خلال النافذة المذكورة تحريك خطوط التقسيم الخضراء من أجل عزل الزوايا عن بقية الأجزاء التي ستتم عملية شدها أثناء تغيير حجم عنصر الواجهة. ل احظ أن لدينا 3 أزرار من كل لون: الأول مرتفع والثاني عادي والثالث مضغوط للأسفل. الأزرار التي سنضيفها ستعمل كالآتي. في الحالة الافتراضية سنعرض صورة الزر العادي، وحين تمرير الفأرة على الزر سنعرض صورة الزر المرتفع، وحين الضغط عليه سنعرض صورة الزر المنخفض. يمكنك تحقيق هذا السلوك عن طريق ضبط إعدادات المكوّنين Image و Button في كائن الزر وفق القيم التي تراها في الصورة التالية. تذكر أن نقطة الارتكاز للأزرار وللعنوان هي المنتصف أفقيا وعموديا middle center. لاحظ أننا حددنا الصورة الافتراضية للزر عبر المكوّن Image، حيث تلاحظ أن نوع الصورة هو Sliced أي صورة مقسمة إلى 9 أجزاء كما سبق ورأينا. بعدها قمنا بتغيير نوع الانتقال في الزر Transition إلى Sprite Swap بحيث نقوم بتبديل الصورة حين الانتقال بين الحالات. حددنا هنا صورتين أخريين إحداهما لحالة التحديد أو المرور بالفأرة Highlighted Sprite والثانية لحالة الضغط Pressed Sprite. أخيرا ستلاحظ وجود كان ابن لكل زر وهو عبارة عن نص يعرض الكتابة التي نرغب بظهورها على الزر. بالتالي يمكننا استخدام هذه الكائنات للكتابة والحصول في النهاية على النتيجة التالية: حل مشكلة اللغة العربيةمشكلة اللغة العربية في محرك Unity قديمة وقد عانيت معها منذ أول إصدار استخدمته وهو 3.5، وحتى الإصدار الخامس لم تحل هذه المشكلة من قبل الشركة. إلا أن الحل موجود، حيث قمت قبل عدة سنوات بكتابة بريمج يسمى ArabicText، ومبدأ عمله يقوم على عكس ترتيب الأحرف بحيث تصبح من اليمين لليسار كما يفترض، إضافة إلى استبدال رموز الحروف المتقطعة بالمتصلة حسب موقع الحرف في الكلمة. هذا البريمج موجود في المشروع داخل المجلد Assets\Scripts\UI وكل ما عليك هو إضافته لكل كائن من نوع Text (أي العنوان وظل العنوان وكائنات الأبناء النصيّة للأزرار). عند تشغيل اللعبة سيقوم البريمج بعمله في تصحيح النص كما ترى في الصورة التالية. هذا البريمج مجرد أداة مساعدة لا علاقة لها بموضوع الدرس لذا لن أقوم بشرحه هنا، لكن يمكنك الاطلاع عليه في المجلد المذكور إن كنت ترغب بذلك. التفاعل مع عناصر واجهة المستخدمأصبحت القائمة الرئيسية جاهزة الآن، إلا أن ضغطك على الأزرار لن يكون ذا تأثير حيث لا توجد أية أوامر ترتبط بها بعد. ربط الأوامر بالأزرار يتم عن طريق استدعاء داّلة أو أكثر من بريمج محدد عند الضغط على الزر. من أجل ذلك سنقوم بكتابة بريمج لكل أمر من هذه الأوامر. البريمج الأول وهو الأسهل هو برنامج الخروج من اللعبة ExitGameCommand. أمر الخروج يمكن تنفيذه في القائمة الرئيسية وفي مشهد اللعبة على حد سواء، حيث يقوم في الحالة الأولى بإغلاق تطبيق اللعبة نهائيا وفي الثانية بالعودة للقائمة الرئيسية. هذا البريمج موضح في السرد التالي: using UnityEngine; using System.Collections; public class ExitGameCommand : MonoBehaviour { //يتم استدعاؤها مرة واحدة عند بداية التشغيل void Start () { } //يتم استدعاؤها مرة عند تصيير كل إطار void Update () { } //تخرج من اللعبة public void ExitGame() { if (Application.loadedLevel == 0) { //نحن الآن في القائمة الرئيسية، بالتالي أغلق التطبيق نهائيا Application.Quit(); } else if (Application.loadedLevel == 1) { //نحن في مشهد اللعبة، بالتالي عد للقائمة الرئيسية Application.LoadLevel(0); } } }لاحظ أن البريمج يستخدم أوامر مباشرة يتيحها محرك Unity من أجل تحميل المشاهد حسب أرقامها. حيث نعرف المشهد الحالي عن طريق المتغير Application.loadedLevel ونقوم بتحميل المشهد الذي نريد عن طريق الدّالة ()Application.LoadLevel. تذكر أن مشهد القائمة الرئيسية يحمل الرقم 0 ومشهد اللعبة يحمل الرقم 1. أخيرا يمكنك ملاحظة أن الدّالة ()Application.Quit تستخدم لإغلاق التطبيق. الخطوة التالية هي ربط الضغط على الزر "خروج" باستدعاء الدّالة ()ExitGame. الخطوة الأولى هي أن نضيف هذا البريمج إلى المشهد على أي كائن، وليكن كائن الزر نفسه. بعدها نعود للمكوّن Button حيث سنجد في أسفله قائمة بالأوامر التي نريد استدعاءها حين الضغط على هذا الزر وهي مرتبة في القائمة ()OnClick كما في ترى في الصورة التالية. يمكنك إضافة أمر جديد بالضغط على الزر + في أسفل القائمة: عند إضافة أمر جديد للقائمة، عليك تحديد الكائن الذي سينفذ الأمر، ومن ثم تحدد البريمج، وأخيرا تحدد الدّالة داخل هذا البريمج. بما أننا أضفنا البريمج ExitGameCommand على كائن الزر نفسه، علينا أن نسحب الزر "خروج" Exit من الهرمية إلى داخل الخانة الخاصّة بالكائن، ومن ثم نفتح قائمة الأوامر والتي تكون قيمتها الافتراضية No Function حيث نختار البريمج ExitGameCommand ومن ثم الدّالة ()ExitGame كما في الصورة التالية: بالتالي عند الضغط على الزر "خروج" فإن التطبيق سيتم إيقاف تشغيله (ملاحظة: لا يعمل الأمر ()Application.Quit من داخل محرر المحرك، عليك بناء التطبيق وتشغيله منفردا لتجربته). لننتقل الآن للزر الثاني وهو زر بداية اللعب. عند الضغط عليه سيعرض نافذة جديدة تحتوي على المراحل الموجودة بحيث يتسنى للاعب اختيار مرحلة منها. من أجل ذلك علينا أولا بناء نافذة مستقلة تحتوي على أزرار المراحل. مبدئيا سنكتفي بزرين يحملان الأرقام 1 و 2 حيث سيكون لدينا مرحلتان فقط في هذا المثال. إضافة لذلك سيكون هناك زر ثالث يحمل الرمز X يقوم بإغلاق النافذة والعودة للقائمة الرئيسية مرة أخرى. لعمل النافذة المذكورة قم بإضافة لوح جديد Panel واحرص على أن يكون ترتيبه بين أبناء الكائن Canvas تحت اللوح الأول الخاص بالقائمة الرئيسية MainMenu. هذا الترتيب مهم حيث أن الكائنات في أسفل الهرمية تظهر على الشاشة أمام الكائنات التي في الأعلى، وهذا ما نريده: أن تظهر هذه النافذة حين عرضها أمام القائمة الرئيسية. قم بتغيير لون اللوح للأسود مع الإبقاء على الشفافية، ومن ثم غير اسمه إلى LevelSelector وحجمه على المحورين الأفقي والعمودي إلى 0.9. هذا سيجعل شكله يبدو كالآتي (لاحظ أيضا ترتيب العناصر في الهرمية على اليسار). ما يلزمنا الآن هو ترتيب الأزرار داخل هذه النافذة على شكل جدول مكون من صفوف وأعمدة، بحيث تكون هذه الأزرار متساوية في الحجم وبينها مسافات ثابتة. لحسن الحظ فإن Unity يسهل علينا هذه المهمة عن طريق توفير المكوّن GridLayoutGroup. هذا المكوّن يقوم بترتيب العناصر داخل اللوح بالطريقة التي ذكرتها للتو، وهو يحتوي على عدة متغيرات كما ترى في هذه الصورة. انتبه لأن إضافة مكوّن كهذا يلغي تأثير طريقة الارتكاز التي تحدثنا عنها سابقا، حيث يصبح المكوّن هو المسؤول عن المواقع والأحجام الخاصة بالعناصر التي يحتويها. المتغيرات الأربع تحت البند Padding تحدد حجم الهوامش من الجهات الأربعة بالبكسل، وهنا اخترت القيمة 32. بعدها نقوم بتحديد حجم كل عنصر أفقيا وعموديا عن طريق المتغير Cell Size وأخيرا نحدد المسافات بين العناصر وهي هنا 16. باقي المتغيرات يمكن تركها على قيمها الافتراضية. بعد هذا علينا أن نصنع قالبا لزر المرحلة بحيث يمكننا إضافته عدة مرات مع تغيير المرحلة التي سيتم تحميلها بتغير الزر. الزر المذكور شبيه بالأزرار التي أضفناها حتى الآن من حيث آلية العرض بتغيير الصور، لكن الذي سيتغير هو النص حيث سيحمل كل زر رقم المرحلة (1، 2، 3، …) إضافة لتغيير البريمج الذي سيستقبل الأمر. بعد صنع قالب الزر حسب الوصف السابق، سنضيف عليه البريمج LevelButton، وهو موضح في السرد التالي: using UnityEngine; using System.Collections; public class LevelButton : MonoBehaviour { //تستدعى مرة واحدة عند بداية التشغيل void Start () { } //تستدعى مرة عند تصيير كل إطار void Update () { } //تقوم ببدء اللعبة مستخدمة رقم المرحلة المزود public void StartLevel(int levelIndex) { //SelectedLevelخزن رقم المرحلة في الإعدادات في الخانة PlayerPrefs.SetInt("SelectedLevel", levelIndex); //قم بتحميل المشهد رقم 1 وهو مشهد اللعبة Application.LoadLevel(1); } } يعمل هذا البريمج عند استدعاء الدّالة ()StartLevel على تحميل مشهد اللعبة (المشهد رقم 1)، لكن قبل ذلك يقوم بتخزين رقم المرحلة التي يجب تحميلها في إعدادات اللاعب. هذه الإعدادات يتم تخزينها على القرص الصلب أي أنها دائمة وليست في الذاكرة. بالتالي فإن القيمة التي تخزن فيها ستبقى محفوظة حين الانتقال بين مشهدي القائمة واللعبة. يمكن الوصول لإعدادات اللاعب عبر PlayerPrefs والتي تحتوي على دوالّ لتخزين وقراءة بيانات بأنواع مختلفة. هنا مثلا استخدمنا الدّالة ()SetInt والتي تقوم بتخزين عدد صحيح، واخترنا اسما للقيمة التي قمنا بتخزينها وهي SelectedLevel. سنرى لاحقا كيف يمكننا قراءة هذه القيمة وتحميل المرحلة بناء عليها. ما علينا فعله الآن هو إضافة عنصر جديد للقائمة ()OnClick ومن ثم سحب الزر نفسه لخانة الكائن تماما كما فعلنا مع زر الخروج من اللعبة. بعدها سنختار البريمج LevelButton من القائمة ومن ثم نختار الدّالة ()StartLevel. الشيء الجديد الذي ستلاحظه هذه المرة هو وجود خانة لإدخال قيمة المتغير levelIndex، حيث أن هذه الدّالة تأخذ متغيرا بخلاف ()ExitGame التي تعاملنا معها في زر الخروج من اللعبة. لاحظ الصورة التالية: سنقوم بعمل زرين من هذا القالب. أحدهما سيحمل النص 1 والقيمة 0 للدّالة ()StartLevel، والآخر سيحمل النص 2 والقيمة 1 للدّالة ()StartLevel. هذان الزران سنقوم بإضافتهما كأبناء للكائن LevelSelector. بعد إضافة الأزرار بالترتيب الصحيح سيتكفل المكوّن Grid Layout Group بوضع كل منهما في الموقع الصحيح وبالحجم الصحيح. قبل الانتقال للحديث عن الزر الثالث وهو زر إغلاق النافذة، لنقم بكتابة البريمج الذي سيحول هذا اللوح إلى نافذة يمكن فتحها وإغلاقها. هذا البريمج هو UIDialog وهو موضح في السرد التالي: using UnityEngine; using System.Collections; public class UIDialog : MonoBehaviour { //قياس النافذة حين تكون مفتوحة public Vector2 maxSize = Vector2.one; //هل تتمدد النافذة حاليا؟ private bool expanding = false; //هل تتقلص النافذة حاليا؟ private bool shrinking = false; //تستدعى مرة واحدة عند بداية التشغيل void Start () { //أخف النافذة مبدئيا transform.localScale = Vector2.zero; } //تستدعى مرة عند تصيير كل إطار void Update () { //اجلب القياس الحالي للنافذة Vector2 scale = transform.localScale; //احسب القياس الجديد بناء على حالة النافذة if (expanding) { scale = Vector2.Lerp(scale, maxSize, Time.deltaTime * 10); //تحقق من الوصول للمنطقة الميتة if (Vector2.Distance(scale, maxSize) < 0.01f) { scale = maxSize; expanding = false; } } else if (shrinking) { scale = Vector2.Lerp(scale, Vector2.zero, Time.deltaTime * 10); //تحقق من الوصول للمنطقة الميتة if (Vector2.Distance(scale, Vector2.zero) < 0.01f) { scale = Vector2.zero; shrinking = false; } } //قم بتغيير القياس للقيمة الجديدة transform.localScale = scale; } //تقوم بفتح النافذة public void Show() { expanding = true; shrinking = false; } //تقوم بإغلاق النافذة public void Hide() { shrinking = true; expanding = false; } } يعتمد مبدأ عمل هذا البريمج على قيمة المتغيرين expanding و shrinking، حيث يحددان ما إذا كانت النافذة تتقلص إلى أن تصل لمرحلة الإغلاق أو إن كانت تتمدد حتى تصل لمرحلة الفتح. حين فتح النافذة يتم إيصال قياسها لقيمة الحد الأعلى المحددة في maxSize، أما حين الإغلاق يجب أن تصل قيمة القياس لصفر حتى تختفي النافذة تماما. لاحظ أن تمدد وتقلص النافذة يتم بشكل سلس عبر ()Vector2.Lerp والتي تستخدم الاستيفاء الذي شرحناه سابقا. افتراضيا يتم ضبط قياس النافذة على Vector2.zero مما يؤدي لأن تبدأ مختفية (مغلقة)، وسيتم إظهارها (فتحها) حين استدعاء الدّالة ()Show، كما يمكن استدعاء ()Hide لإخفائها (أو إغلاقها) ثانية. بعد إضافة هذا البريمج للكائن LevelSelector ستلاحظ أنه يختفي تلقائيا عند تشغيل اللعبة. بقي علينا أن نظهره حين يضغط اللاعب على "ابدأ اللعب" ونخفيه حين يضغط اللاعب على الزر X الذي سنضيفه لهذه النافذة. لنبدأ بعمل زر إغلاق النافذة مستخدمين الصور الثلاث للزر الأحمر. بعد إضافة هذا الزر سنقوم بحذف مكوّن النص من الكائن الإبن Text ونضيف بدلا منه كائن صورة Image كما هو موضح في الصورة التالية: بعدها سنقوم بسحب الصورة cross والموجودة في مجموعة رسوم واجهة المستخدم في المجلد Assets\Kenney.nl\UI Pack إلى الخانة Source Image مما يجعل الشكل النهائي لنافذة اختيار المرحلة يبدو كالتالي: بالنسبة لزر الإغلاق الأحمر سيكون الكائن الهدف لتنفيذ الأمر هو النافذة LevelSelector بالتالي سنسحبها لعنصر جديد نضيفه للقائمة ()OnClick، ومن ثم سنقوم بتحديد البريمج UIDialog والدّالة ()Hide كأمر يتم تنفيذه حين الضغط على هذا الزر. بعدها سنعود للزر الأول في القائمة الرئيسية وهو "ابدأ اللعب" ونضيف له النافذة LevelSelector كهدف للأمر والبريمج UIDialog أيضا، إلا أن الدّالة هذه المرة ستكون ()Show حيث أن الضغط على هذا الزر سيظهر النافذة. الشكل النهائي للقائمة ()OnClick في هذين الزرين سيبدو كالآتي: لو قمت بتشغيل اللعبة الآن ستلاحظ أن الضغط على "ابدأ اللعب" سيظهر لك نافذة اختيار المراحل، ومن هناك يمكنك الضغط على الزر 1 أو 2 لتحميل المرحلة التي تريدها. بطبيعة الحال لا توجد أي مراحل حاليا، لذا سيأخذك الضغط على هذه الأزرار إلى مشهد اللعبة الفارغ. ما نريد عمله الآن هو إضافة زر في مشهد اللعبة يمكّن اللاعب من العودة للقائمة الرئيسية. كل ما علينا فعله هو إضافة زر صغير في أعلى يمين الشاشة يحمل إشارة X ، وعند الضغط عليه سيظهر للاعب نافذة صغيرة يسأله من خلالها إن كان يريد أن يعود للقائمة الرئيسية. بالنظر لموقع الزر المفترض، علينا مراعاة أن تكون نقطة ارتكازه في أعلى اليمين، وذلك حتى يبقى على مسافة ثابتة من أعلى يمين الشاشة بغض النظر عن حجمها. هذا الزر لا يختلف عن التي أنشأناها سابقا سوى أنه أصغر حجما. سنعود لاحقا لإضافة الأمر الخاص بهذا الزر. الصورة التالية توضح موقعه في الشاشة، ويمكنك ملاحظة نقطة ارتكازه في أعلى اليمين: بعد إضافة هذا الزر سنضيف نافذة حوار جديدة كالتي أضفناها في القائمة الرئيسية لاختيار المراحل، إلا أنها ستكون أصغر حجما وتحتوي على سؤال لتأكيد العودة للقائمة الرئيسية، إضافة لزرين للاختيار بين نعم و لا. الصورة أدناه تمثل الشكل والحجم المفترضين لنافذة كهذه. (لاحظ الهرمية في يسار الصورة لترى مم تتكون هذه النافذة): الزر الذي يحمل علامة ✓ سيعود باللاعب للقائمة الرئيسية، بينما الآخر سيقوم بإغلاق نافذة الحوار هذه مع البقاء في مشهد اللعبة• من أجل العودة للقائمة الرئيسية سنحتاج مرة أخرى للبريمج ExitGameCommand ولكننا سنضيفه هذه المرة على الكائن الجذري للواجهة Canvas حيث سنحتاج لاستدعائه من أكثر من نافذة كما سنرى. بعد إضافة البريمج ستكون الدّالة ()ExitGame المعرفة فيه هي الأمر الذي سينفذ حين الضغط على الزر ✓، بينما سيكون Canvas هو الكائن الهدف حيث أنه من يحمل هذا البريمج. بالتالي سيكون شكل القائمة ()OnClick كما يلي: تذكر أن الدّالة ()ExitGame تعود للقائمة الرئيسية في حال تم استدعاؤها من مشهد اللعبة. بعد ذلك علينا أن نضيف لهذه النافذة الصغيرة البريمج UIDialog بحيث تبدأ مختفية وتظهر حين استدعاء ()Show. بطبيعة الحال سيكون زر الخروج الموجود أعلى يمين الشاشة هو من يستدعي الدّالة ()Show عند الضغط عليه، بينما سيكون زر الإغلاق X الموجود على النافذة نفسها هو من يستدعي لها الدّالة ()Hide. أعتقد أنه إلى هنا أصبحت فكرة ربط الضغط على الزر بكائن معين واستدعاء دالّة من بريمج عليه واضحة، لذا لن أعاود شرحها بالصور وسأكتفي بذكر الارتباطات اللازمة. بهذا تكون القائمة الرئيسية للعبة جاهزة، ويمكننا الانتقال بينها وبين مشهد اللعبة. بقي علينا أن نجهز المراحل وما يتعلق بحالة اللعبة حتى تصبح لعبتنا مكتملة ويمكننا لعبها. إضافة المراحل والتنقل بينهابعد أن أصبحت عناصر بناء المرحلة مكتملة لدينا إضافة للشاشة الرئيسية وبعض عناصر واجهة المستخدم، سنقوم الآن بصنع مرحلتين لتجربة تتابع المراحل إضافة للتنقل بينها وبين الشاشة الرئيسية. يمكنك أن تستخدم أي مقذوفات ترغب بها وأي وحدات بنائية وخصوم. المهم هو أن تتبع بناء هرميا محددا حتى تكون جميع المراحل متوافقة في الشكل. الشكل التالي يوضح مثالا على مرحلة صغيرة ومما تتكون هرمية المرحلة. لاحظ أن المرحلة تتكون من 3 عناصر: القاذف، والعناصر البنائية والوحوش والتي تندرج تحت الكائن الفارغ Elements، وأخيرا المقذوفات والتي تندرج تحت الكائن الفارغ Projectiles. لاحظ أيضا أن جميع العناصر على مستوى أفقي واحد وهو المستوى الذي ستظهر فيه الأرضية. عند بناء المرحلة، راعي أن يكون الكائن الفارغ الأب للمرحلة (Level1 في الصورة السابقة) في منتصف المشهد، وأن يكون أسفل المرحلة على مستوى الأرضية التي ستظهر. بعد بناء المرحلة يجب أن نحولها كاملة إلى قالب واحد كبير، لكن قبل ذلك علينا إضافة بريمج بسيط لكائن المرحلة الجذري. هذا البريمج مهمته تحديد رقم الخلفية التي ستظهر حين تحميل المرحلة ويسمى GameLevel وهو موضح في السرد التالي: using UnityEngine; using System.Collections; public class GameLevel : MonoBehaviour { //صورة الخلفية التي ستظهر عند تحميل المرحلة public int backgroundIndex; //تستدعى مرة واحدة عند بداية التشغيل void Start () { } //يتم استدعاؤها مرة عند تصيير كل إطار void Update () { } }المهم في هذا البريمج هو أن نعرف أي صورة خلفية يجب أن نختار عند تحميل المرحلة، عدا عن ذلك فمحتويات المرحلة كفيلة بالتحكم بحالة اللعبة كما سنرى بعد قليل. بعد تجهيز المراحل على شكل قوالب، سنقوم بعمل بريمج جديد لتخزين هذه القوالب ومن ثم إنشائها حسب الحاجة، أي حسب المرحلة التي يتم تحميلها. هذا البريمج يسمى GameLevelLoader وسنقوم بإضافته للكائن الجذري في المشهد. السرد التالي يوضح هذا البريمج: using UnityEngine; using System.Collections; public class GameLevelLoader : MonoBehaviour { //تقوم بتخزين القوالب الخاصة بجميع المراحل public GameLevel[] allLevels; //العنصر الخاص بالمرحلة المحملة حاليا private int currentLevel = -1; //مرجع لبريمج التحكم بالخلفية private BackgroundManager bgManager; //مرجع لبريمج أمر الخروج من اللعبة ExitGameCommand egc; //يتم استدعاؤها مرة عند بداية التشغيل void Start () { bgManager = GetComponent<BackgroundManager>(); egc = FindObjectOfType<ExitGameCommand>(); } //يتم استدعاءها مرة عند تصيير كل إطار لكن في وقت متأخر void LateUpdate () { if (currentLevel == -1) { //قم بتحميل المرحلة التي تم اختيارها من القائمة الرئيسية //إذا لم تكن هناك أي مرحلة، قم تلقائيا بتحميل المرحلة الأولى int selectedLevel = PlayerPrefs.GetInt("SelectedLevel", 0); LoadLevel(selectedLevel); } } //تقوم بتحميل المرحلة المحددة public void LoadLevel(int index) { //قم بالتأكد من وجود المرحلة المطلوبة في المصفوفة //إن لم تكن موجودة فعد للقائمة الرئيسية if (index < 0 || index >= allLevels.Length) { egc.ExitGame(); return; } //قم بالبحث عن المرحلة المحملة حاليا وتدميرها إن وجدت GameLevel current = FindObjectOfType<GameLevel>(); if (current != null) { Destroy(current.gameObject); } //قم بإنشاء المرحلة الجديدة مستخدما قالبها GameObject newLevelObject = (GameObject)Instantiate(allLevels[index].gameObject); GameLevel newLevelScript = newLevelObject.GetComponent<GameLevel>(); //قم بتحديد الكائن الأب والموقع للقائمة الجديدة newLevelObject.transform.parent = transform; newLevelObject.transform.position = Vector2.zero; //قم بتغيير رقم العنصر الخاص بالمرحلة الحالية currentLevel = index; //قم بتغيير الخلفية للصورة المحددة في المرحلة الجديدة bgManager.ChangeBackground(newLevelScript.backgroundIndex); //قم بإبلاغ البريمجات الأخرى بان هناك مرحلة جديدة تم تحميلها للتو SendMessage("NewLevelLoaded"); } //تقوم بإعادة لعب المرحلة الحالية public void RestartCurrentLevel() { if (currentLevel != -1) { LoadLevel(currentLevel); } } //تقوم بتحميل المرحلة التالية في المصفوفة public void LoadNextLevel() { LoadLevel(currentLevel + 1); } }هذا البريمج يحتوي على متغير عام واحد فقط وهو المصفوفة allLevels التي تحتوي على قوالب جميع مراحل اللعبة. لاحظ أن تحميل المرحلة يتم تأخيره باستخدام الدّالة ()LateUpdate وذلك حتى نضمن أن جميع البريمجات الأخرى قد بدأت العمل ويمكننا الاعتماد عليها مثل البريمج BackgroundManager والذي سنستخدمه لتغيير صورة الخلفية للصورة المحددة في البريمج GameLevel الخاص بالمرحلة الحالية. يبحث البريمج مبدئيا عن متغير مخزن في إعدادات اللاعب ويحمل الاسم SelectedLevel. كما تذكر فإن هذا المتغير يفترض أن يتم تخزينه من قبل البريمج LevelButton والخاص بأزرار المراحل في القائمة الرئيسية. إذا لم يوجد هذا المتغير يتم إرجاع القيمة الافتراضية وهي 0 بالتالي يتم تحميل المرحلة الأولى في المصفوفة. الدّالة ()LoadLevel هي الأساسية في هذا البريمج حيث نعطيها رقم المرحلة التي نرغب بتحميلها من المصفوفة، فإذا لم يكن رقم المرحلة المحددة صالحا ستعود للقائمة الرئيسية للعبة. أما إذا كان الرقم صحيحا فإنها تتأكد من عدم وجود مرحلة محملة حاليا عن طريق البحث عن بريمج من نوع GameLevel، إذا وجدت هذا البريمج فإنها تقوم بتدمير الكائن الذي يحمله، وبما أن الكائن هو جذر عناصر المرحلة جميعها، سيتم تدمير جميع هذه العناصر أيضا، مما يجعل المشهد فارغا وجاهزا لاستقبال المرحلة الجديدة. هذه المرحلة يتم إنشاؤها عن طريق استخراج القالب الموجود في الموقع المحدد index ومن ثم بناء كائن منه. هذا الكائن تتم إضافته كابن للكائن الجذري لمشهد اللعبة كما يتم وضعه في منتصف المشهد. بعدها يتم تحديث قيمة currentLevel إلى المرحلة الجديدة وتغيير الخلفية باستخدام المتغير backgroundIndex الخاص ببريمج المرحلة الجديدة. أخيرا تقوم الدّالة بإرسال الرسالة NewLevelLoaded حتى تخبر البريمجات الأخرى بأن المرحلة الجديدة تم تحميلها. إضافة لذلك لدينا الدّالتان ()RestartCurrentLevel والتي تقوم بإعادة تحميل المرحلة الحالية، و ()LoadNextLevel والتي تقوم بتحميل المرحلة التالية في الترتيب في المصفوفة. حالة اللعبة وشروط الفوز والخسارةبعد أن أصبحت جميع محتويات اللعبة مكتملة بما فيها المراحل، بقي علينا أن نضيف شروط الفوز والخسارة وما يترتب عليها من تغيير على حالة اللعبة. في ألعاب من هذا النوع يفوز اللاعب إذا قام بتدمير جميع الخصوم وهي الوحوش في لعبتنا هذه، ويخسر إذا استنفد جميع ما لديه من مقذوفات دون تدمير الخصوم. تذكر أننا سابقا أضفنا البريمج Enemy لكائنات الوحوش والذي يرسل للكائن الجذري الرسالة EnemyDestroyed حين يتم تدمير الكائن، كما أن بريمج المقلاع Launcher يقوم بإرسال الرسالة ProjectilesConsumed عندما يتم إطلاق كافة المقذوفات التي كانت بحوزة اللاعب. ما يتوجب علينا هو كتابة بريمج يستقبل هاتين الرسالتين وبناء عليهما يقوم بفحص حالة اللعبة والتأكد من فوز أو خسارة اللاعب. هذا البريمج هو GameStateManager وهو موضح في السرد التالي: using UnityEngine; using System.Collections; public class GameStateManager : MonoBehaviour { //متغير لمعرفة ما إذا فاز اللاعب بالمرحلة private bool playerWon; //تستدعى مرة واحدة عند بداية التشغيل void Start () { playerWon = false; } //تستدعى مرة عند تصيير كل إطار void Update () { } //والتي ترسلها EnemyDestroyed تستقبل الرسالة //كائنات الوحوش عند تدميرها void EnemyDestroyed() { //قم بعد الوحوش المتبقية في المشهد Enemy[] enemies = FindObjectsOfType<Enemy>(); if (enemies.Length <= 1) { //تم تدمير جميع الوحوش، أي فاز اللاعب بالمرحلة SendMessage("PlayerWon"); playerWon = true; } } //تقوم باستقبال رسالة استنفاد اللاعب //لجميع المقذوفات التي كانت بحوزته void ProjectilesConsumed() { if (!playerWon) { SendMessage("PlayerLost"); } } //التي تعني NewLevelLoaded تستقبل الرسالة //false إلى playerWon أنه تم تحميل مرحلة جديدة، وبناء عليها تعيد void NewLevelLoaded() { playerWon = false; } }في كل مرة يتم فيها تدمير أحد الوحوش يستقبل هذا البريمج الرسالة EnemyDestroyed ومن ثم يقوم بعد الوحوش المتبقية في المشهد عن طريق البحث عن البريمج Enemy. لاحظ أن وجود بريمج واحد في المشهد يعني أن اللاعب قد فاز فكيف هذا؟ الجواب هو أن تدمير الكائن لا يتم مباشرة عند استدعاء ()Destroy، وإنما يتم تأخيره حتى نهاية الإطار الحالي. لذا فمن المحتمل أن تصل الرسالة ويتم بعدها البحث عن بريمج من نوع Enemy وإيجاده. فإن كان العدد واحدا فهذا يعني أنه الأخير المتبقي في المشهد واستقبال الرسالة يعني أنه تم تدميره. لذا نعرف هنا بأن اللاعب قد فاز في المرحلة ويتم إرسال الرسالة PlayerWon وتغيير قيمة playerWon إلى true. أما استقبال الرسالة ProjectilesConsumed فيعني أن آخر مقذوف أطلقه اللاعب قد انقضت مدة بقائه وتم حذفه من المشهد، وأن القاذف لم يجد أي مقذوفات أخرى. حينها تقوم الدّالة ()ProjectilesConsumed باستقبال الرسالة ومن ثم التأكد من أن اللاعب لم يفز باللعبة حتى الآن – أي لم يدمر جميع الوحوش – وفي هذه الحالة تحكم بخسارة اللاعب عن طريق إرسال الرسالة PlayerLost. السؤال الآن هو ماذا سيحدث عندما يتم إرسال PlayerWon أو PlayerLost؟ الجواب هو أن كل رسالة ستقوم بإظهار نافذة حوار مختلفة. ففي حال فوز اللاعب ستظهر له نافذة تخيره بين إعادة اللعب وبين التقدم للمرحلة التالية واسمها WinDialog، وفي حالة الخسارة تظهر نافذة أخرى تخيره بين إعادة المرحلة والخروج للقائمة الرئيسية واسمها LoseDialog. هاتان النافذتان ستكونان كالنوافذ السابقة عبارة عن كائنات Panel مضاف عليها البريمج UIDialog وتحتوي كل منهما على نص وزرين تماما كنافذة تأكيد العودة للقائمة الرئيسية. بداية لنقم ببناء هاتين النافذتين وتحديد الوظائف الخاصة بأزرارها. لنبدأ مع نافذة الفوز والتي ستبدو بالشكل التالي: المشترك في الزرين الموجودين على النافذة هو أن الهدف لأوامرهما هو الكائن الجذري لمشهد اللعبة SceneRoot وتحديدا بريمج تحميل المراحل GameLevelLoader. أما الفرق فهو أن الزر الأيمن سيقوم باستدعاء الدّالة ()LoadNextLevel عند الضغط عليه مما ينقل اللاعب للمرحلة التالية، بينما الزر الأيسر يستدعي عند الضغط عليه الدّالة ()RestartCurrentLevel مما يؤدي لإعادة تحميل المرحلة الحالية. علاوة على ذلك، يجب أن يقوم كلا هذين الزرين أيضا بإخفاء النافذة حتى يتمكن اللاعب من متابعة اللعب سواء في المرحلة التالية أو الحالية. من أجل ذلك يجب أن نضيف لكل منهما هدفا آخر وهو النافذة نفسها، حيث سيقوم كلاهما باستدعاء الدّالة ()Hide من البريمج UIDialog. لاحظ أن ()OnClick هي عبارة عن قائمة كما ذكرنا سابقا، بالتالي يمكنها أن تستدعي أكثر من أمر من أكثر من كائن وبريمج كما هو مبين في الصورة التالية: النافذة الأخرى وهي التي تظهر في حال الخسارة تبدو بهذا الشكل: الزر الأيمن وهو زر العودة للقائمة الرئيسية سيكون الكائن الهدف بالنسبة له هو الكائن الجذري للواجهة Canvas وتحديدا البريمج ExitGameCommand والدّالة ()ExitGame. أما الزر الأيسر فتماما كما في نافذة الفوز يستدعي الدّالة ()RestartCurrentLevel ويقوم أيضا باستدعاء ()Hide من البريمج UIDialog الموجود على كائن نافذة الخسارة LoseDialog. بقي علينا الآن أن نربط بين الرسائل التي يرسلها GameStateManager وبين ظهور هذه النوافذ. المشكلة التي تواجهنا هنا هي أن النوافذ تقع تحت كائن جذري مختلف عن الكائن الجذري للمشهد، وكل منهما ذو وظيفة محددة ولا يجب أن تتداخل هذه الوظائف كثيرا. من أجل ذلك سنقوم بكتابة بريمج يعمل على استقبال الرسائل من GameStateManager ومن ثم استدعاء دوال من بريمج آخر سنضيفه على Canvas بحيث يشكل هذان البريمجان معا جسر التواصل بين واجهة المستخدم ومنطق اللعبة. لنبدأ مع البريمج الأول الذي سنضيفه على جذر واجهة المستخدم Canvas وهو GameStateDialogs الموضح في السرد التالي: using UnityEngine; using System.Collections; public class GameStateDialogs : MonoBehaviour { //متغير لتخزين نافذة فوز اللاعب public UIDialog winDialog; //متغير لتخزين نافذة خسارة اللاعب public UIDialog loseDialog; //تستدعى مرة واحدة عن بداية التشغيل void Start () { } //تستدعى مرة عند تصيير كل إطار void Update () { } //تعرض نافذة فوز اللاعب public void ShowWinDialog() { winDialog.Show(); } //تعرض نافذة خسارة اللاعب public void ShowLoseDialog() { loseDialog.Show(); } } كل ما يفعله هذا البريمج البسيط هو تخزين نافذتي الفوز والخسارة في مراجع ومن ثم عرضها عند استدعاء الدّالة ()ShowWindDialog أو الدّالة ()ShowLoseDialog. بعد إضافة هذا البريمج للجذر Canvas عليك أن تسحب كلا من نافذة الفوز ونافذة الخسارة لخانة المتغير المناسب لها كما ترى في الصورة التالية: لننتقل الآن للطرف الآخر وهو جذر المشهد SceneRoot والذي سنضيف عليه البريمج GameStateReporter الموضح في السرد التالي: using UnityEngine; using System.Collections; public class GameStateReporter : MonoBehaviour { //مرجع لبريمج عرض نافذتي الفوز والخسارة GameStateDialogs gsDialogs; //تستدعى مرة عند بداية التشغيل void Start () { gsDialogs = FindObjectOfType<GameStateDialogs>(); } //تستدعى مرة عند تصيير كل إطار void Update () { } //تستقبل رسالة فوز اللاعب void PlayerWon() { gsDialogs.ShowWinDialog(); } //تستقبل رسالة عرض اللاعب void PlayerLost() { gsDialogs.ShowLoseDialog(); } }كل ما يفعله هذا البريمج هو استقبال رسائل الفوز والخسارة ومن ثم استدعاء الدّالة التي تعرض النافذة المناسبة من البريمج GameStateDialog. بهذا تكون لعبتنا قد اكتملت على جهاز الحاسب ويمكن تشغيلها ولعب المراحل والفوز والخسارة بها. بقي علينا أن ننقلها للهواتف الذكية وشاشات اللمس، وهي خطوة بسيطة نظرا للطريقة المنظمة التي اتبعناها في استقبال المدخلات.
  8. فى درس اليوم سنقوم بعمل بعض عمليات التكرار الممتعة لتقليد أسلوب عناوين الأفلام الكلاسيكية من أفلام الأبيض والأسود القديمة من فترة الثلاثينات والأربعينات. التأثيرات ثلاثية الأبعاد كانت شائعة الاستخدام في ذلك الوقت، جنبًا إلى جنب مع الإضاءة الرئيسية المنخفضة، لتكرار هذه الجماليات في برنامج الفوتوشوب، سوف تستخدم ميزة الـ 3D الموجودة فى الإصدار CS6 من الفوتوشوب وما بعده، والتي ستولد إضاءة تلقائية وتظليل للنص. يستند العمل الفني الذي سأقوم بإنشائه على عنوان الفيلم الخيالي “The Phantom”. معظم العمل الشاق يتم من خلال وظائف الفوتوشوب ثلاثية الأبعاد، كل المطلوب هو بعض التهيئة للإعدادات لإنتاج التأثيرات ثلاثية الأبعاد وجعل وجه النص مشطوبًا، جنبًا إلى جنب مع الإضاءة والظلال المرتبطة بها. لولا ذلك، كان سيجب تصميم هذه التأثيرات من الصفر، ولكن مزايا الـ3D توفر وسيلة سريعة وسهلة لإنتاج تأثيرات تشبه إضاءة الحياة. ابدأ بإنشاء لوحة بالأبعاد التي تختارها. أنا أعمل مع مستند بحجم 3000×2000 بكسل. قم بتغيير لون الخلفية إلى رمادي داكن، مثل #181818، ثم استخدم اختصار CMD+Backspace لملء طبقة الخلفية. توجه إلى Filter > Noise > Add وقم بتهيئة الإعدادات إلى 5٪، وقم باختيارGaussian و Monochromatic لإضافة سطح محبّب ثقيل إلى خلفية التصميم. توجه إلى قائمة الفلتر Filter menu مجددًا وقم باختيار تصحيح العدسة Lens Correction. تحت علامة التبويب المخصص Custom tab، حرك شريط تمرير Vignette Amount إلى اليسار لتطبيق هالة داكنة حول لوحة الرسم. قم باختيار أداة النص Type tool لوضع عنوان الفيلم الذي اخترته. أنا استخدام خط Buford فى هذا المثال. يتم تصغير الجزء الأول من العنوان ووضعه بالمنتصف، ويمكن أن يتم ذلك دائمًا في عنصر نص واحد، ولكن استخدام طبقات نصية متعددة يسمح بتخطيطات أكثر تعقيدًا والتي قد تتضمن تأثيرًا مشوّهًا. حدد كل طبقة نصية بدورها وانتقل إلى3D > New 3D Extrusion من محدد الطبقة Selected Layer. سيؤدي القيام بذلك إلى تغيير مساحة العمل إلى الوضع ثلاثي الأبعاد وإنشاء نماذج فردية من النص. اضغط مع الاستمرار على مفتاح Shift في لوحة المفاتيح وقم بتحديد كل طبقة من الطبقات ثلاثية الأبعاد في لوحة الطبقات، ثم انتقل إلى3D>Merge 3D Layers. سيجمع هذا بين النماذج المنفصلة في مشهد ثلاثي الأبعاد. بشكل افتراضي، يقف النص ثلاثي الأبعاد في وضع مستقيم ضد الأرضية، ولكن نريد أن يتم وضع النص على ظهره لهذا التأثير لعنوان الفيلم. قم بتحديد كل كائن ثلاثي الأبعاد في اللوحة ثلاثية الأبعاد، ثم انتقل إلى قسم الإحداثيات من لوحة الخصائص Properties panel. قم بتغيير قيمة دوران X إلى 90° درجة. اضغط على قائمة الأيقونة الصغيرة الموجودة في جانب لوحة الخيارات Properties panel، ثم قم باختيار Move Object to Ground Plane. سيحرص هذا الخيار على أن العنصر لا يطفو في فراغ ثلاثي الأبعاد. على الرغم من أنك قمت بتدوير النص ثلاثي الأبعاد، فإن عرض الكاميرا الافتراضي ينظر الآن إلى النماذج من الجانب. قم بتنشيط Scene في اللوحة ثلاثية الأبعاد 3D panel، ثم اختار أداة التدوير ثلاثي الأبعاد في شريط الأدوات العلوي. انقر مع السحب لتدوير المشهد إلى موضع معين بحيث يكون وجه النص مرئيًا، أثناء النظر إلى النص من زاوية طفيفة. حدد كلاً من النماذج النصية ثلاثية الأبعاد من خلال الضغط على مفتاح CMD لإضافتها إلى التحديد، ثم قم بتهيئة Cap options في Properties panel إلى عرض بنسبة 100٪ مع زاوية 45 درجة افتراضيًا. وهذا سيطبق أسلوب “King Kong” المشطوب على وجه النص. في لوحة 3D panel، حدد لانهائية عنصر Infinite Light 1. ستعرض الواجهة أيقونة كبيرة يمكن تدويرها لتغيير اتجاه مصدر الضوء. انقر واسحب الطرف الأصغر من الرسم لتوليد ظل طويل من خلال تسليط الضوء على زاوية حادة. بِاستخدام Infinite Light 1 الذي تم اختياره، قم بتغيير ليونة الظل في لوحة Properties panel لطمس الظلال. إذا كانت زاوية إعدادات الإضاءة الخاصة بك تظلل وجوه النص باللون الأبيض، قم بإغلاق الكثافة داخل هذه الخيارات أيضًا. ارجع مرة أخرى إلى لوحة 3D panel ، تنقل وانقر بين جميع المستويات التي تنتهي بكلمة Material لتسليط الضوء عليها جميعًا. قم بتقليل التألق إلى صفر وقم بتغيير لون الانتشار من الأبيض إلى الرمادي الفاتح من داخل لوحة الخصائص Properties panel. اختر فقط مواد Extrusion Materials لكلا النموذجين في اللوحة ثلاثية الأبعاد 3D panel، ثم قم بتغيير اللون المنتشر لهذه الوجوه إلى نصف رمادي من لوحة الخصائص Properties panel. انقر على رمز التقديم Render أسفل اللوحة ثلاثية الأبعاد لبدء عرض المشهد ثلاثي الأبعاد النهائي مع إضاءة وظلال ذات جودة كاملة. يمكن أن يستغرق بعض الوقت للانتهاء من التقديم الكامل، لذلك أفضّل السماح للمربع الأزرق بعمل عمليتَي مرور، قبل الضغط على مفتاح الهروب Escape. في الواقع، تضيف النتيجة المحبحبة لعملية التقديم غير المكتملة إلى تأثير الفيلم القديم. قم بالرجوع إلى تخطيط الفوتوشوب الافتراضي ضمن Window > Workspace > Essentials menu لإلغاء تحديد الأدوات ثلاثية الأبعاد. قم بإضافة طبقة تعديل المستويات، ثم اضغط على مفتاح ALT أثناء النقر بين طبقة التعديل والطبقة ثلاثية الأبعاد لجعل تأثير التعديل لا ينطبق إلا على النص وليس على الخلفية. قم بضبط الظلال وشرائط الدرجات اللونية النصفية بضع وحدات لتحسين تباين النص ثلاثي الأبعاد. كل ما تبقى لإنهاء عنوان تصميم قديم هو وضع الملمس المحبحب. بنية “free Dust and Scratches” تناسب تمامًا نمط الفيلم الكلاسيكي. قم بلصق، تدوير وموازنة واحدة من الخامات على اللوحة الفنية، ثم قم بتغيير نمط المزج إلى الشاشة Screen وقلل التعتيم ليتناسب. اخترت 15٪ لترك بعض الملمس المُحبّب. النتيجة النهائية تكرر أسلوب عناوين الأفلام القديمة تمامًا مع تأثير نص ثلاثي الأبعاد وقوام محبحب. الأدوات ثلاثية الأبعاد الخاصة بالفوتوشوب قامت بعمل رائع في إنتاج تأثيرات الإضاءة الواقعية مع مظهر الظلال الطبيعية، والتي سيكون من الصعب خلقها يدويًا، وخاصة في المناطق التي يُلقي فيها كل حرف فردي ظلال على الحرف الذي يليه. ترجمة –وبتصرّف- للمقال How To Create a Vintage Film Title Text Effect In Photoshop لصاحبه Chris Spooner.
  9. هذا الدرس لا يعطيك فكرة عن استخدام مزايا 3D الجديدة في الإصدارات الحديثة من برنامج فوتوشوب بل يعلمك كيفية جعل الصور البسيطة نابضة بالحياة وخارجة عن المألوف كخروج العناصر من شاشة تلفاز أو قفز غزال من لوحة فنية ما أو كما في هذا الدرس حيث سيبدو أن الطريق يخرج من شاشة الهاتف المحمول وأن هناك سيارة منطلقة على ذلك الطريق. سنبدأ أولًا بالحصول على صورة الهاتف المحمول. أنا اخترت هذه الصورة لهاتف محمول باليد مفرغة بالكامل وجاهزة (يمكنك الحصول على صورة أفضل غير مفرغة وتقوم بتفريغها بنفسك باستخدام إحدى طرق التفريغ المختلفة). ثم سنحتاج لصورة الطريق. حمّلت هذه الصورة لطريق ملتوٍ في نهايته بشكل يناسب التصميم الذي أعمل عليه. اسحب الصورة إلى داخل مستند الهاتف المحمول المفتوح في الفوتوشوب أو قم بإستيراده إلى داخل المستند عبر Import ثم عدّل بالحجم والموقع حتى تصبح أطراف الطريق السفلية البيضاء ملامسة لأسفل شاشة الهاتف المحمول بشكل شبه دقيق. وللقيام بذلك بسهولة أكبر خفّف مستوى التعتيم Opacity إلى 50% ثم استخدم الاختصار Ctrl+T للقيام بتعديل الحجم والموضع ثم اضغط على مفتاح Enter لتثبيت التعديلات الجديدة. لا تقم بتغيير مستوى التعتيم إلى الحالة الأصلية لأننا لم ننتهِ من العمل على هذه الصورة بعد. انقر بالزر الأيمن للفأرة على طبقة هذه الصورة من لوحة الطبقات واختر Rasterize Layer وذلك لنتمكّن من التعديل المباشر على هذه الطبقة ضمن هذا المستند ولا تكون هذه الطبقة عبارة عن عنصر ذكي. استخدم أداة التحديد المضلع Polygonal Lasso Tool لتحديد الشاشة من الداخل للهاتف المحمول مع استثناء أطراف أصابع اليد وعند الوصول بالتحديد إلى أسفل الشاشة تابع مع أطراف الطريق الخارجية لتحدد من الطريق الجزء الخارج من الهاتف المحمول وعند الانتهاء من التحديد اضغط على الاختصار Shift+Ctrl+I لعكس التحديد ثم انقر على مفتاح Delete لحذف كل ما هو خارج شاشة المحمول والجزء الخارجي من الطريق من صورة الطريق العامة. استخدم الآن أداة الممحاة Eraser مع فرشاة ناعمة لمسح أطراف الطريق الخارجية وجعلها ناعمة مندمجة مع المحيط الذي حولها. أعد تعتيم هذه الطبقة إلى وضعها الطبيعي 100% لتشاهد النتيجة الحالية. سنحتاج الآن إلى صورة السيارة. حمّلت هذه الصورة المجانية لهذه السيارة الرياضية. أهم ما في تجميع الصور في أي تصميم أن تكون اتجاهات الصورة والمناظر مطابقة لطبيعة التصميم الأساسية، فهناك ملايين من صور السيارات على الإنترنت ولكن يجب علينا أن نختار صورة سيارة بزاوية ومنظور مطابق لوضعية الطريق الذي سنضعها عليه. أدرج هذه الصورة ضمن المستند وأيضًا خفّف التعتيم Opacity لنتمكّن، من العمل بسهولة أكبر على الصورة. اتجاه السيارة الحالية مغاير لاتجاه الطريق لذلك حدّد طبقة السيارة ثم اذهب إلى القائمة Edit > Transform > Flip Horizantal وبذلك تم عكس الصورة أفقيًا اضغط Ctrl+T ثم عدّل بحجم وموضع السيارة حتى تصبح مناسبة وكأنها تسير فعليًا على الطريق. استخدم أداة القلم وابدأ بالرسم حول شكل السيارة لتحديدها. أداة القلم تعتبر من أدق الأدوات للتحديد ولكن استخدامها قد يبدو صعبًا للوهلة الأولى للمبتدئين إلا أنه من الواجب تعلّم وإتقان استخدام هذه الأداة لمن أراد فعلًا أن يحترف التصميم. انقر على لوحة Path لإظهار المسار المرسوم بالقلم ثم انقر بالزر الأيمن للفأرة على المسار واختر Make Selection اضغط على الاختصار Ctrl+J لنسخ التحديد إلى طبقة جديدة واحذف طبقة السيارة الكاملة القديمة. اضبط تعتيم صورة السيارة الجديدة إلى 100%. انقر على زر التعديلات Adjustments أسفل لوحة الطبقات واختر من القائمة Curves حتى نستطيع دمج صورة السيارة بطبيعة وألوان المشهد العام للطريق. انقر على الطرف السفلي لطبقة التعديلات هذه مع الاستمرار بالضغط على مفتاح Alt وذلك لجعل تأثيرات هذه التعديلات تطبّق على طبقة السيارة فقط وليس على كامل المستند. الآن ومن نافذة إعدادات هذه التعديلات طبَق التعديلات التالية على الألوان الثلاثة الأساسية الأحمر والأزرق والأخضر. أنشئ طبقة شفافة جديدة وضعها تحت طبقة السيارة ثم استخدم فرشاة ناعمة باللون الأسود وارسم ظلًّا تحت السيارة. خفّف مستوى التعتيم Opacity لهذه الطبقة إلى 80%. غيّر طبقة الخلفية وهي طبقة صورة الهاتف المحمول باليد إلى طبقة عادية عبر النقر بالزر الأيمن للفأرة عليها واختيار Layer from Background. أنشئ طبقة جديدة تحت طبقة الهاتف المحمول ثم قم بتفريغ اللون الأبيض في أرضية طبقة الهاتف (يمكنك بسهولة استخدام أداة التحديد العصا السحرية Magic Wand Tool). لوّن الطبقة الأرضية الجديدة باللون الأبيض بالكامل باستخدام أداة Paint Bucket Tool. حدّد هذه الطبقة وانقر على أيقونة الأنماط للطبقة أسفل لوحة الطبقات. اختر Pattern Overlay. قم بتجهيز الإعدادات كما في الصورة التالية لنمط النقش. النقش الذي اخترته هو نقش أساسي يأتي مع الفوتوشوب وهو باسم Sandpaper. ثم أضف أيضًا نمط التدرج اللوني Gardient Overlay واضبط الإعدادات كما في الصورة التالية وانتبه لجعل Opacity بقيمة 91%. أضف نصًا وهو عبارة عن عنوان هذا الدرس “تأثير ثلاثي الأبعاد على الصور” مع ترك فراغ مكان جملة “ثلاثي الأبعاد”. اختر خطًا عريضً لهذا النص. أضف الأنماط الثلاثة التالية على النص Bevel & Emboss و Color Overlay و Drop Shadow مع تطبيق ما في الصور التوضيحية التالية حمّل صورة 3D ثلاثية الأبعاد هذه وأضفها إلى المستند وعدّل حجمها وموقعها لتكون في موضعها الصحيح ضمن النص. لم أشرح بعض الخطوات بتفاصيل إضافية لأن ذلك سيحتاج إلى أكثر من درس وخصوصًا لجهة التفريغ واستخدام أداة القلم ولذلك يعتبر هذا الدرس للمستوى المتوسط من مستخدمي برنامج الفوتوشوب. مصادر الصور: صورة الهاتف المحمولة محفوظة الحقوق لصالح Freepik صورة الطريق الملتوي على الجبل مجانية من Unsplash صورة السيارة الرياضية مجانية برخصة CC0 من PEXELS
  10. سنتعلّم اليوم كيفية تصميم سجادة صغيرة مع إظهار تفاصيل فراء السجادة باستخدام برنامج 3D Studio MAX والاستعانة بمزايا VRay للحصول على النتيجة المطلوبة. بداية افتح برنامج 3D MAX وأنشئ ملفًا جديدًا وسنقوم بالتأكّد من أن إعدادات مقاسات العمل مضبوطة على وحدة الميليمتر عبر الذهاب للقائمة Customize > Units Setup… ومن خانة Display Unit Scale نختار الخيار Millimeters من Metric. ثم انقر على زر System Unit Setup وضع القيمة 1.0 لجهة 1Unit والوحدة يجب أن تكون Millimeters ثم انقر Ok لكلا النافذتين. وقبل البدء برسم الشكل ثلاثي الأبعاد يجب أن نكون قد حددنا الصورة أو الرسم الذي سيكون شكل السجادة لأننا سنعتمد مقاسات هذه الصورة لرسم الشكل المسطح بذات المقاسات. أنا اخترت هنا هذه الصورة المجانية لسجادة أنيقة وهي بحجم 1400 في 980 بيكسل وهي المقاسات التي سنعتمدها للسجادة ثلاثية الأبعاد. اختر إنشاء الشكل Plane من اللوحة اليمنى لإنشاء جسم مسطّح ثم اضبط المقاسات على 1400 في 980 كما هو حجم الصورة المختارة سلفًا. انقر بالزر الأيمن للفأرة على الشكل المسطح واختر القائمة Convert To > Convert to Editable Poly سنقوم بتطبيق تأثير الفراء على السجادة من إحدى أدوات VRay عبر العودة إلى لوحة Geometry في اللوحة اليمنى للبرنامج والنقر على القائمة المنسدلة لاختيار أدوات VRay. ومع التأكد من أننا نحدد شكل السجادة المسطح الذي أنشأناه للتو نختار من اللوحة اليمنى VRayFur. جرّب تصيير المشهد على وضعه الحالي لرؤية الفراء بشكل مبدئي. تستطيع تمييز لون الفراء الأبيض عن لون الأرضية للجسم المسطح والآن سنقوم بتجهيز المواد التي ستجعل السجادة تظهر بالرسم الظاهر بالصورة التي اخترناها سابقًا. انقر على المفتاح M من لوحة المفاتيح لإظهار لوحة المواد Material. وانقر على Standard ثم ابحث في القوائم التي ستظهر لاحقًا ضمن مجموعة مواد VRay على VRayMtl. انقر على المربع الصغير بجانب Diffuse ثم اختر من القائمة التي ستظهر لاحقًا الخيار Bitmap. ثم انقر على الزر Assign Material To Selection لتطبيق المادة على الجسم المحدّد (يجب أن يكون مجسم السجادة بالإضافة إلى الفراء محدّدة سلفًا). هذا ما ستبدو عليه النتيجة حتى هذه اللحظة. حدد عنصر VRayFur ثم عدّل بقيم العوامل المتغيرة Parameters كما في الصور التالية. وعند التصيير Render بعد هذه المرحلة ستبدو السجادة رائعة كما هو ظاهر. طبعًا يمكننا تعديل طول الشعر (الفرو) من خلال الخيار Length كما في الصورة المتحركة التالية. كما بإمكاننا تعديل مستوى انحناء الشعيرات عبر الخيار Bend كما في الصورة المتحركة التالية. وأمّا خيار Gravity فهو لتحدد مستوى قوة الجاذبية ما سيؤدي إلى تغيير انحناء الشعيرات وأخيرًأ الخيار Per Area من Distribution فهو لأجل تحديد تعداد وتوزيع الشعيرات ما يسمح لنا بزيادة أو تخفيف كثافة الشعيرات والفراء بحسب القيمة المدرجة. تعلمنا في هذا الدرس كيفية التعمل بشكل بسيط وسريع مع عنصر الفراء (الشعر) من VRay وهو ما يمكن القياس عليه للقيام بتصميم أنواع مختلفة من السجاد والمسطحات العشبية وشعر المخلوقات وحتى الإنسان وغيرها.
  11. بعد تعلّم المعلومات الرئيسية عن الفضاء ثلاثي الأبعاد والإضاءة، تعجّلنا في نهاية الدرس السابق لكي نحصل على صورة ثلاثية الأبعاد، إلا أنني سأعود قليلًا إلى الوراء وأشرح كائنات threeJS بالتفصيل قبل إعادة عرض الناتج مجددًا. التفاصيل أنشأنا في نهاية الدرس السابق جسمًا كرويًا نمثّل به لكوكب المريخ: let marsGeo = new THREE.SphereGeometry (500, 32, 32); تدعم مكتبة threeJS أشكالا هندسية مختلفة، من بينها الشكل الكروي الذي يُتحصَّل عليه بالدالة SphereGeometry. نمرّر للدالة في المعطى الأول قيمة نصف قطر الكرة (500)، عدد القطع الأفقية المكونة للكرة (32) وعدد القطع العموديّة (32). يُنشَأ كل جسمٍ افتراضيًا في نقطة المبدأ (‎0, 0, 0)، لذا لا حاجة إلى نقل الجسم. ماذا يحدث لو قلّلنا عدد القطع إلى 4 في كل اتجاه من الكرة؟ الصورة الآتية تعرض أثر اختلاف عدد القطع (من اليسار إلى اليمين: 4 ثم 8 ثم 16 ثم 32 قطعة أفقيًا وشاقوليًا لكل جسم). يمكنك أن تلاحظ أنَّ حافة الجسم تصبح «خشنةً» كلما قلّ عدد القطع؛ ويبدو الجزء الأمامي من الجسم كرويًا بسبب الأضواء والمُظلِّلات (shaders، سأتحدث عن المُظلِّلات بعد قليل). كقاعدة عامة: كلما ازدادت عدد القطع الموجودة في أحد الأجسام كان «أنعم»؛ لكن زيادة عدد القطع له سلبياته، فالعدد الكبير من القطع يؤدي إلى زيادة وقت المعالجة اللازم لإظهار المشهد إضافةً إلى زيادة حجم الذاكرة اللازمة لعرضه. عليك الموازنة بين الأمرين وذلك بتحديد دقة التفاصيل التي تحتاج لها في الجسم؛ فلو كانت الكرة بعيدةً جدًا أو صغيرةً جدًا، فلن تحتاج إلى قطعٍ كثيرة لكي تجعلها تبدو كرويةً، لكن إذا أردتَ إنشاء مشهدٍ يصوِّر الكوكب عن قرب، فعليك زيادة عدد القطع لتضمن أنَّ حواف الكرة ستبقى ناعمةً حتى لو اقتربنا كثيرًا من الكوكب. تركيب «المواد» طبّقنا في آخر مثال مادة Phong ‏(Phong material) إلى الكرة: marsMaterial = new THREE.MeshPhongMaterial( { color: 0xff6600 } ), Phong هي خوارزمية تظليل (Shader algorithm) كتبها أحد باحثي رسوميات الحاسوب الفيتناميين. الغرض من المُظلِّل هو تعريف كيفية تفاعل الضوء مع السطح ثلاثي الأبعاد: وكانت خوارزمية Phong سريعةً وكفاءتها عالية، ومثاليةً لعرض السطوح الناعمة. يجب أن تُدمَج المادة مع كائن ثلاثي الأبعاد في threeJS لإنشاء mesh: marsMesh = new THREE.Mesh(marsGeo, marsMaterial); الناتج المعروض في المثال السابق بسيطٌ جدًا ولا يناسب غرضنا، فنحن نريد إنشاء كوكب، وليس كرةً برتقاليةً لامعة. ولإنشاء هذا الشعور، فعلينا تضمين المزيد من المواد ووضعها على الكرة، وذلك عبر Texture Loader: let loader = new THREE.TextureLoader(); هنالك الكثير من الجوانب التي تتعلق بالمواد المُشكِّلة للجسم، وأبرزها – في حالة كوكب المريخ – هو اللون، لكن سطح كوكب المريخ متنوع جدًا ولا يمكن تمثيله بلونٍ واحد. فالحل هو أخذ إحدى الخرائط التي أنشأتها المكوكات الفضائية واستعمالها على الكرة. استعملتُ في هذا المثال صورًا من Celestia ثم ضبطُها لتكوِّن خريطةً المواد لسطح الكوكب: marsMaterial.map = loader.load(imgLoc+"mars-map.jpg"); ربما تتذكر من أوّل درس في هذه السلسلة أننا عرّفنا المتغير imgLoc الذي يحتوي على مسار تخزين الصور. قياس الخريطة المستعملة مع WebGL على النقيض من عدد القطع التي تُشكِّل الجسم، من المستحسن استخدام خرائط ذات دقة عالية، لأنها تعطي شعورًا بدقة تفاصيل الجسم؛ لكن ذلك يؤدي إلى نفس المشاكل: استخدام ذاكرة أكثر، وتقليل الأداء. أجرتَ WebGL موازنة بين ما سبق عبر وضع شرطين للخرائط المستعملة: يجب أن يكون عرض وارتفاع الخريطة من قوى العدد 2: أي 1 أو 2 أو 4 أو 8 أو 16 أو 32 أو 64 أو 128 أو 256 أو 512 أو 1024 أو 2048 أو 4096 أو 8192 بكسل طولًا أو عرضًا (يمكن أن تختلف الأرقام. فمن الممكن أن تكون الخريطة بعرض 1024 وبارتفاع 512). هنالك حدٌّ أقصى لما تستطيع متصفحات الهاتف استعماله لخرائط الأجسام، وهذا الحد يرتفع مع مرور الوقت (نظام iOS 10 يدعم خريطةً بأبعاد 4096×4096، ويمكنك تجربة مختلف الأجهزة والأنظمة في webglreport.com). سأعيد تحجيم الخريطة التي سأستعملها إلى 4096‎×2048 بكسل: ‎من المهم أن تكون الخريطة سلسة الحواف (seamless): أي عندما توضع على كرة، فلن تكون حدودها واضحةً. العرض لإنتاج أيّ مشهد فعلينا «عرضه» (render)، وذلك باستخدام شفرة ذات خمسة أسطر، على النحو التالي: let renderer = new THREE.WebGLRenderer({antialiasing : true}); marsloc.appendChild(renderer.domElement); function render(){ renderer.setSize(window.innerWidth, window.innerHeight); renderer.clear(); renderer.render(scene, camera); } استعملنا الخيار antialiasing لتنعيم شكل كوكب المريخ عند تعريف المتغير renderer (الذي يملك خياراتٍ كثيرة أخرى). المتغير marsLoc هو العنصر الذي سيحتوي على مشهد WebGL والذي أنشأناه في الجزء الأول، حيث أضفنا renderer إليه. أما داخل الدالة render فكانت أبعاد المشهد مساويةً لأبعاد نافذة المتصفح؛ ثم مسحنا كل ما كان موجودًا في لوح الرسم، ثم عرضنا المشهد باستخدام الكاميرا التي عرَّفناها سابقًا. ستلاحظ الآن أنَّ النتيجة تبدو مسطحةً ولامعةً، وثابتةً في الفضاء، وغير متجاوبة؛ وسنتخذ التدابير اللازمة في الدرس القادم من هذه السلسلة لحلّ تلك المشاكل. ترجمة –وبتصرّف– للمقال A WebGL Tour of the Solar System: Mars, Part ThreeلصاحبهDudley Storey
  12. شرحنا في أوّل جزء من هذه السلسلة أساسيات استخدام إطار عمل threeJS، بما في ذلك ضبط إعدادات الكاميرا ودمج مشهد WebGL مع محتويات صفحة الوِب. أما في هذا الدرس فسنُموضع الكاميرا في الفضاء ثلاثي الأبعاد ونجعلها تُشير إلى كائن ونُضيف إضاءةً إلى المشهد. ولكن قبل فعل أيّ مما سبق، علينا أن نفهم طبيعة الفضاء ثلاثي الأبعاد. ملاحظة: هذا الدرس يكمل من حيث انتهى الدرس السابق، لذا عليك أن تفهمه وتحصل على شِفرته قبل الاستمرار بقراءة هذا الدرس. التنقل في الفضاء ثلاثي الأبعاد أتوقع أنَّك تعرف محاور الإحداثيات من دراستك الثانوية: يُرسَم المحور x أفقيًا، والمحور y شاقوليًا (عموديّا). وبضبط الوحدات التي تُمثلها تلك المحاور، فسنتمكن من تحديد مكان أيّ عنصرٍ في الجزء الموجب من الفضاء ثنائي الأبعاد. أما إذا أردنا تضمين الأماكن السالبة فعلينا تمديد المحاور إلى اليسار وإلى الأسفل: نقطة تقاطع المحورين هي النقطة ‎0, 0 وتسمى «المبدأ» (Origin). أما لتحديد المواقع في فضاء ثلاثي الأبعاد، فعلينا إضافة محور ثالث عمودي على المحورين السابقين ويتجه بعيدًا عن المشاهد. نستطيع تخيّل المحور z أيضًا بإمالة المنظور قليلًا كما في الرسم التوضيحي الآتي: لاحظ أنَّ الجزء السالب من المحور z يتجه مبتعدًا عنّا، أما الجزء الموجب فهو أقرب. يمكن الآن تحديد مكان أيّة نقطة في الفضاء بتقاطع ثلاثة قيم x وy وz. ملاحظة: لاحظ عدم أهمية ما الذي تمثِّله تلك الأرقام، فقد تكون بوحدة المليمتر أو القدم أو السنوات الضوئية! المهم هو كيف تتفاعل تلك الأرقام مع بعضها: فالقيمة 2x هي ضعف المسافة x. تتواجد الكاميرات التي أنشأناها في الدرس السابق في مبدأ الإحداثيات افتراضيًا، لكننا نريد وضعها بعيدًا عن المنتصف: camera.position.set(1380, 0, 0); المتغير scene يحتوي على الكائنات التي سنُنشِئها، والذي يُمكن تهيئته بالسطر الآتي: scene = new THREE.Scene(); يوضع المشهد تلقائيًا في مبدأ الإحداثيات (‎0, 0, 0) وسنضع فيه أيضًا العنصر الرئيسي الذي سنُنشِئه (كوكب المريخ). لذا نريد أن نوجِّه الكاميرا إلى تلك النقطة: camera.lookAt(scene.position); ملاحظة: يمكن وضع الكاميرا – في هذا المثال– على المحور z أيضًا لكن يجب أن تبعد بنفس القيمة (1380)، ويمكن أيضًا وضعها في الجزء السالب من المحور x أوz؛ وذلك لأنَّ الكاميرا ستكون موجهةً نحو المبدأ دومًا. لنشغِّل الأضواء المشهد الذي أنشأناه هو فضاءٌ مظلمٌ لا متناهٍ، مما يعني أنَّ أي كائن سيوضع فيه سيكون غيرَ مرئي، لعدم وجود مصدر للضوء. لنضف واحدًا: light = new THREE.PointLight(0xFFFFFF, 2, 5000); light.position.set(2000, 2000, 1500); scene.add(light); ملاحظة: لاحظ أنَّك لن ترى شيئًا في هذه المرحلة، ليس لأنَّ مصدر الضوء يكون مخفيًّا افتراضيًا، وإنما لأننا لم نعرض المشهد بعد. تتوافر ستة أنواع من الأضواء في إطار عمل threeJS: ضوء نقطي (PointLight): وهو الضوء الذي يكون له موضعٌ معيّن، ويُشعّ الضوء في كل الاتجاهات بقدر متساوٍ، مما يجعل هذا النوع من الإضاءة مثاليًا لمحاكاة الضوء الآتي من النجوم أو المصابيح. ضوء ذو اتجاه (DirectionalLight): وهو الضوء الذي له اتجاهٌ معيّن، لكنه ليس حزمةً ضوئيةً (Beam، على النقيض من «بقعة الضوء» Spotlight أدناه)، وهو مفيدٌ لمحاكاة طريقة رؤية أشعة الشمس من سطح الأرض. بقعة ضوء (SpotLight): الضوء الذي يُشير إلى اتجاهٍ معيّن يشبه حزمةً ضوئيةً واسعةً مَثَلُهُ كَمَثَلِ الأضواء المسرحية. الضوء الآتي من منطقة مضيئة مستطيلة (RectAreaLight) وهو مفيدٌ لمحاكاة الضوء المار عبر النافذة أو من لوحٍ من الفلورسنت. الإضاءة المحيطية (AmbientLight): هذا ضوءٌ عامٌ كالذي تراه آتيًا من جميع الاتجاهات. تخيل ليلةً غيرَ مقمرةٍ فيها ضوء محيطي. للإضاءة المحيطية القدرة على إضفاء لونٍ معيّن على المشهد: فكلما كان الضوء المحيطي فاتحًا كلما ظهر المشهد بلونٍ باهت. الإضاءة نصف الكروية (HemisphereLight): يدعى هذا النوع من الإضاءة في برامج التصميم ثلاثي الأبعاد بالمصطلح «Skylight». وهي تحاكي الضوء القادم من الأعلى (السماء) إلى الأسفل (أيّ نوع من الانعكاس أو الضوء من الأرض). يمكنك تخيّل هذا النوع من الإضاءة كما لو أنَّ الإضاءة المحيطية مقسومة إلى نصفين. سأشرح أنواع الإضاءة السابقة تفصيليًا في مقالاتٍ قادمة، لكن علينا أن نركِّز الآن على الضوء النقطي والذي يأخذ ثلاثة وسائط: اللون (عبر قيمة بالنظام الست عشري، يسبقها ‎0x)، والشدة (Intensity)، والنقطة التي سيبدأ الضوء بالانتشار منها. وكذلك الأمر فيما يتعلق بالظلال، فجميع الأضواء تلقي بظلالٍ في الواقع، أما في الرسومات ثلاثية الأبعاد فقد يُسبِّب ذلك مشاكل، لذا يكون إلقاء الظلال الناتجة من الضوء اختياريًا. ربما تُفضِّل التجربة مع شدة الضوء لترى تأثيرها، حيث ستجد أنَّ الشدة العالية للضوء ستجعل الألوان قويةً جدًا، مثل استخدام ضوء فلاش قوي جدًا بالقرب من الجسم الذي تصوِّره بكاميرتك العادية. نموذج أولي بسيط يؤسفني أن نخوض في كل المعلومات السابقة دون أن تتاح لنا فرصةٌ لرؤية أيّة أشكال في صفحتنا، لذا أنشأتُ نسخةً مبسطةً من الناتج وعرضتها لك. الشيفرة الآتية تضم جميع التعليمات البرمجية التي كتبناها منذ بداية هذه السلسلة وحتى هذه المرحلة (دون الشفرة المسؤولة عن تضمين إطار threeJS): let camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000), light = new THREE.PointLight(0xFFFFFF, 2, 5000), scene = new THREE.Scene(); light.position.set(2000, 2000, 1500); camera.position.set(1500, 0, 0); camera.lookAt(scene.position); scene.add(light); let marsGeo = new THREE.SphereGeometry (500, 32, 32), marsMaterial = new THREE.MeshPhongMaterial( { color: 0xff6600 } ), marsMesh = new THREE.Mesh(marsGeo, marsMaterial); scene.add(marsMesh); let renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight) marsloc.appendChild(renderer.domElement); renderer.render(scene, camera); بوضع الشيفرة السابقة في صفحة الويب التي أنشأناها في الدرس السابق، فسترى النتيجة الآتية؛ لكن ما يزال علينا إضافة الكثير من الأمور إليها، وشرحها بالتفصيل، وهذا ما سنفعله في الدرس القادم. ترجمة –وبتصرّف– للمقال A WebGL Tour of the Solar System: Mars, Part Two لصاحبه Dudley Storey.
  13. كانت هنالك الكثير من المحاولات الباكرة لابتكار تقنية لإنشاء رسوميات ثلاثية الأبعاد 3D تفاعلية في صفحات الوِب، بما فيها VRML وFlash، لكن لم يظهر معيارٌ متكاملٌ حتى عام 2013 ألا وهو WebGL المبني على OpenGL ES 2.0، لذا أصبح بإمكاننا تضمين رسوميات 3D تفاعلية في صفحات الوِب دون الحاجة إلى أيّة إضافات أو ملحقات للمتصفح. ما هي تقنية WebGL؟ تسمح تقنية WebGL بكتابة رسوميات 3D في صفحات الويب باستخدام JavaScript عبر العنصر <canvas>، لكن تقنية WebGL لا تُنشِئ «عناصر» على الصفحة، إذ تتعامل مباشرةً مع البكسلات؛ وبالتالي نقول عن تقنية WebGL أنّها تقنيةٌ منخفضة المستوى: حيث توفِّر تحكمًا دقيقًا بالفضاء ثلاثي الأبعاد. وعلى النقيض من أغلبية تطبيقات 3D، لا تتضمن WebGL «مشاهد» (Scenes) أو «كائنات» (Objects) أو «نماذج» (Models). وهذا ما يجعلها تقنيةً قويةً جدًا، لكن في الوقت نفسه تُصعِّب عملية التعلم بالنسبة للمطورين، ولا يمكن إخراج النتائج بواسطتها بسرعة. صحيحٌ أنَّ من الممكن تقنيّا كتابة شِفرات WebGL عبر JavaScript مباشرة، لكن أغلبية المطورين يستعملون إطار عمل Framework، وأشهر إطار عمل لتقنية WebGL هو threeJS، لكن هنالك خياراتٌ أخرى عداه. الحاجة إلى إطار عمل أنصح دومًا بالابتعاد عن أطر العمل: فأنا أعتقد أنَّ المطورين سيتعلمون أمورًا تفيدهم في المستقبل إذا تمكنوا من فهم الأساسيات التي تُبنَى عليها تقنيةٌ ما، بدلًا من سَلك «طرق مختصرة». لكنّ الرسم ثلاثي الأبعاد موضوعٌ معقدٌ جدًا، ومحاولة بناء خبرة عملية باستخدام WebGL إضافةً إلى تعلم تقنيات الوِب الأخرى أمرٌ صعبٌ للكثيرين، وتعلّم أساسيات WebGL يعني إضاعة الكثير من الوقت في التعلم دون القدرة على إنشاء أيّة رسومات ولو كانت بسيطةً. لهذا السبب، سنستعمل في شرحنا لهذه التقنية إطار threeJS، ولا أفترض عند كتابتي لهذه السلسلة أنَّ القارئ على دراية بمبادئ الرسم ثلاثي الأبعاد، لكن يجب أن يكون ذا درايةٍ جيدة بتقنيات HTML وCSS وJavaScript. سنستخدم في هذه السلسلة آخر إصدار متوافر من إطار threeJS. ما الذي يجعل هذه السلسلة مختلفةً عن غيرها أغلبية الدروس التعليمية التي تتحدث عن threeJS والمتوافرة على الوِب هي دروسٌ ليست بالمستوى المطلوب، حيث لا تعمل الأمثلة الحية لعدم تحديث الشفرة منذ فترةٍ طويلةٍ (تأتي التحديثات والتحسينات على إطار عمل threeJS بين الحين والآخر)، وهنالك خطواتٌ كاملةٌ غيرُ مشروحةٍ. لذا سأبذل جهدي لتفادي ذلك في هذه السلسلة، حيث سأضع المعلومات بتسلسلٍ منطقيٍ شارحا باستفاضة، مستعملًا أمثلةً عمليةً مسليةً ألا وهي نمذجة الكواكب الموجودة في نظامنا الشمسي كرسومات 3D. بناء كوكب المريخ باستخدام WebGL بعد أن تعرفنا على WebGL وتحدثنا أننا سنستعمل إطار العمل threeJS للاستفادة من إمكانية WebGL لإنشاء رسوميات 3D في صفحات الويب التي نُنشِئها، فسنكمل تعلمنا في بقية هذا الدرس (وفي الدروس القادمة) بإنشاء نموذج لكوكب المريخ؛ وسنستهل الأمر بتعلم كيفية وضع كاميرا ثلاثية الأبعاد، والتحكم بتفاعل محتوى WebGL مع بقية صفحة HTML الموجود داخلها. ملاحظة: سنشرح كل خطوة بالتفصيل أثناء بنائنا للنموذج، لذا لن يكون لدينا مشهدٌ جاهزٌ في نهاية هذا الدرس، وإنما سنفعل ذلك في المقالات اللاحقة المبنية على هذه المقالة (والمستقلة عنها)، أما لو كنتَ متحمسًا لرؤية الناتج النهائي، فاطلع على هذه التجربة الحية. تهيئة الصفحة على الرغم من إمكانية استخدام عناصر WebGL بمفردها في الصفحة، إلا أنها تُصنَّف كتقنية وِب معيارية، مما يعني أنَّها تندمج اندماجًا كاملًا مع محتوى HTML، ولعدم امتلاك العنصر <canvas> ميزات تتعلق بقابلية الوصول وتحسين أرشفة محركات البحث للصفحة، فمن المنطقي أن نُنشِئ محتوى WebGL ضمن صفحة وِب فيها معلوماتٌ تشرح محتواه، وذلك بوضع النص ضمن شيفرات HTML، ثم إضافة محتوى WebGL عند الحاجة. وسنؤسِّس لصفحتنا –التي تتحدث عن المريخ– باستعمال الشيفرة الآتية: <div id="marsloc"></div> <article id="marsinfo"> <h1>Mars</h1> <div> <p>Home to both the Solar System’s highest mountain… </div> </article> سيوضع محتوى WebGL ضمن العنصر marsloc، وسيوضَع النص الموجود في عنصر <div> فوق جميع محتويات الصفحة. هذه هي شِفرة Sass التي تتحكم بمظهر الصفحة: body { background: black; margin: 0; min-height: 100vh; color: #fff; } #marsloc { cursor: grab; } #marsinfo { position: absolute; top: 0; width: 100%; padding: 2rem; } #marsinfo h1 { font-size: 8vw; margin-top: 0; font-weight: 100; line-height: 1; position: absolute; } #marsinfo div { width: 40%; position: absolute; background-color: rgba(0,0,0,0.3); right: 0; padding: 1.3rem; line-height: 1.6; font-size: 1.2rem; pointer-events: none; @media all and (max-width: 540px) { width: 100%; left: 0; top: 40vw; } } تغيير شكل مؤشر الفأرة في العنصر ‎#marsloc سيُدلُّ على محتوى WebGL، أما العنصر div الموجود في ‎#marsloc فله الخاصية pointer-events: none لذا لن يتأثر النص الموجود أعلى محتوى WebGL بالتعديلات التي نجريها على الكوكب. إنشاء الكوكب بعد كتابة شفرات HTML و CSS، فلنحمِّل آخر إصدار من threeJS من CDN في أسفل الصفحة: <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r83/three.js"> </script> ملاحظة: علينا أن نضمن وجود إطار عمل threeJS قبل كتابة أيّة شفرات تتعلق به. سيبدأ السكربت بضبط مجموعة من المتغيرات والثوابت التي سنستعملها في شيفرتنا: var container, controls, camera, renderer, scene, light, marsMesh, clock = new THREE.Clock(); const imgLoc = "https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/"; سنستخدم المتغير clock للمساعدة في الحركة الافتراضية لكوكب المريخ، أما imgLoc فهو ثابتٌ يُشير إلى موقع جميع الصور التي سنستعملها وعرّفناه في البداية كي لا نُكرِّر المسار لاحقًا. مجال الرؤية أوّل عنصر سنُنشِئه هو الكاميرا، وهذا أمرٌ ضروريٌ لنتمكن من «رؤية» المشهد الذي سنُنشِئه. يوجد نوعان من الكاميرات في إطار threeJS: المنظور (perspectiveCamera): الخطوط المتوازية الموجودة في المشهد ستتقارب من بعضها إذا امتدت لمسافة طويلة (تخيل نفسك واقفًا على سكةٍ حديديةٍ وتنظر إلى أبعد جزء ينتهي إليه بصرك)؛ وستبدو الأجسام البعيدة من الكاميرا صغيرةً. وهذه مشابه لآلية عمل بصرنا، وسيبدو المشهد من هذا النوع من الكاميرات واقعيًا. الإسقاط العمودي (OrthographicCamera): الخطوط المتوازية ستبقى متوازية بغض النظر عن مدى امتدادها؛ ولنفس السبب، لن تبدو الأجسام أصغر كلما ابتعدت عن الكاميرات. نستفيد من هذا النوع من الكاميرات عند رسم عناصر الواجهة الرسومية أو لبعض المناظير المعمارية. إذا كنّا سنستخدم كاميرا ذات منظور (perspectiveCamera) فعلينا أن نُعرِّف مجال الرؤية (يُشار إليه عادةً بالاختصار FOV، الذي يرمز إلى Field of view). يُحدِّد مجال الرؤية مدى اتساع «رؤية» الكاميرا. فمجال الرؤية الضيق (الذي يشبه الغِماء Blinker الذي يضعونه على أعين الخيول التي تجر العربات، كيلا تجزع الأحصنة مما حولها) يؤدي إلى «تركيز» الكاميرا ugn جزءٍ مُحدّد من المشهد، مما يؤدي إلى عدم إظهار بعض العناصر لأنها ستقع خارج مجال الرؤية. أما مجال الرؤية العريض فيؤدي إلى إظهار المزيد من الأجسام، لكنه يُسبِّب في جعلها تبدو أصغر وأبعد. علينا أيضًا ضبط نسبة العرض إلى الارتفاع Aspect ratio: أي ما هو عرض المشهد نسبةً إلى ارتفاعه. من المرجّح أنَّك قد سمعتَ بنسبة العرض إلى الارتفاع في الأفلام، فالأفلام ذات المشاهد «العريضة» تجنح لأن تكون أفلام «ملحمية»، أما الأفلام التي نسبة العرض إلى الارتفاع قليلة (تكاد أن تصبح مربعةً) فستشعر أنها أفلامٌ قديمة. نريد غالب الأوقات أن تتشابه نسبة العرض إلى الارتفاع في المشهد مع نسبة العرض إلى الارتفاع التابعة لنافذة المتصفح للزائر. آخر قيمتين علينا ضبطهما للكاميرا هما قيمتا لوحي القص Clipping plane البعيد والقريب. مبدئيا، تستطيع الكاميرات ثلاثية الأبعاد أن «ترى» إلى مسافة لا متناهية (على النقيض من المشاهد الواقعية)، أي لا توجد محدوديات في العدسات المستعملة في الكاميرات ثلاثية الأبعاد ولا توجد جزئيات في طبقات الجو تعرقل رؤيتها. يُشار إلى ذلك في الألعاب بالمصطلح «مسافة الرؤية» (أو مسافة الرسم، Draw distance)، وهذا هو أحد أسباب استخدام الضباب في الألعاب ثلاثية الأبعاد القديمة: فكلما قلَّ عدد العناصر التي يجب تحميلها كانت اللعبة أسرع. وفي حالتنا، نريد أن يكون لوح القص القريب Near clipping plane قريبًا جدًا إلى «عدسة» الكاميرا، ولوح القص البعيد Far clipping plane على مسافةٍ معقولة، وبالتالي ستحتوى العناصر التي نريد عرضها بين هذين اللوحين. الشفرة التي سنستعملها لفعل ذلك هي: camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000); أصبحتَ لدينا الآن كاميرا ثلاثية الأبعاد، لكنها موجودة في فضاء أسود لا متناهي، ولا تُشير إلى أيّ شيءٍ بعد؛ لكننا سنشرح في الدرس القادم طبيعة الفضاء ثلاثي الأبعاد، وكيفية إضاءته، وطريقة إضافة العناصر إلى المشهد. ترجمة –وبتصرّف– للمقال Introduction to WebGL وللمقال A WebGL Tour of the Solar System: Mars, Part One لصاحبهما Dudley Storey.
  14. سنقوم برسم تصميم ثلاثي الأبعاد بنمط Isometric لرمز الوجه المبتسم باستخدام برنامج انكسكيب. ولنستطيع الرسم بشكل صحيح ودقيق سيتوجب علينا رسم مخطط مسطح للتصميم للعمل انطلاقًا منه، ولذلك رسمت هذا المخطط. وبما أننا سنرسم بنمط الإيزومترك فسيكون علينا تحضير المكعب الأساسي الذي سنقوم بنسخه وتوزيعه للحصول على الشكل المطلوب. افتح برنامج الإنكسكيب ثم كبّر منظور العرض إلى القياس الطبيعي عبر القائمة View > Zoom > Zoom1:1 استخدم أداة رسم النجمة والمضلعات، عدّل عدد الزوايا في شريط أدوات الأداة إلى 6 لنحصل على مضلع سداسي (مسدس) مع اختيار رسم شكل المضلع بدل النجمة ثم ارسم المسدس مع الاستمرار بالضغط على Shift+Ctrl أثناء سحب الشكل باستخدام الفأرة وذلك لنحصل على شكل مسدس مركزه نقطة بداية السحب وليكون بمحاذاة عمودية مثالية. تأكد من جعل الشكل كما في الصورة تمامًا. سنحتاج إلى تحديد ميزة المطابقة لتصبح عملية التصميم أكثر سهولة ودقة. في حال لم يكن شريط المطابقة Snap موجودًا، قم بإظهاره عبر الذهاب إلى القائمة View > Show/Hide > Snap Controls Bar وتأكّد من وجود إشارة التفعيل بجانب Snap Controls Bar. ثم فعّل خيار المطابقة الموضح في الدائرة الحمراء وهو خيار Snap cusp nodes. استخدم أداة رسم منحنيات البيزير (يقابلها أداة القلم في برامج أدوبي المختلفة) ثم ارسم خطًّا مستقيمًا من إحدى زوايا المسدس إلى الزاوية المقابلة مستعينًا بميزة المطابقة Snap. والآن ارسم خطًّا آخر من زاوية أخرى. وأخيرًا ارسم خطًّا آخر عموديًّا من الزاوية العلوية إلى السفلية. ارسم باستخدام ذات الأداة شكلًا رباعي الأضلاع يمتد من الزوايا العلوية الثلاث للمسدس ومع نقطة التقاط الخطوط السوداء في المركز. وبما أن هذا الشكل الجديد ما يزال مُحدّدًا قم بإزالة لون الحدود وإضافة لون للتعبئة وليكن الأزرق بشكل مبدئي. ارسم الجانب الأيمن للمكعب عبر رسم شكل ممتد بين النقطة اليمنى العلوية والسفلية والنقطة السفلية إلى نقطة التقاء الخطوط في مركز الشكل. أزِل لون الحدود وأضِف لون تعبئة مختلف وليكن الأخضر. وأخيرًا ارسم الجانب الأيسر من ما بقي من شكل المسدس. وبنفس الطريقة أزِل لون الحدود ولوّن هذا الجانب باللون الأصفر. استخدم أداة التحديد والتحويل Select and Transform ثم حدّد الجانب العلوي ثم اضغط باستمرار على مفتاح Shift وانقر على الجانب الأيمن واستمر بالضغط على مفتاح Shift ثم انقر على الجانب الأيسر وأفلت مفتاح Shift وبذلك يكون قد تم تحديد الجوانب الثلاثة الملونة بدون تحديد شكل المسدس والخطوط المتقاطعة الموجودة تحت أشكال هذه الجوانب. اجمع هذه الأشكال في مجموعة واحدة عبر النقر على خيار Group في شريط الأدوات أو من خلال الاختصار Ctrl+G. حرّك مجموعة الأشكال هذه بعيدًا عن الأشكال الأساسية التي تحتها. احذف الأشكال الأساسية المستخدمة لرسم المكعب وهي شكل المسدس بالإضافة إلى الخطوط السوداء المتقاطعة. حدّد مجموعة المكعب ثم ألغِ التجمّع عبر الخيار Ungroup في شريط الأدوات أو من خلال الاختصار Shift+Ctrl+G وذلك لنقوم بإعادة تلوين جوانب المكعب بشكل صحيح. حدّد الجانب العلوي ثم لوّنه باللون الأصفر الفاتح ذو القيمة RGBA تعادل FFE680FF. والجانب الأيسر بلون أصفر فاقع بقيمة FFCC00FF. وأخيرًا الجانب الأيمن بلون أصفر داكن بقيمة AA8800FF. قم بجمع الجوانب مجدّدًا عبر الاختصار Ctrl+G أو من خيار Group في شريط الأدوات. في تصميمنا هذا لم نحدّد حجم التصميم أو الصفحة ولا أحجام المكعب وباقي الأشكال وذلك لأننا لا نقوم بتصميم محدّد بل الهدف من هذا التصميم هو تعلّم الرسم بتقنية Isometric لذلك قد تكون جوانب الصفحة ظاهرة وهو ما قد يشوش عملية التصميم في هذه الحالة لذا سنقوم بإزالة هذه الحدود عبر الذهاب إلى القائمة File > Document Properties أو من خلال الاختصار Shift+Ctrl+D. أزِل تفعيل خيار Show Page Border ثم أغلق نافذة الخصائص. سنقوم الآن بالبدء بعملية رسم التصميم المطلوب، وعبر الاستعانة بمخطط التصميم الأساسي في بداية الدرس سنقوم بالبدء برسم الجزء الأيسر من حدود الوجه. حدّد شكل المكعب ثم ضاعفه عبر الاختصار Ctrl+D ثم اسحب الشكل الجديد للأعلى مستعينًا بمزايا المطابقة لوضع الشكل الجديد بشكل مطابق فوق الشكل الأول. ضاعف الشكل الأخير عبر الاختصار Ctrl+D مجدّدًا ثم اسحبه بذات الطريقة نحو الأعلى أيضًا. من خلال المخطط فإن الجانب الأيسر المستقيم للوجه وكذلك بقية الجوانب بحجم خمس مكعبات. لذلك تابع مضاعفة الأشكال ورفع النسخ الجديدة للأعلى حتى يصبح عدد المكعبات خمسة. ضاعف الشكل الأخير ثم حرّكه بمقدار مكعب للأعلى وبمقدار مكعب أيضًا لليمين وذلك بحسب المخطط مع الاستعانة بمزايا المطابقة المفعلّة التي ستحقق مطابقة تامة للزوايا في تحريك الأشكال. ضاعف الشكل الأخير وحرّك النسخة الجديدة للأعلى. ضاعف النسخة الأخيرة وحرّكها للأعلى واليمين. كرّر ذات العملية الأخيرة تمامًا. ضاعف المكعب الأخير وحرّك النسخة لليمين (لاحظ أننا وبالعودة إلى شكل مخطط التصميم فإننا نتبع إرشادات المخطط بحذافيرها). ضاعف الشكل الأخير ثم حرّكه للأعلى واليمين. ضاعف هذا الشكل الأخير أربع مرّات إضافية وحرّكها لليمين في كل مرّة لتحصل على خمسة مكعبات في صف واحد. والآن اصنع نسختين جديدتين وضعهما كما في الصورة وبحسب المخطط. واصنع نسخة أخرى وحرّكها للأسفل واليمين. وواحدة أخرى بعد بذات الطريقة والاتجاه. اصنع نسخة عن الشكل الأخير ثم حرّكها للأسفل. هنا ستلاحظ أن الشكل الجديد قام بتغطية الشكل السابق ما يجعل المنظور غير متناسق ومنطقي. ولتصحيح هذا الوضع حدّد الشكل الجديد ثم أرسله للأسفل عبر الخيار Lower Selection to Bottom أو من خلال المفتاح End من لوحة المفاتيح، وبذلك سيتم إرسال هذا الشكل أسفل الشكل السابق ويصبح منظور التصميم منطقيًا وصحيحًا. اصنع نسخة جديدة وحرّكها للأسفل واليمين. اصنع نسخة جديدة وحرّكها للأسفل. ستلاحظ تكرار عملية الترتيب غير الصحيح للأشكال في هذه المرحلة وذلك بحسب شكل المكعب وترتيب النسخ الجديدة. مجدّدًا قم بإرسال النسخة الجديدة للأسفل عبر الخيار Lower Selection to Bottom أو من خلال المفتاح End من لوحة المفاتيح. كرّر هذه العملية مع إرسال النسخة الجديدة للأسفل في كل مرّة حتى يصبح لدينا خمسة مكعبات فوق بعضها. حرّك نسخة جديدة من المكعب الأخير للأسفل واليسار ولاحظ أن عملية التحريك الأخيرة توحي بأن المكعب الجديد موجود أمام المكعب السابق بصورة مختلفة عن نسق سير التصميم وهذه هي روعة تصميم الإيزومترك حيث أن مجالات الإبداع فيها كبيرة وتسمح لنا برسم تصاميم محيّرة للعقل وجميلة في نفس الوقت ولكننا هنا لسنا بصدد تصميمٍ من هذا النوع لذلك سنقوم في الخطوة التالية بتصحيح الوضع. من جديد أرسل الشكل الأخير للأسفل عبر الخيار Lower Selection to Bottom أو من خلال المفتاح End من لوحة المفاتيح. والآن أصبح شكل التصميم صحيحًا ومطابقًا للمخطط الأساسي. حرّك نسخة جديدة للأسفل ثم أعد ترتيبها أسفل بقية الأشكال بذات الطريقة. تابع الرسم بحسب المخطط وبذات الأسلوب حتى تتم رسم دائرة حدود الوجه كاملًا. وأخيرًا ارسم مكعبات جديدة مع تغيير ألوانها إلى تدرجات الرمادي وضعها بحسب المخطط مكان العينين والفم المبتسم. يمكنك إضافة خلفية تدرج دائري بسيطة لإنهاء التصميم بشكل بسيط وناعم. أو يمكنك تعديل التصميم للحصول على الشكل التالي أيضًا. هذه هي إحدى طرق رسم الإيزومترك في الإنكسكيب وهناك طرق أخرى لرسم المكعب الأول في التصميم بتقنية الإيزومترك وهي: طريقة ثانية لرسم مكعب إيزومترك في الإنكسكيب: تعتمد هذه الطريقة على تجهيز إعدادات المستند بشكل يظهر فيه شبكة إيزومترك جاهزة وصحيحة ليتم استخدامها مع تفعيل مزايا المطابقة لرسم المكعب. افتح ملفًّا جديدًا في الإنكسكيب ثم اذهب إلى القائمة File > Document Properties أو من خلال الاختصار Shift+Ctrl+D ستقوم بفتح نافذة خصائص المستند. افتح تبويب Grids. ثم اختر من قائمة Creation الخيار Axonometric grid ثم اضغط على New بجوارها لتظهر شبكة مضلعة مع خصائص هذه الشبكة وهنا يمكنك اختيار حجم هذه الشبكة من خيار Spacing Y كما يمكن تحديد دمج خطوط الشبكة لكل عدد محدد من الخلايا. والآن استخدم أداة رسم منحنيات البيزير مع الاستعانة بمزايا المطابقة لرسم الجانب العلوي من المكعب كما في الصورة. وباستخدام ذات الأداة ارسم الجانب الأيمن. ثم الجانب الأيسر. أزِل ألوان الحدود من الأشكال الثلاثة ثم لوّن الجوانب الثلاثة بألوان مناسبة. يمكنك إزالة تفعيل ظهور الشبكة من خلال خصائص المستند وتبويب Grids ثم إزالة تفعيل Enable أو يمكن الإبقاء على هذه الشبكة لسهولة رسم تصاميم الإيزومترك بالاستعانة بها. طريقة ثالثة لرسم مكعب إيزومترك في الإنكسكيب: ارسم باستخدام أداة رسم النجمة والمضلعات ذات شكل المسدس وبذات الطريقة المشروحة في هذا الدرس ولوّنه بلون أزرق مع إزالة لون الحدود واجعل مستوى التعتيم Opactiy عند 50%. مع تفعيل مزايا المطابقة المستخدمة في هذا الدرس تحديدًا قم بمضاعفة هذا الشكل وتحريكه إلى الجانب السفلي الأيسر من الشكل الأساسي. ضاعف الشكل الأخير وحرّكه إلى الجهة اليمنى تمامًا كما في الصورة. اصنع نسخة جديدة وضعها في مركز هذه الأشكال كما في الصورة. ضاعف الشكل الأوسط ثم حدّده مع الشكل العلوي باستخدام مفتاح Shift ثم اذهب إلى القائمة Path > Intersection ليتم قص الجزء المشترك بين الشكلين وهو في هذه الحالة الجانب العلوي من المكعب المطلوب. لوّن هذا الشكل الأخير بلون مختلف لتمييزه كجانب علوي. ضاعف مجدّدًا الشكل الأوسط ثم حدّد النسخة الأخيرة مع الشكل الأيسر ثم اذهب إلى القائمة Path > Intersection ليتم قص الجانب الأيسر للمكعب. لوّن هذا الجانب بلون مناسب بحسب اللون الأول. الآن لست مضطرَّا إلى مضاعفة الشكل الأوسط لأنه لم يتبقَ إلّا جانب واحد. حدّد الشكل الأوسط والشكل الأيمن ثم اذهب إلى القائمة ذاتها لقص الجانب الأيمن للمكعب. لوّن الجانب الأيمن باللون المناسب وبذلك نحصل على المكعب المطلوب. إن مجالات التصاميم الإيزومترك كبيرة وواسعة ولا يحدّها إلّا خيال المصمم فقط، وفي هذا الدرس تعلّمنا أساسيات الرسم بهذا الأسلوب وطرق رسم المكعبات المختلفة وما عليك إلا متابعة العمل الجاد لتطوير مهاراتك في رسم تصاميم إبداعية بهذا الأسلوب.
  15. لدى برنامج أدوبي إليستريتور أدوات أنيقة للتصميم ثلاثي الأبعاد. هذا المثال سيعطيك فكرة عن كيفية استخدام هذه الأدوات لتصميم كرة أرضية ثلاثية الأبعاد يمكنك تدويرها لرؤية المعالم والبلاد. الخطوة الأولى ستكون الحصول على صورة للكرة الأرضية ثنائية الأبعاد والتي يمكنك الحصول عليها من أحد المصادر التالية Free Vector Maps and Country Outlines وthe vector world map. افتح الخريطة في برنامج الإليستريتور وحدّد أشكال الفكتور الأساسية ثم انقر على أيقونة New في لوحة الرموز Symbols. وبذلك يتم حفظ هذا الشكل كرمز لنستخدمه لاحقًا والآن احذف الأشكال. ارسم دائرة على لوح الرسم ولوّنها بالأزرق. استخدم أداة التحديد المباشر Direct Selection وحدّد النقطة اليمنى من الدائرة. اضغط على مفتاح Delete لحذف هذه النقطة والإبقاء على نصف دائرة فقط. حدّد نصف الدائرة واذهب إلى القائمة Effect > 3D > Revolve في خيارات التدوير ثلاثي الأبعاد غيّر المصدر إلى Right Edge والسطح إلى Diffuse Shading. انقر على Map Art واختر الرمز الذي أنشأناه سابقًا لخريطة العالم ثم عدّل الحجم حتى يملأ المساحة وفعّل خيار Shade Artwork. وبهذا ستظهر لنا كرة أرضية ثلاثية الأبعاد يظهر فيها بوضوح القارات والمحيطات. إذا أردت ضبط زاوية عرض الكرة الأرضية قم بفتح لوحة المظهر Appearances وانقر مرتين على 3D Revolve لفتح نافذة الخيارات. كما تشاهد يمكنك الحصول على عدد غير محدود من صور الكرة الأرضية بحسب زاوية دورانها وهذه التقنية لا تقتصر على الكرة الأرضية فحسب بل يمكنك تصميم زجاجة عصير ووضع الملصق عليها للمراجعة والتدقيق. ترجمة -وبتصرّف- للمقال: Create a Rotatable Globe in Adobe Illustrator لصاحبه: Chris Spooner
  16. قمنا في الدرس السابق بالتعرف على محرك Unity وكيفية تحميله وإنشاء مشروع جديد عليه، سنبدأ في هذا الدرس في مشروع عملي لتعلم كيفية صناعة لعبة حقيقية كاملة. سنتكلم في الدرس الأول عن إعداد مشهد اللعبة والتحكم بالكاميرا. ملاحظة: يمكن تحميل الملفات المصدرية لكامل هذه السلسلة عبر حساب أكاديمية حسوب على Github، يمكن أيضا تحميل ملف APK لتجريب اللعبة على أجهزة Android. استيراد الصور وتجهيزها سأستخدم في هذا المثال مجموعة من الرسوم المطروحة مجانا تحت رخصة المشاع الإبداعي CC0 وهي متوفرة على الموقع http://kenney.nl. المجموعة الأولى عبارة عن رسومات خاصة بالألعاب الفيزيائية مثل Angry Birds، وهي اللعبة التي نحاول أن نحاكي ميكانيكياتها عبر هذه السلسلة. أما المجموعة الثانية فهي عبارة عن رسوم حيوانات بسيطة سنستخدمها بدلا عن الطيور الموجودة في اللعبة الأصلية بحيث تمثل المقذوفات. إلا أننا سنضيف بعض الرسومات الأخرى وملفات الأصوات حسب الحاجة. سأعتمد في هذه السلسلة وضع كل مصدر (ملف صورة أو ملف صوت) داخل مجلد يحمل اسم الموقع الذي تم جلب المصدر منه، بحيث يمكنك الرجوع لاحقا لهذه المواقع وتحميل الملفات. بعد تحميل هذه الرسومات وفك ضغطها قم بنسخها إلى داخل المجلد Assets الخاص بمشروعك، يمكنك نسخها عن طريق نظام التشغيل أو بسحبها مباشرة إلى داخل المجلد في مستعرض Unity. بمجرد أن تضيف هذه الملفات للمشروع سيتعرف عليها Unity على أنها رسومات شبحية sprites، وهي أنواع الرسوم الأكثر شيوعا في الألعاب ثنائية الأبعاد. من أجل الحصول على أعلى جودة ممكنة سنقوم بتعديل بعض خصائص الرسومات، سأضرب مثالا هنا على مجلد واحد ومن ثم علينا تكرار العملية لجميع مجلدات الرسومات. ملاحظة: تحتوي مجموعات الرسومات على طريقتين مختلفتين للتخزين: الأولى تخزين كل صورة على حدى في ملف مستقل، والثانية جمع الصور في ملف واحد يسمى ورقة الرسومات sprite sheet. سنتناول في هذه الدروس الطريقة الأولى وهي الأشكال المنفصلة؛ وذلك لسهولة العمل عليها. علما بأن الطريقة الثانية أكثر كفاءة من ناحية الأداء وأسهل في حالة الرسومات المتحركة. كما ترى في الشكل التالي فإنني قمت باختيار جميع عناصر مجلد رسومات الوحوش والتي ستمثل الخصوم في هذه اللعبة. بعد ذلك قمت بتعديل خصائص استيراد هذه الرسومات لتصبح كالتالي: بتغيير نوع المرشِّح إلى Trilinear وتنسيق الألوان إلى Truecolor فإننا نطلب من Unity ألا يقوم بضغط هذه الصور بحيث تبقى بحجمها الأصلي وتحافظ على جودتها. على الرغم من أن الضغط أفضل للأداء، إلا أنك ستلاحظ أن Unity يخبرك أن معظم هذه الرسومات غير قابلة للضغط كونها لا تحقق قاعدة أن يكون الطول والعرض مساويين لأرقام لوغاريتمية للأساس 2 (مثلا 64، 128، 512، إلخ). لا تنس أن تضغط على Apply لحفظ التغييرات بعد الانتهاء منها. بناء المشهد وتجهيز الخلفية بعد تغيير الخصائص لجميع الرسومات التي استوردناها يمكننا أن نبدأ بإعداد المشهد. الخطوة الأولى ستكون بإضافة الخلفية والأرضية التي ستدور أحداث اللعبة عليها. إحدى المواصفات المهمة في عملية الاستيراد هي Pixels Per Unit. الرقم 100 هنا يعني أن خطا بطول 100 بكسل في الصورة الأصلية يغطي مسافة قدرها وحدة واحدة في فضاء Unity. فلو افترضت أن الوحدة هي متر واحد، فإن صورة صندوق بحجم 10×10 بكسل تساوي صندوقا بحجم 10×10 سم في فضاء اللعبة. لحسن حظنا فإن مجموعة الصور التي استوردناها ذات أحجام مناسبة لبعضها البعض، فمثلا صور الوحوش هي ذات مقاس 70×70 بكسل بينما الخلفيات أكبر من ذلك بكثير وتصل إلى 1024×1024 بكسل. لنأخذ بعين الاعتبار منذ البداية أن هذه السلسلة ليست لتعلم برمجة الألعاب فقط، كما أنها ليست لتعلم محرك Unity فقط، بل يمكنك القول أنها ستعلمك أيضا أفضل الممارسات البرمجية والتنظيمية للمشهد لتحصل على أفضل نتيجة باستخدام هذا المحرك. من أجل ذلك سنقوم بإعداد مشهد اللعبة بطريقة خاصة بحيث يحتوي المشهد على كائن واحد نسميه الكائن الجذري للمشهد SceneRoot ومن ثم سنضيف كل عناصر المشهد على شكل أبناء وأحفاد لهذا الكائن. لإضافة كائن جديد كل ما عليك هو اختيار القائمة: Game Object > Create Empty وسيظهر بعدها الكائن الجديد في هرمية المشهد باسم GameObject، قم باختياره وتغيير اسمه إلى SceneRoot وموقعه إلى نقطة الأصل (0 ,0). كما ذكرت في مقدمة هذا الفصل يمكنك تغيير هذه القيم من نافذة الخصائص Inspector كما هو موضح في الصورة أدناه. لاحظ أن هذا الكائن "فارغ" كما يدل اسمه، أي أنه موجود في الذاكرة فقط ولا يمكن رؤيته في المشهد رغم أنه موجود في وسطه، سنأتي إلى هذه التفاصيل حسب حاجتنا لها. بعد ذلك سنضيف كائنا فارغا آخر ليمثل خلفية المشهد، كل ما عليك هو أن تضغط بزر الفأرة الأيمن على الكائن SceneRoot في الهرمية وتختار Create Empty من أجل أن تضيف كائنا فرعيا (ابنا) للكائن الجذري ولنقم بتسميته Background. أخيرا عليك أن تقوم بسحب كائن الكاميرا Main Camera إلى داخل الكائن الجذري بحيث تصبح هرمية المشهد بهذا الشكل. حان الوقت الآن لحفظ المشهد الذي نعمل عليه، كما هو الحال في 99% من البرامج يمكنك الحفظ عن طريق Control+S وهو أمر خاص بحفظ المشهد وليس حفظ المشروع كاملا، حيث أن المشروع ما هو إلا مجموعة ملفات يتم تعديلها وحفظها على حدى. قم بإنشاء مجلد جديد داخل Assets وقم بتسميته Scenes ومن ثم احفظ المشهد داخله باسم GameScene. لنتفق من الآن على أننا سنقوم ببناء مشهد واحد لكل اللعبة، وسنعمل على تغيير كل من الخلفية والأرضية ومواقع الكائنات لصنع مراحل مختلفة. الكائن الأول سيكون خلفية المشهد، والذي توجد عدة صور يمكن استخدامها له. هذه الصور عددها 8 وهي موجودة في المجلد Backgrounds في مجموعة الصور الأولى كما ترى في الصورة أدناه. ما يميز صور الخلفيات هذه هو أن كلا منها ينطبق طرفها الأيمن على طرفها الأيسر تماما مما يجعلنا قادرين على تكرارها أفقيا بشكل متتابع دون أن يلاحظ اللاعب وجود حدود بينها. بما أننا نتعامل مع لعبة ذات مشهد عرضي فإن علينا أن نكرر الخلفية أكثر من مرة بشكل أفقي، ولتكن 4 مرات. قبل أن نبدأ بإضافة الخلفيات للمشهد، لنسهل الأمر على أنفسنا بجعل نقطة الارتكاز Pivot لجميع صور الخلفيات هي الطرف الأيسر من الصورة بدل الأوسط، وذلك كما ترى في الصورة التالية: ولكن ماذا يعني أن تكون نقطة ارتكاز الصورة هي طرفها الأيسر وليس وسطها؟ الصورتان في الأسفل تجيبان على هذا السؤال. في كلتا الحالتين فإن موقع الصورة لم يتغير وهو (0 ,0) أي في منتصف المشهد. في الوضع الافتراضي (الصورة اليسرى) فإن ارتكاز الصورة يكون في منتصفها، أي أن موقع الصورة في الفضاء هو موقع منتصفها، ويمتد طرفا الصورة الأيسر والأيمن بين النقطتين x=-5.12 و x=+5.12. أما في الحالة الثانية قمنا بتغيير الارتكاز لأقصى يسار الصورة أفقيا مع بقائه في منتصفها عموديا. بهذا الشكل أصبحت الصورة تمتد من النقطة x=0 يسارا إلى النقطة x=+10.24 يمينا. لاحظ أن قيم هذه النقاط متوافقة مع حقيقة أن الوحدة الواحدة =100 بكسل حيث يكون عرض الصورة بالوحدات هو 10.2=1024/100 بهذا أصبح بإمكاننا أن نحسب مواقع الصور الأربعة التي سنقوم برصّها بجانب بعضها البعض من اليسار لليمين حول نقطة الأصل، وهي كالتالي: الصورة في أقصى اليسار ستكون في الموقع 20.48- وتمتد إلى 10.24-. الصورة على يسار نقطة الأصل ستكون في الموقع 10.24- وتمتد إلى 0.0. الصورة على يمين نقطة الأصل ستكون في الموقع 0.0 وتمتد إلى 10.24+. الصورة في أقصى اليمين ستكون في الموقع 10.24+ وتمتد إلى 20.48+. بدلا من أن نقوم بوضع هذه الصورة يدويا، سنقوم بكتابة بُريمج صغير script بحيث نعطيه صورة ونطلب منه أن يكررها عددا من المرات ليصنع لنا الخلفية. هذا البريمج سيعمل بالشكل التالي: سنقوم بإعطائه جميع صور الخلفيات الموجودة لدينا على شكل مصفوفة بحيث تحمل كل صورة رقما خاصا بها، إضافة لذلك سنكون قادرين على تزويده بعدد مرات التكرار المطلوبة للصورة من أجل رسم الخلفية. عند تشغيل اللعبة فإنه يجب علينا أن نقوم باختيار رقم الخلفية التي نرغب بظهورها على الشاشة، وهذا الرقم سيكون من 0 إلى 7. سنعود لموضوع البريمج هذا بعد قليل. قبل الخوض في التفاصيل أود التنويه إلى أن الكائنات في محرك Unity جميعها تتشابه، وهي في وضعها الأصلي فارغة غير مرئية، وما يميز كل كائن عن غيره ويعطيه سماته الخاصة هو مجموعة المكوّنات التي تتم إضافتها إليه. المكوّن الوحيد الموجود في الكائن الفارغ هو Transform، وهو موجود في جميع كائنات المحرك دون استثناء، حيث أنه يعطي الكائن موقعه ودورانه وحجمه في الفضاء ثنائي الأبعاد (أو ثلاثي الأبعاد) إضافة إلى أنه يحدد علاقاته بالكائنات الأخرى كعلاقة الأب والأبناء التي نراها في هرمية المشهد. بناء على هذه الحقيقة، فإن ما تراه في شاشة الخصائص Inspector حين تختار أي كائن هو مجموعة المكوّنات المضافة إليه. ما سنقوم به الآن هو بناء قالب prefab، وهو عبارة عن كائن نضيف إليه بعض المكوّنات، ومن ثم يمكننا إنشاء عدة نسخ منه أثناء تشغيل اللعبة. الأمر الجيد في هذه القوالب هو أنه يمكن تعديلها من مكان واحد مهما بلغ عدد الكائنات التي يتم إنشاؤها منها، حيث ينعكس أي تعديل في القالب الأصلي (كإضافة مكون أو حذفه) على جميع الكائنات التي تتبع هذا القالب. القالب الذي سنقوم به خاص بالكائن الذي سيعرض صورة الخلفية، والذي سيحتاج مبدئيا لمكوّن واحد وهو Sprite Renderer الخاص بتصيير الصور ثنائية الأبعاد على الشاشة. لإنشاء القالب لنقم أولا بإضافة كائن فارغ للمشهد ومن ثم نضيف له المكوّن المذكور وذلك عن طريق الزر Add Component والذي يعطيك قائمة بجميع المكوّنات المتوفرة، ولتسهيل الوصول يمكنك البحث عن طريق كتابة اسم المكوّن Sprite Renderer ومن ثم اختياره كما يلي: بعد إضافة المكوّن أصبحنا جاهزين لتحويل هذا الكائن إلى قالب، وذلك عن طريق سحبه من الهرمية إلى داخل أي مجلد في المشروع، في هذه الحالة سأقوم بإنشاء مجلد جديد داخل Assets وأسميه Prefabs لأننا سنحتاج في هذا العمل إلى عدد كبير من القوالب كما سنرى. بعدها قم بتغيير اسم القالب ليصبح BGElement. بعد إنشاء القالب لم نعد بحاجة للكائن في المشهد بالتالي يمكننا حذفه باستخدام مفتاح Delete. انتبه هنا أنك تحذف الكائن من الهرمية ولا تحذف القالب من المشروع فهما يحملان نفس الاسم لكن الفرق كبير بين الأمرين! لإضافة بريمج جديد للمشروع لنقم أولا بإنشاء مجلد خاص بالبريمجات داخل Assets ولنسمه Scripts. بعدها يمكنك إضافة بريمج جديد بلغة #C وذلك عن طريق الضغط على المجلد بزر الفأرة الأيمن ومن ثم اختيار: Create > C# Script. أدخل الاسم BackgroundManager ومن ثم اضغط Enter وبعدها قم بفتح الملف على محرر MonoDevelop أو Visual Studio وذلك بالنقر المزدوج. لنشاهد البريمج الذي سنكتبه في السرد التالي ثم نناقشه معا بالتفصيل. using UnityEngine; using System.Collections; public class BackgroundManager : MonoBehaviour { //القالب المستخدم لبناء عناصر الخلفية public GameObject bgElementPrefab; //مصفوفة تحتوي على جميع صور الخلفيات المتاحة public Sprite[] selectionList; //عدد مرات تكرار صورة الخلفية public int repeatCount = 4; //صورة الخلفية المعروضة حاليا private int selectedIndex = -1; //"Background" مرجع للكائن الابن المسمى private Transform bgGameObject; //تستدعى مرة واحدة عند بداية التشغيل void Start () { //"Background" ابحث في الأبناء على الكائن الذي يحمل الاسم bgGameObject = transform.FindChild("Background"); //قم مبدئيا باختيار الصورة الأولى كخلفية ChangeBackground(0); } //تستدعى مرة واحدة عند تصيير كل إطار void Update () { } //تقوم بتغيير صورة الخلفية المعروضة حاليا public void ChangeBackground(int newIndex){ if(newIndex == selectedIndex){ //لا حاجة لتغيير الصورة return; } //قم بحذف صور الخلفية الحالية for(int i = 0; i < bgGameObject.childCount; i++){ Transform bgSprite = bgGameObject.GetChild(i); Destroy(bgSprite.gameObject); } //قم بتخزين صورة الخلفية الجديدة من المصفوفة حسب الموقع المعطى Sprite newSprite = selectionList[newIndex]; //ما هو عرض صورة الخلفية بالبكسل؟ float width = newSprite.rect.width; //ما هو ارتفاع صورة الخلفية بالبكسل؟ float height = newSprite.rect.height; //كم عدد البكسلات في الوحدة الواحدة؟ float ppu = newSprite.pixelsPerUnit; //احسب الطول والعرض مستخدما الوحدات width = width / ppu; height = height / ppu; // قم بحساب الموقع الأفقي للصورة الأولى في أقصى اليسار float posX = -width * repeatCount * 0.5f; //قم بحساب حدود المشهد الجديدة Vector2 boundsSize = new Vector2(width * repeatCount, height); Bounds newBounds = new Bounds(Vector2.zero, boundsSize); //قم بإرسال رسالة تخبر بتغير حدود المشهد BroadcastMessage("SceneBoundsChanged", newBounds); //يمكننا الآن البدء ببناء الخلفية الجديدة for(int i = 0; i < repeatCount; i++){ //قم ببناء كائن جديد مستخدما القالب GameObject bg = (GameObject) Instantiate(bgElementPrefab); //قم بتحديد اسم الكائن bg.name = "BG_" + i; //قم بجلب مكوّن تصيير الصور الموجود في الكائن SpriteRenderer sr = bg.GetComponent<SpriteRenderer>(); //قم بتحديد الصورة التي سيتم تصييرها لتكون الصورة المختارة من المصفوفة sr.sprite = newSprite; //قم بضبط الموقع الأفقي مستخدما القيمة التي سبق وحسبناها bg.transform.position = new Vector2(posX, 0); //قم بإرجاع صورة الخلفية خطوة للخلف في ترتيب الرسم sr.sortingOrder = -1; //كأب لعنصر الخلفية الذي تم إنشاؤه "Background" قم بتحديد الكائن الفارغ bg.transform.parent = bgGameObject; //قم بإضافة مكون تصادم على شكل مربع bg.AddComponent<BoxCollider2D>(); //قم بإضافة عرض الصورة إلى قيمة الموقع الأفقي لحساب الموقع الجديد للعنصر التالي posX += width; } //أرسل رسالة تخبر بتغير صورة الخلفية وأرفق معها موقع الصورة الجديدة BroadcastMessage("BackgroundChanged", newIndex); } } يتعامل محرك Unity مع البريمجات على أنها مكوّنات يمكن إضافتها إلى أي كائن في المشهد أو قالب في المشروع (القوالب في النهاية هي كائنات). بالنسبة لنا فهذا بريمج أساسي يتعلق بإدارة المشهد ككل وليس باللاعب أو الخصم، بالتالي سنضيفه إلى الكائن الجذري وذلك ببساطة عن طريق سحب ملف BackgroundManager.cs من مستعرض المشروع إلى الكائن SceneRoot سواء في الهرمية أو في شاشة خصائصه. بعد إضافته ستلاحظ أن البريمج ظهر في شاشة خصائص الكائن الجذري وظهرت المتغيرات العامة bgElementPrefab و selectionList و repeatCount بحيث يظهر الأول على شكل خانة فارغة ويظهر الثاني على شكل قائمة يمكنك تحديد عدد عناصرها من الخانة size، والثالث على شكل مربع نص يقبل قيمة رقمية. لنر الآن كيف يمكننا تحديد قيم هذه المتغيرات وستكون البداية مع bgElementPrefab. كما هو متوقع فهذه الخانة مخصصة لتحديد القالب الذي سيستخدم لاحقا لإنشاء عناصر الخلفية، وهو BGElement الذي سبق وأنشأناه. لربط القالب بهذا المتغير كل ما عليك هو أن تقوم بسحبه من مستعرض المشروع إلى داخل الخانة التي تراها في شاشة الخصائص. بعد ذلك قم بتغيير عدد العناصر في القائمة selectionList إلى 8 ومن ثم اسحب لكل خانة منها واحدة من صور الخلفية الموجودة في المجلد Backgrounds، أما المتغير الثالث repeactCount فقد أخذ قيمة افتراضية هي 4 وهي القيمة التي استخدمناها عند تعريفه. سيصبح شكل الكائن الجذري الآن كالتالي: لو جربت تشغيل اللعبة الآن ستلاحظ ظهور صورة الخلفية الموجودة في العنصر الأول من القائمة، كما ستلاحظ أنها تكررت أفقيا 4 مرات بشكل صحيح كما ترى أدناه، وتلاحظ أيضا الكائنات الأربعة لهذه الصور والتي تمت إضافتها كأبناء للكائن Background في الهرمية. سنناقش الآن بشكل سريع أهم آليات عمل البريمج BackgroundManager، جميع البريمجات في محرك Unity تأخذ تقريبا نفس التنسيق، حيث تبدأ بتعريف المتغيرات اللازمة، ومن ثم الدّالتين الأكثر استخداما وهما ()Start و ()Update. كما هو موضح في التعليقات على الكود فإنّ الدّالة ()Start تستدعى مرة واحدة فقط عند بداية التشغيل إن كان الكائن موجودا في المشهد أصلا، أو بمجرد إضافته للمشهد إن لم يكن موجودا من قبل. بعد ذلك تدخل اللعبة فيما نسميها حلقة التحديث أو حلقة تصيير الإطارات حيث يتم استدعاء الدّالة ()Update عند تصيير كل إطار طالما أن اللعبة تعمل. في حالتنا هذه لا يلزمنا استخدام ()Update. لاحظ أننا بدأنا البريمج بتعريف عدد من المتغيرات بعضها عام public وبعضها الآخر خاص private. بالنسبة لمحرك Unity فإن المتغيرات العامة ذات أهمية خاصة لأنه يعرضها على شكل خانات في شاشة الخصائص مما يسمح لك بتغيير قيمها دون تعديل الكود كما سبق ورأينا. فيما يلي شرح هذه المتغيرات: bgElementPrefab يستخدم كمرجع للوصول للقالب الذي سنستخدمه لإنشاء عناصر الخلفية عند بنائها. selectionList مصفوفة تحتوي على عناصر من نوع Sprite حيث تقوم بتخزين قائمة بجميع الخلفيات التي يمكن استخدامها. repeatCount عدد صحيح يمثل عدد مرات تكرار الخلفية أفقيا، بطبيعة الحال فزيادة هذا العدد سيؤدي لزيادة عرض الخلفية النهائية. selectedIndex يمثل موقع الخلفية المعروضة حاليا في القائمة، حيث تمثل القيمة 0 العنصر الأول. bgGameObject سنستخدم هذا المتغير للوصول إلى الكائن الفارغ Background والذي خصصناه ليكون أبا لجميع صور الخلفية الموجودة في المشهد. الجدير بالذكر هنا هو أننا في معظم الحالات نستخدم متغيرا من نوع Transform للوصول للكائنات، ولذلك فوائد عديدة سنعرفها. عند بداية التشغيل يتم استدعاء الدّالة ()Start والتي تقوم أولا بالبحث في الأبناء عن الكائن المسمى Background وتخزينه في المتغير bgGameObject. الخطوة الثانية التي تقوم بها هذه الدّالة هي اختيار العنصر الأول في القائمة تلقائيا ليكون خلفية المشهد وذلك عن طريق استدعاء الدّالة ()ChangeBackground مع القيمة 0. الدّالة ()ChangeBackground هي الأهم في هذا البريمج حيث تعمل على تغيير الخلفية حسب القيمة التي تعطى لها حين الاستدعاء newIndex. إذا كانت هذه القيمة أصلا تساوي قيمة الخلفية المعروضة حاليا selectedIndex فلا حاجة لتغيير أي شيء بالتالي يتوقف تنفيذ الدّالة. عدا ذلك فإن الدّالة تحتاط لوجود خلفية معروضة حاليا فتقوم بحذفها قبل كل شيء. عملية الحذف تتم عبر المرور على جميع أبناء الكائن bgGameObject واستدعاء الدّالة ()Destroy لها وذلك ليتم حذفها من المشهد. حالة حذف الكائن هي أحد الاستثناءات لقاعدة التعامل مع الكائنات عن طريق المكون Transform، حيث أن الحذف يجب أن يتم على مستوى الكائن كاملا وليس على مكوّن بعينه، بالتالي نستدعي bgSprite.gameObject حين الحذف. بعد حذف الخلفية السابقة (إن وجدت) نحتاج لإضافة الجديدة. بالتالي فالخطوة التالية ستكون تخزين قيمة الصورة الموجودة في العنصر newIndex في المتغير newSprite ومن ثم حساب عرض الصورة الأصلية بوحدات فضاء Unity وذلك بقسمة عرضها بوحدة البكسل على عدد البكسلات في كل وحدة. بما أن تكرار صورة الخلفية سوف يتمحور حول نقطة الأصل، فإن أقصى نقطة إلى اليسار ستكون نصف عرض جميع الصور التي سنكررها، بالتالي نحسب القيمة posX عن طريق ضرب نصف العدد الكلي للصور repeatCount بعرض الصورة الواحدة width، ونحول الناتج للقيمة السالبة حتى نبدأ من اليسار (تذكر أننا قمنا باختيار يسار الصورة ليكون نقطة ارتكازها في الفضاء). إضافة لنقطة البداية قمنا بحساب الطول والعرض الكلي للمشهد بعد بناء الخلفية الجديدة، ومن ثم قمنا بتخزين هذه القيم في متغير من نوع Bounds، هذا المتغير يخزن ببساطة نقطة في الفضاء وامتدادات لهذه النقطة على المحورين x و y. لاحظ أننا عرّفنا متغير الامتداد على شكل متجه ثنائي الأبعاد وحددنا قيمة x بأنها عدد مرات تكرار صورة الخلفية مضروبة في عرض الصورة الواحدة و قيمة y على أنها ارتفاع الصورة الواحدة. بعد ذلك قمنا بإرسال رسالة لجميع البريمجات الأخرى سواء الموجودة على الكائن الجذري أو أي كائن في الأبناء وذلك لإعلامها بأن حدود المشهد تغيرت، واستخدمنا لذلك الدّالة ()BroadcastMessage. عند استدعاء هذه الدّالة فإننا نعطيها اسم الرسالة وهو هنا SceneBoundsChanged ونرفق معها أيضا المتغير newBounds الذي يحتوي على حدود المشهد الجديدة. سنرى لاحقا ما معنى أن ترسل رسالة، وكيف تستقبلها، ولماذا هي مهمة. خلال مجموعة الدروس هذه سنتعامل بشكل مستفيض مع الرسائل، لذا لا بأس من التعرف مبكرا على كيفية إرسالها. يتم إرسال الرسائل في محرك Unity باستخدام أحد الدّوال التالية: BroadcastMessage والتي تقوم بإرسال رسالة لجميع البريمجات الموجودة على الكائن الحالي إضافة إلى جميع كائنات الأبناء والأحفاد المتفرعة منه. SendMessage والتي تقوم بإرسال الرسالة إلى جميع البريمجات الموجودة على الكائن الحالي فقط. SendMessageUpwards والتي تقوم بإرسال الرسالة إلى جميع بريمجات الكائن الحالي إضافة إلى جميع آبائه وأجداده في الهرمية. الحلقة التكرارية التي تلي هذه الخطوات هي التي يتم عبرها بناء وتوزيع صور الخلفية في الفضاء بالشكل الصحيح. حيث نبدأ بإنشاء كائن جديد bg مستخدمين القالب bgElementPrefab ثم نعطيه اسما متسلسلا حسب موقعه في مجموعة الخلفيات من اليسار لليمين (مثلا BG_0 سيكون اسم الخلفية في أقصى اليسار و BG_3 في أقصى اليمين). بعد ذلك نستدعي المكوّن Sprite Renderer ونحدد له الصورة التي سيقوم بتصييرها، وهي هنا newSprite التي سبق واستخرجناها من المصفوفة selectionList. مرة أخرى تعاملنا مع الكائن مباشرة وليس مع مكون Transform، وذلك لأن الهدف هنا هو إضافة مكون جديد له. أما الخطوتان التاليتان فهما تتعاملان مع bg.transform كما ترى، فالأولى تحدد موقعه في الفضاء gb.transform.position والثانية تحدد الكائن الأب له وهو هنا bgGameObject الذي سبق وتحدثنا عنه. بالنسبة للموقع فإن الخلفية تتوسط الشاشة عموديا كما ترى حيث y=0، أما أفقيا فالموقع هو القيمة posX التي سبق وحسبناها. من المهم هنا إدراك حقيقة أن صور الخلفية يجب أن تظهر خلف باقي الصور الموجودة في فضاء اللعبة. من أجل ذلك علينا أن نخبر مكوّن التصيير أن يقوم برسم الخلفية قبل أن يرسم أي صورة أخرى وذلك حتى لا تغطي الخلفية على عناصر المشهد. هذا الأمر يمكننا القيام به عن طريق تقليل قيمة المتغير sr.sortingOrder حيث القيمة الافتراضية هي صفر. الصور ذات القيمة الأقل للمتغير sortingOrder يتم تصييرها أولا تتبعها الصور ذات القيمة الأعلى فالأعلى. بعد ذلك نضيف مكوّن اكتشاف التصادمات Box Collider 2D حتى نتمكن من اكتشاف قيام اللاعب بلمس الخلفية أو النقر عليها بالفأرة. الخطوة الأخيرة هي زيادة posX بمقدار عرض الصورة width حتى يكون موقع الصورة التالية على يمين الحالية مباشرة وملاصقة لطرفها الأيمن. بعد بناء الخلفية نرسل رسالة أخرى هي BackgroundChanged ونرفق معها رقم عنصر الخلفية الجديدة، والتي سنرى لاحقا أهميتها. بناء نظام التحكم بالكاميرا لو قمت بتشغيل اللعبة ستلاحظ أن الكاميرا تنظر مباشرة لوسط المشهد، وما سنقوم به الآن هو إضافة آلية لتحريكها يمينا ويسارا، إضافة إلى إمكانية التقريب والإبعاد. قبل البدء في تفاصيل التحكم بالكاميرا علينا أن نحدد ما هي نسبة عرض الشاشة إلى طولها aspect ratio. هذه القيمة مهمة لأنها تؤثر مباشرة على حجم المستطيل الذي يحدد مجال رؤية الكاميرا. بما أن هذه اللعبة مصممة للهواتف وتلعب بشكل عرضي، فإن النسبة التي سنعتمدها هي 16:9، ولاختيارها انتقل من شاشة المشهد Scene إلى شاشة اللعبة Game وقم باختيار هذه النسبة من أعلى يسار الشاشة كما ترى هنا: قبل البدء في كتابة بريمج التحكم بالكاميرا، علينا أن نعرف طبيعة هذا التحكم وماذا يمكن للاعب أن يفعل من خلاله. طريقة التحكم ستكون ثنائية البعد، أي أن اللاعب سيتمكن من نحريك الكاميرا يمينا ويسارا ولأعلى وأسفل. إضافة لذلك فإن اللاعب يجب أن يكون قادرا على تقريب وإبعاد الكاميرا، وكل ذلك ضمن حدود معينة. سنطّلع بعد قليل على بريمج التحكم بالكاميرا ومن ثم نشرح بعض تفاصيله، وأخيرا سنرى كيف يمكننا ربط وظائف هذا البريمج مع مدخلات اللاعب. لكن قبل ذلك لنتعلم أحد المبادئ المهمة في برمجة الألعاب وخاصة مع محرك Unity وهي فصل الاهتمامات separation of concerns. معنى هذا أن البريمج الواحد مسؤول عن مهمة واحدة، وهو الوحيد المخول بالتحكم بتفاصيل هذه المهمة. بالتالي فإننا سنقوم أولا بكتابة بريمج للتحكم بالكاميرا، لكنه منفصل تماما عن مدخلات اللاعب. هذه المدخلات سنكتبها في بريمج آخر خاص بها، والذي سيستقبلها وبناء عليها "يطلب" من بريمج التحكم بالكاميرا تحريكها. هذا الطلب قد يستجاب له وقد لا يستجاب له وفقا لمعطيات يقدرها بريمج التحكم بالكاميرا. مثلا إذا حرك اللاعب الكاميرا لأقصى يمين المشهد ومن ثم حاول تحريكها لليمين متجاوزا حدود المشهد، فسيقوم بريمج الكاميرا برفض هذا الطلب وستبقى الكاميرا في مكانها. لنبدأ الآن مع البريمج CameraControl والذي تراه في السرد التالي، هذا البريمج يجب أن تتم إضافته إلى كائن الكاميرا حتى يقوم بالتحكم بها: using UnityEngine; using System.Collections; public class CameraControl : MonoBehaviour { //أقل حجم للكاميرا في حال التقريب public float minSize = 2.5f; //ارتفاع المستطيل المحدد لمجال الرؤية private float camHeight; //عرض المستطيل المحدد لمجال الرؤية private float camWidth; //مرجع إلى مكوّن الكاميرا Camera cam; //متغير لتخزين حدود المشهد الحالية private Bounds sceneBounds; //يتم تنفيذها مرة عند بداية التشغيل void Start () { //اجلب مكوّن الكاميرا الموجود على نفس الكائن cam = GetComponent<Camera>(); //قم بتحديث أبعاد الكاميرا UpdateCamDimensions(); } //يتم استدعاؤها مرة عند تصيير كل إطار void Update () { } //قم باستقبال الرسالة التي تخبر بتغير حدود المشهد void SceneBoundsChanged(Bounds newBounds){ sceneBounds = newBounds; } //تقوم هذه الدّالة بتحريك الكاميرا بمقدار محدد public void Move(Vector2 distance){ //قم بحساب حدود الحركة المسموحة float maxX = GetRightLimit(); float minX = GetLeftLimit(); float maxY = GetUpperLimit(); float minY = GetLowerLimit(); //يهمنا في هذه الحالة الخاصّة الموقع ثلاثي الأبعاد //z = -10 وذلك حتى نضمن أن الكاميرا في الموقع //دائما Vector3 dist3D = distance; //احسب الموقع الجديد Vector3 newPos = transform.position + dist3D; //التزم بحدود الحركة newPos.x = Mathf.Clamp(newPos.x, minX, maxX); newPos.y = Mathf.Clamp(newPos.y, minY, maxY); newPos.z = -10.0f; //قم بتغيير الموقع transform.position = newPos; } //تقوم هذه الدّالة بتغيير تقريب الكاميرا //القيمة الموجبة تعني تقريب الكاميرا من المشهد //القيمة السالبة تعني إبعاد الكاميرا عن المشهد public void Zoom(float amount){ float newSize = cam.orthographicSize - amount; //التزم بحدود التقريب والإبعاد float maxSize = GetMaxSize(); newSize = Mathf.Clamp (newSize, minSize, maxSize); //قم بتغيير حجم مجال الرؤية وبالتالي يتغير التقريب cam.orthographicSize = newSize; //قم بتحريك الكاميرا بمقدار صفر حتى تضمن تنفيذ الالتزام بحدود المشهد UpdateCamDimensions(); Move(Vector2.zero); } //تقوم بتحديث عرض وارتفاع الكاميرا void UpdateCamDimensions(){ camHeight = cam.orthographicSize * 2; camWidth = camHeight * cam.aspect; } //تحسب قيمة أعلى ارتفاع للكاميرا float GetUpperLimit(){ return sceneBounds.max.y - camHeight * 0.5f; } //تحسب قيمة أدنى ارتفاع للكاميرا float GetLowerLimit(){ return sceneBounds.min.y + camHeight * 0.5f; } //تحسب الحد الأقصى لموقع الكاميرا يمينا float GetRightLimit(){ return sceneBounds.max.x - camWidth * 0.5f; } //تحسب الحد الأقصى لموقع الكاميرا يسارا float GetLeftLimit(){ return sceneBounds.min.x + camWidth * 0.5f; } //تقوم بحساب أكبر حجم مسموح للكاميرا حين الإبعاد //وذلك اعتمادا على حدود المشهد float GetMaxSize(){ float maxHeight = sceneBounds.max.y - sceneBounds.min.y; return maxHeight * 0.5f; } } المتغير العام الوحيد في هذا البريمج هو minSize والذي يحدد أقل حجم مسموح للكاميرا عند التقريب. لشرح آلية التقريب والإبعاد لاحظ أولا أن الكاميرا لا ترى كل المشهد في كل وقت ولكن لها مجال رؤية محدد بشكل مستطيل، ويظهر هذا المستطيل حين اختيار الكاميرا كما في الشكل التالي: كلما زاد حجم هذا المستطيل فإن المساحة التي يراها من المشهد تزيد، بالتالي يبدو الأمر وكأن الكاميرا تبتعد، أما في حالة تقليل حجمه فإن العكس يحصل وهو تقليل المساحة المرئية بحيث يبدو الأمر كأن الكاميرا تقترب. يمكنك تجربة ذلك أثناء تشغيل اللعبة عن طريق تعديل قيمة المتغير size في مكوّن الكاميرا من شاشة الخصائص حيث قيمته الافتراضية هي 5. معنى هذا أننا نسمح بتقريب الكاميرا أي تصغير حجمها إلى أن يصل إلى 2.5 ويمكنك السماح بتقريبها أكثر إن قمت بتقليل هذا الرقم. المتغيران الآخران المهمان هما camHeight و camWidth ويمثلان طول وعرض المستطيل الذي يحدد مجال الرؤية، لكنهما محسوبان بقيم فضاء Unity وسنرى أهميتهما بعد قليل. أيضا نحتاج لمرجع لمكوّن الكاميرا وهو cam. تذكر ما ذكرته سابقا وهو أن المكوّنات هي التي تميز كائنا عن الآخر، ووجود هذا المكوّن هو الذي يجعل الكائن المسمى Main Camera عبارة عن كاميرا وليس شيئا آخر. أخيرا لدينا متغير من نوع Bounds وهو sceneBounds والذي سيقوم بتخزين حدود المشهد والتي سنحصر حركة الكاميرا دخلها. سأبدأ هذه المرة مع الدّالة ()SceneBoundsChanged وذلك لإكمال شرح فكرة الرسائل. بالعودة إلى البريمج BackgroundManager سترى أنه يقوم بإرسال رسالة اسمها SceneBoundsChanged ويرفقها بمتغير من نوع Bounds. إذا قمت بتعريف دالّة تحمل نفس اسم الرسالة وتأخذ متغيرا من نفس نوع المرفق، فإنك بذلك حددت هذه الدّالة كأحد مستقبلي هذه الرسالة (يمكن أن يستقبل الرسالة عدد غير محدد من البريمجات). بالتالي فالبريمج CameraControl يستقبل هذه الرسالة ويخزن قيمة الحدود الجديدة للمشهد في المتغير sceneBounds. بالعودة إلى ()Start فإن ما تقوم به هو تخزين قيمة مكوّن الكاميرا في المتغير cam ومن ثم تقوم باستدعاء ()UpdateCamDimensions والتي تحسب عرض وارتفاع الكاميرا بوحدات فضاء Unity. لنتحدث قليلا عن كيفية حساب هذه القيم. بالرجوع إلى توثيق محرك Unity وتحديدا هذه الصفحة سنعرف أن قيمة المتغير cam.orthographicSize والذي يمثل حجم الكاميرا هو عبارة عن منتصف ارتفاعها. بالتالي يمكننا ضرب هذه القيمة في 2 لنحصل على ارتفاع الكاميرا. بالنسبة لعرضها فهو يعتمد على نسبة العرض إلى الارتفاع aspect ratio، والذي يمكننا الوصول إليه عبر المتغير cam.aspect، حيث يمكننا ضرب هذا المتغير في الارتفاع لنحصل على عرض الكاميرا. بحصولنا على حدود المشهد وارتفاع الكاميرا وعرضها، يمكننا أن نحسب الحدود التي يُسمح للكاميرا بالحركة ضمنها. سيُسمح للكاميرا بالحركة يمينا إلى أن يصل طرف مستطيل مجال الرؤية الأيمن إلى أقصى حد في يمين المشهد. بالتالي فإن أقصى موقع للكاميرا يمينا هو طرف المشهد الأيمن مطروح منه نصف عرض الكاميرا. هذه القيمة نحسبها عن طريق الدّالة ()GetRightLimit، وبطريقة مشابهة نحسب الحدود الأخرى في اليسار والأعلى والأسفل عبر ()GetLeftLimit و ()GetUpperLimit و ()GetLowerLimit. لاحظ أننا في هذه الدّوال استخدمنا sceneBounds.min و sceneBounds.max وهما المتجهان اللذان يعبران عن الحد الأدنى (أسفل ويسارا) والحد الأقصى (أعلى ويمينا) لحدود المشهد. قبل الدخول في الوظائف الرئيسية للبريمج وهما التحريك والتقريب، لنتعرف على الدّالة المتبقية ضمن الدّوال المساعدة وهي ()GetMaxSize. تعمل هذه الدّالة على حساب الحد الأقصى المسموح لحجم الكاميرا حين تنفيذ الإبعاد، وذلك اعتمادا على الحدين العلوي والسفلي للمشهد إضافة لارتفاع الكاميرا. فالارتفاع الأقصى المسموح به هو المسافة بين حد المشهد الأعلى والأسفل، والحجم المسموح به بالتالي هو نصف هذه المسافة، ذلك لأن حجم الكاميرا هو نصف ارتفاعها كما سبق وعرفنا. نأتي الآن على الوظائف الأساسية لهذا البريمج وهي تحريك الكاميرا وتقريبها وإبعادها. البداية مع التحريك والذي يتم عن طريق الدّالة ()Move والتي تأخذ متجها يمثل مقدار الإزاحة التي نرغب بتحريك الكاميرا بها. أول خطوة هي حساب القيم القصوى والدنيا للحركة المسموح بها، وتخزينها في المتغيرات الأربع maxX, minX, maxY, minY. بعد ذلك نقوم بتعريف متجه ثلاثي الأبعاد هو dist3D وذلك لأن موقع الكاميرا على محور الثالث z مهم بخلاف الكائنات الأخرى، حيث يجب أن تبقى هذه القيمة سالبة أي أن الكاميرا بعيدة عن المشهد نحو الخارج وتنظر إليه داخل الشاشة. أما إذا حسبنا موقعها مستخدمين الأبعاد الثنائية فقط فإن هذا سيؤدي لضياع القيمة z للموقع وتصبح الكاميرا في الموقع z=0 وبالتالي لن يمكنها رؤية أي كائن في المشهد. بعد حساب الموقع الجديد نقوم بتخزينه في الموقع newPosition وكل ما علينا الآن هو التأكد من أن قيمة newPos.x محصورة بين minX و maxX وكذلك الأمر بالنسبة لقيمة newPos.y التي يجب أن تنحصر بين minY و maxY. لاحظ هنا استخدام الدّالة ()Mathf.Clamp والتي تقوم بالتأكد من أن الرقم الأول محصور بين الرقمين الثاني والثالث وتعيد الحد الأقصى أو الأدنى في حال كان الرقم يتجاوز هذين الحدين. أخيرا نقوم بتغيير موقع الكاميرا للموقع الجديد newPos. الوظيفة الرئيسية الثانية هي تقريب الكاميرا وإبعادها، والتي تتم عن طريق الدّالة ()Zoom، هذه الدّالة تأخذ رقما واحدا وهو مقدار التقريب (إن كان موجبا) أو الإبعاد (إن كان سالبا). طريقة التقريب والإبعاد تتم عن طريق طرح القيمة amount من حجم الكاميرا الحالي، وذلك لأن العلاقة بين حجم الكاميرا وتقريبها عكسية، فزيادة الحجم تعني تقليل التقريب. بعدها يتم حصر القيمة الجديدة بين minSize وهو المتغير الذي يمكننا تحديده كما نشاء و maxSize والذي يتم حسابه عن طريق الدّالة ()GetMaxSize التي سبق شرحها. بعد التأكد من أن الحجم الجديد ضمن الحدود يتم تغيير قيمة cam.orthogonalSize للقيمة الجديدة newSize. أخيرا يجب أن نعيد حساب أبعاد الكاميرا حيث أن حجمها تغير لذا نستدعي ()UpdateCamDimensions إضافة إلى إزاحتها بمقدار صفر احتياطا من إمكانية كون تغيير حجمها قد أدى لتجاوز حدودها لحدود المشهد خاصة في حالة الإبعاد حيث يزيد حجم الكاميرا؛ حيث أن الإزاحة بغض النظر عن مقدارها ستُبقي الكاميرا ضمن حدود المشهد دائما. بهذا تكون آلية التحكم بالكاميرا جاهزة، ويبقى علينا أن نربط استدعاء كل من ()Move و ()Zoom بمدخلات اللاعب. البداية ستكون مع الفأرة وذلك لأن المحرك يعمل على الحاسب بالتالي من السهل تجربتها مباشرة، بينما سنؤجل شاشة اللمس والهواتف الذكية لوقت لاحق. تحريك الكاميرا سيتم عن طريق الضغط بزر الفأرة الأيسر على الخلفية ومن ثم تحريكها في الاتجاهات الأربع، بينما يستخدم الزر الأيمن للتقريب والإبعاد، حيث يضغط اللاعب بالزر الأيمن ويحرك الفأرة لليمين للتقريب ولليسار للإبعاد. هذه الوظائف سيقوم بها البريمج CameraMouseInput والذي يجب أن نضيفه لقالب الخلفية BGElement، حيث يجب أن تكون كل صور الخلفية قادرة على استقبال مدخلات الفأرة. فيما يلي سرد بهذا البريمج. using UnityEngine; using System.Collections; public class CameraMouseInput : MonoBehaviour { //سرعة حركة الكاميرا public float movementSpeed = 0.1f; //سرعة التقريب والإبعاد public float zoomingSpeed = 0.01f; //أثناء التقريب والإبعاد trueتكون قيمة هذا المتغير private bool zoomingAcitve = false; //تقوم بتخزين موقع مؤشر الفأرة في الإطار السابق private Vector2 lastPosition; //مرجع لبريمج التحكم بالكاميرا private CameraControl camControl; //يتم تنفيذ هذه الدّالة مرة عند بداية التشغيل void Start () { //اجلب بريمج التحكم بالكاميرا camControl = FindObjectOfType<CameraControl>(); } //يتم استدعاؤها عند تصيير كل إطار لكن في وقت متأخر void LateUpdate () { UpdateZooming(); } //تقوم بقراءة مدخلات التقريب والإبعاد void UpdateZooming(){ //قم بفحص الضغط على زر الفأرة الأيمن if(Input.GetMouseButtonDown(1)){ zoomingAcitve = true; lastPosition = Input.mousePosition; } //قم بتحديث التقريب والإبعاد بناء على الحركة الأفقية للفأرة if(zoomingAcitve){ float amount = Input.mousePosition.x - lastPosition.x; camControl.Zoom(amount * zoomingSpeed); lastPosition = Input.mousePosition; } //عند رفع الضغط عن زر الفأرة الأيمن false إلى zoomingActive قم بإرجاع قيمة if(Input.GetMouseButtonUp(1)){ zoomingAcitve = false; } } //يتم استدعاء هذه الدّالة عند الضغط بزر الفأرة الأيمن على الكائن void OnMouseDown(){ //لا تسمح بالحركة أثناء التقريب والإبعاد if(!zoomingAcitve){ lastPosition = Input.mousePosition; } } //يتم استدعاء هذه الدّالة عند السحب بزر الفأرة الأيسر فوق الكائن void OnMouseDrag(){ //امنع الحركة أثناء التقريب والإبعاد if(!zoomingAcitve){ Vector2 movement = lastPosition - (Vector2)Input.mousePosition; camControl.Move(movement * movementSpeed); lastPosition = Input.mousePosition; } } } كما ذكرت سابقا يجب أن تتم إضافة هذا البريمج على قالب صور الخلفية، وذلك لأن اللاعب سيضغط عليها بالفأرة إذا أراد تحريك الكاميرا. عند بداية تشغيل البريمج فإنه يبحث في المشهد عن البريمج الذي يتحكم بالكاميرا CameraController وذلك عن طريق ()FindObjectOfType، وبما أن هذا البريمج موجود مرة واحدة في المشهد بالتالي ستكون نتيجة البحث هي قطعا البريمج الموجود على الكاميرا. بالتالي يمكننا الآن استخدام المتغير camController للتحكم بالكاميرا. عندما يضغط اللاعب بزر الفأرة الأيسر على كائن ما يتم إرسال الرسالة OnMouseDown مرة واحدة إلى ذلك الكائن، لذا فإننا هنا نستقبل هذه الرسالة عبر الدّالة التي تحمل نفس الاسم حيث نقوم بتخزين موقع الفأرة الحالي في المتغير lastPosition. إذا بقي اللاعب ضاغطا على الزر الأيسر وقام بتحريك الفأرة، فحينها يتم إرسال الرسالة OnMouseDrag إلى الكائن في كل إطار يتم فيه تحريك المؤشر أثناء الضغط. في الدّالة ()OnMouseDrag نقوم بثلاثة أشياء: أولا نحسب مقدار الإزاحة عن موقع الضغط وذلك بطرح الموقع الحالي من الموقع السابق. بهذه الطريقة فإننا نجعل حركة الكاميرا معاكسة لحركة المؤشر، فإن تحرك المؤشر يمينا تتحرك الكاميرا يسارا، مما يعطي اللاعب شعورا بأنه لا يحرك الكاميرا، وإنما يمسك المشهد ويحركه يمينا ويسارا وهذه الطريقة أسهل عليه في التحكم خاصة مع شاشة اللمس. الخطوة الثانية هي استدعاء الدّالة ()Move وتزويدها بمقدار الإزاحة المحسوبة مضروبة في سرعة الحركة. لاحظ أن سرعة الحركة قليلة نسبيا وذلك لأن قيمة إزاحة الفأرة عالية مقارنة مع مقدار الإزاحة المطلوبة للكاميرا. أخيرا وبعد تنفيذ الإزاحة نقوم بتخزين موقع المؤشر الحالي في lastPosition حتى نكون جاهزين لحساب الإزاحة القادمة انطلاقا من الموقع الجديد. لاحظ أن جميع الخطوات في الدّالتين ()OnMouseDown و ()OnMouseDrag مشروطتان بأن تكون قيمة zoomingActive هي false. هذا المتغير يخبرنا ما إذا كان اللاعب يقوم حاليا بتقريب أو إبعاد الكاميرا مستخدما الزر الأيمن، وبذلك نمنع التحريك والتقريب في آن واحد. الدّالة ()LateUpdate التي عرّفناها هنا بدلا من ()Update تختلف عن هذه الأخيرة في شيء واحد، وهو أنها تُستدعى متأخرة عنها. فعند تحديث كل إطار يقوم Unity بتحديث جميع البريمجات عن طريق استدعاء ()Update ومن ثم يعاود التحديث مجددا باستخدام ()LateUpdate. بالتالي فإن استدعاء أي خطوات خلال ()LateUpdate هو مضمون أن يتم تنفيذه بعد تحديث جميع عناصر المشهد من خلال ()Update. الفائدة من ذلك هو أن نضمن أن كل العناصر أصبحت جاهزة للإطار الجديد قبل أن نقوم بتحريك الكاميرا، بالتالي عادة ما يتم استخدام ()LateUpdate مع أي شيء له علاقة بالتحكم بالكاميرا. ما نفعله في ()LateUpdate هو استدعاء ()UpdateZooming والتي تفحص ما إذا ضغط اللاعب على زر الفأرة الأيمن عن طريق الدّالة ()Input.GetMouseButtonDown والتي تفحص أزرار الفأرة بناء على أرقامها؛ فالرقم 0 للأيسر و 1 للأيمن و 2 للأوسط. أول ما نقوم به عند اكتشاف الضغط على الزر الأيمن هو تغيير قيمة zoomingActive إلى true مما يمنع استقبال مدخلات التحريك. بعدها نقوم بتخزين الموقع الحالي للمؤشر في lastPosition تماما كما فعلنا مع حالة الضغط بالزر الأيسر. بناء على قيمة zoomingActive نقوم بتحديث التقريب والإبعاد، فنحسب قيمة الإزاحة الأفقية بطرح الإحداثي x للموقع السابق من الإحداثي x للموقع الحالي، فإذا تحرك مؤشر الفأرة يمينا ستكون النتيجة موجبة مما يجعل قيمة amount * zoomingSpeed المزودة للدّالة ()camControl.Zoom موجبة وينتج عنه تقريب الكاميرا، والعكس يحدث حين تحريك الفأرة يسارا. بعد تحديث قيمة التقريب نقوم بتخزين الموقع الحالي في lastPosition من أجل حساب الإزاحة القادمة. آخر خطوة في هذه الدّالة هي فحص ما إذا كان اللاعب قد رفع الضغط عن زر الفأرة الأيمن وإعادة قيمة zoomingSpeed إلى false في هذه الحالة. بناء أرضية المشهد بعد أن انتهينا من تجهيز خلفية المشهد وأصبحنا قادرين على تحريك الكاميرا للتجول فيه بحرية، حان الوقت لإضافة عناصر المشهد، وهي الكائنات ثنائية الأبعاد التي سنبني منها اللعبة. ستكون البداية مع الأرضية التي ستقف عليها باقي الكائنات، والتي سنبنيها بطريقة مشابهة لطريقة بناء الخلفية. سنقوم أولا بإضافة كائن فارغ كابن للكائن الجذري ونسميه Ground. هذا الكائن سيكون أبا لجميع كائنات الأرضية. بعدها سنقوم بإنشاء قالب خاص بكائنات الأرضية ونضيف له المكوّن sprite renderer والبريمج CameraMouseInput، مما يجعل التحكم بالكاميرا عن طريق الضغط على الأرضية ممكنا تماما كما هو الحال مع الخلفية. سنسمي هذا القالب GroundElement ومن ثم سنكتب البريمج الذي يعمل على إضافة كائنات الأرضية اعتمادا على الخلفية وحدود المشهد. هذا البريمج هو GroundManager والموضح في السرد التالي، علما أن هذا البريمج يجب أن نضيفه أيضا للكائن الجذري SceneRoot. using UnityEngine; using System.Collections; public class GroundManager : MonoBehaviour { //قالب كائن عناصر الأرضية public GameObject gePrefab; //مصفوفة بصور الأرضية المتوفرة public Sprite[] selectionList; //متغير لتخزين حدود المشهد الحالية private Bounds sceneBounds; //موقع صورة الخلفية المعروضة حاليا private float selectedIndex = -1; //تستدعى مرة واحدة عند بداية التشغيل void Start () { } //تستدعى مرة واحدة عند تصيير كل إطار void Update () { } //تقوم باستقبال رسالة تغير صورة الخلفية void BackgroundChanged(int newIndex){ ChangeGround(newIndex); } //تقوم باستقبال رسالة تغير حدود المشهد void SceneBoundsChanged(Bounds newBounds){ sceneBounds = newBounds; } //تقوم بتغيير صورة الأرضية المعروضة بناء على رقم العنصر المحدد public void ChangeGround(int newIndex){ //"Ground" ابحث عن الكائن الابن المسمى Transform groundGameObject = transform.FindChild("Ground"); //قم بحذف عناصر الأرضية الحالية for(int i = 0; i < groundGameObject.childCount; i++){ Transform ge = groundGameObject.GetChild(i); Destroy(ge.gameObject); } //قم بحساب عرض المشهد float sceneWidth = sceneBounds.max.x - sceneBounds.min.x; //قم بحساب النقطة في أقصى اليسار float posX = sceneBounds.min.x; //قم بجلب صورة الأرضية من المصفوفة Sprite newGround = selectionList[newIndex]; //قم بحساب عرض وارتفاع صورة الأرضية float width = newGround.rect.width; float height = newGround.rect.height; //قم بحساب العرض والارتفاع بالوحدات width = width / newGround.pixelsPerUnit; height = height / newGround.pixelsPerUnit; //قم بحساب الموقع العمودي للأرضية float posY = sceneBounds.min.y + height * 0.5f; //كم مرة يجب أن نكرر صورة الأرضية؟ int repeats = Mathf.RoundToInt(sceneWidth / width) + 1; for(int i = 0; i < repeats; i++){ //قم بإضافة كائن عنصر أرضية جديد GameObject ge = (GameObject) Instantiate(gePrefab); ge.name = "GE_" + i; //ضع الكائن في الموقع الصحيح ge.transform.position = new Vector2(posX, posY); //قم بتحديد الأب ge.transform.parent = groundGameObject; //قم بوضع الصورة على مكوّن تصيير الكائن الذي أضفناه SpriteRenderer sr = ge.GetComponent<SpriteRenderer>(); sr.sprite = newGround; //قم بإضافة مكوّن التصادم ge.AddComponent<BoxCollider2D>(); //قم بزيادة قيمة الموقع الأفقي استعدادا للعنصر التالي posX += width; } } } ما نلاحظه للوهلة الأولى هو التشابه الشديد بين GroundManager و BackgroundManager حثي أن كلا منهما يقوم ببناء عدة كائنات مستخدما قالبا محددا ومن ثم رص هذه الكائنات بجانب بعضها البعض من اليسار لليمين. الفرق هنا هو أن هذا البريمج يعتمد في عمله على استقبال الرسالة BackgroundChanged بحيث يختار صورة الأرضية الموجودة في الموقع المساوي لموقع الخلفية التي تم اختيارها. معنى ذلك أنه لصور الخلفية الثمانية الموجودة سنحتاج لصور ثماني أرضيات. صور الأرضيات موجودة في المجلد Other في مجموعة الصور وعددها هو 4 كما ترى في الصورة التالية، مما يعني أن نفس الأرضية يمكن أن تتكرر مع أكثر من خلفية: أول خطوة علينا القيام بها هي تغيير نقطة الارتكاز لهذه الصور الأربعة بحيث تصبح في اليسار تماما كما فعلنا مع صور الخلفية. ومن ثم سنقوم بسحبها إلى المواقع الثمانية داخل المصفوفة selectionList. أثناء إضافتي لصورة الأرضية المقابلة لكل خلفية، حاولت أن أختار لونا متميزا عن لون الجزء الأسفل من الخلفية، بحيث يسهل على اللاعب تمييز أرضية المشهد عن خلفيته، وكانت النتيجة كالتالي. لا تنس أيضا بعد إضافة البريمج للكائن SceneRoot أن تقوم بتحديد القالب GroundElement ليكون هو مصدر بناء كائنات الأرضية. اختلاف آخر بين البريمجين نلحظه في موقع وضع الكائنات، حيث توضع كائنات الخلفية عموديا في المنتصف بينما توضع كائنات الأرضية في الأسفل. الفرق الآخر المهم هو أن عدد مرات التكرار بالنسبة للخلفية متغير يمكننا تحديد قيمته، بينما في حالة الأرضية يتم حسابه تلقائيا بقسمة عرض المشهد على عرض صورة الأرضية، ومن ثم إضافة 1 لتغطية أي ثغرة متبقية في أقصى اليمين نتيجة للكسور. إلى هذه النقطة نكون قد انتهينا من بناء الخلفية والأرضية، بالتالي لو حاولنا تشغيل اللعبة الآن سنحصل على النتيجة التالية: قمنا في هذا الدرس بتجهيز الخلفية و الأرضية للعبة كما قمنا بالتحكم في الكاميرا. في الدرس القادم سنقوم بإنشاء الوحدات البنائية للعبة. اقرأ أيضًا تعرف على أشهر لغات برمجة الألعاب
  17. سنقوم بتصميم أحد قطع (أحجار) الشطرنج وهو البيدق. هناك العديد من الطرق لتصميم البيدق ولكننا اليوم سنتعلم طريقة سهلة وبسيطة في برنامج التصميم ثلاثي الأبعاد 3D MAX. افتح برنامج 3DS MAX وارسم أسطوانة Cylinder كما في الصورة. عدّل خصائص هذه الأسطوانة بحيث يكون نصف القطر 16، الارتفاع 2، عدد أقسام الارتفاع 1، عدد أقسام السطح 1 وعدد الجوانب 30. سنقوم الآن بتحويل هذه الأسطوانة إلى مجسّم مضلعات POLY (بولي) وذلك لنتمكن من تعديلها ونمذجتها كما نشاء. تأكّد من أن قائمة المُعدِّلات Modifier هي المفتوحة في القائمة اليمنى من البرنامج لأن العمل سيكون بالكامل عليها. اختر خاصية التعديل على الأسطح (المضلعات) Polygon ثم حدّد سطح الأسطوانة العلوي. في قائمة خصائص البولي على اليمين ابحث عن خيار Inset ثم اضغط على المربع الصغير بجانبه لتظهر خصائص هذه العملية فوق المجسّم. ضع القيمة 3 واضغط على إشارة موافق. الآن حدّد أدوات التحريك من شريط الأدوات العلوي، وبما أن السطح ما زال محدّدًا، قم بتحريكه للأعلى على المحور عموديًّا قليلًا. مع استمرار تحديد السطح، قم بحذفه عبر الضغط على مفتاح Delete من لوحة المفاتيح. اختر خاصية التعديل على الحدود Border ثم حدّد الحدود المفتوحة أعلى شكل المجسّم. والآن سنبدأ عملية التشكيل السريعة والبسيطة والسهلة لهذا المجسّم. كما في الكثير من برامج التصميم كالإليستريتور والفوتوشوب من الممكن نسخ أي عنصر تمّ تحديده عبر الاستمرار بالضغط على أحد مفاتيح لوحة المفاتيح ثم سحب هذا العنصر بالفأرة ليتم نسخه إلى الموقع الجديد. هذا الأمر ينطبق هنا على هذه الحدود التي حدّدناها حيث سنضغط على المفتاح Shift ثم سنسحب بالفأرة هذه الحدود عموديًّا على المحور الشاقولي للأعلى كما في الصورة. وبذلك ستبقى الحدود القديمة ويتم سحب نسخة عنها مرتبطة معها ومتصلة بها، وهو ما يشكّل امتدادًا للشكل المجسّم. الآن استخدم أداة تغيير الحجم من شريط الأدوات العلوي (ستجده بالقرب من أداة التحريك) ثم كبّر هذه الحدود أفقيًّا على المحورين الأفقيين ليتم تكبير هذه الحدود بشكل متناظر ومتناسب، وأسهل طريقة للقيام بذلك هي عبر منظور TOP لنحصل على هذه النتيجة. مجدّدًا استخدم أداتي التحريك وتغيير الحجم مع الضغط على مفتاح Shift لتمديد الشكل كما في الصورة. والآن اسحب نسخة جديدة شاقوليًّا للأعلى بدون أي تغيير في الحجم. قم بسحب نسخة جديدة للأعلى وصغّر حجم الفتحة بذات الطريقة. مدّد نسخة جديدة للأعلى أكثر مع التصغير بشكل طفيف. كرّر العملية السابقة ولكن اجعل التمديد للأعلى أكبر هذه المرّة. والآن مدّد نسخة جديدة لمسافة قصيرة جدًّا وكبّر حجم الفتحة بشكل كبير هذه المرّة. مدّد نسخة أخرى عن هذه الفتحة الكبيرة الجديدة للأعلى قليلًا بدون أي تغيير في الحجم. مدّد نسخة جديدة لمسافة أكبر من السابقة بقليل مع تصغير الفتحة لتعود للحجم الصغير كما في الخطوة السابقة. الآن ارسم كرة Sphere بنصف قطر 7 وبعدد أقسام يصل إلى 32. حجم الكرة يمكن أن يكون مختلفًا وذلك لأننا لم نقم بتصميم دقيق بحسب أبعاد محدّدة في الخطوات السابقة، إلا أنّ حجم الكرة يبقى تقديريًّا بحسب الفتحة التي وصلتَ إليها في النهاية وبحسب حجم المجسّم بشكل عام، بحيث تكون هذه الكرة مناسبةً كرأسٍ للبيدق. المهم أن تتأكّد من أن الكرة متداخلة بشكل بسيط مع المجسم حتى لا يكون هناك أية فراغات أو فجوات في التصميم. سنقوم بدمج هذه الكرة مع شكل المجسّم. حدّد شكل المجسّم ثم اضغط على خيار Attach ضمن قائمة خصائص البولي في القائمة اليمنى ثم انقر على الكرة وبذلك سيتّحد العنصران معًا في نموذج واحد. سنقوم بشطب بعض الحواف عبر الخاصية Chamfer. قم باختيار خاصية تعديل الحواف Edge ثم حدّد الحواف الواضحة في الصورة. اضغط على المربع الصغير الذي بجانب الخيار Chamfer لتظهر خيارات هذه الميزة فوق شكل النموذج. ضع القيمة 0.05 فقط ثم اضغط على إشارة موافق. وبهذا نكون قد انتهينا من تصميم هذا النموذج بشكل كامل. ولكن هذا النموذج يبدو مضلّعًا أكثر من اللازم لذلك سنحتاج إلى تنعيمه. حدّد النموذج ثم ابحث في قائمة المُعدِّلات عن مُعدِّل التنعيم MeshSmooth واضغط عليه ليتم تطبيق هذا المُعدِّل على النموذج ثم ضع قيمة التكرار Iterations القيمة 2. كما لاحظت في هذا الدرس استخدمنا مُعدِّلًا واحدًا فقط ونحو ثلاثة مزايا لمرّات قليلة وهي Chamfer ،Inset و Attach بينما كان معظم العمل يدويًّا سهلًا وسريعًا عبر استخدام أداوت التحريك وتعديل الحجم، والعمل بهذه الطريقة يشبه اللعب بالصلصال. بالإمكان إنشاء العديد من النماذج باستخدام هذه الطريقة، حتى أن معظم النماذج كالوحوش والمخلوقات الغريبة يتم تصميمها بمثل هذا الأسلوب.
  18. قطع التركيب أو ما يسمى باللغة الإنجليزية Puzzle من الألعاب المشهورة والمفيدة للأطفال في الواقع، أما في مجال التصميم فتعلم طريقة تصميمها يرجع بالفائدة على المصمم لتعدد استخداماتها، وسنتناول في هذا المقال إحدى طريق الحصول عليها. الخطوات بأداة المربع والمستطيل ارسم مع الضغط على Ctrl أثناء الرسم ليعطينا الشكل المربع، واجعله بزوايا مستديرة عن طريق تحريك الدائرة في زاويته العلوية اليمنى للأسفل قليلا. مقاس الطول والعرض للمربع 300 تقريبا، كما تلاحظ في الشريط العلوي للأداة. بأداة الرسم المنحني Bezier tool ارسم خطا بالضغط على شاشة الرسم حيث موضع العقدة الأولى ثم اسحب إلى موضع العقدة الثانية مع الضغط على Ctrl أثناء السحب للمحافظة على استقامة الخط دون ميلان، ثم اضغط عند موضع العقدة الثانية، ولإنهاء رسم الخط اضغط على زر الإدخال Enter من لوحة المفاتيح. من تبويب سمة الحد Stroke style في لوحة التعبئة والحدود Fill and stroke سنختار قيمة عرض الخط 4. من لوحة المحاذاة والاصطفاف Align and distribute نحاذي الخط وسط المربع، فنختار المستطيل أولا ثم المربع تاليا مع الضغط على Shift أثناء التحديد ونحاذيهما عاموديا وأفقيا، مع التأكد من وجود خيار Last selected أعلى اللوحة لتتم المحاذاة بالنسبة لآخر عنصر تم اختياره. نختار أداة التحرير Node tool ثم نحدد الخط ونضيف عقدة Node عن طريق خيار Insert new Nodes بين العقدتين الأصليتين من شريط الأداة، ثم نختار الجزء يمين العقدة الجديدة، ونضيف عقدة جديدة مرة أخرى. نضيف عقدة للجزء أيمن العقدة التي أنشأناها للتو وعقدة أيسرها، بحيث يكون عندنا ثلاث عقد في الجزء الأيمن للخط، ثم نحدد الثلاث عقد الجديدة بسحب مؤشر السهم حولها أو الاستعانة بزر Shift أثناء التحديد، ومن لوحة المفاتيح نضغط على الاختصار Ctrl+< لتضييق المسافة بين العقد. ملاحظة: لتكبير مساحة الرسم أو تصغيرها استعن بعلامتي + و – من لوحة المفاتيح. ألغ تحديد العقد عن طريق الضغط على المساحة البيضاء، ثم حدد العقدة الوسطى فقط من بين العقد الثلاثة، وارفعها للأعلى عن طريق أسهم التحكم في لوحة المفاتيح للمحافظة على استقامتها. ملاحظة: إذا كان خيار الالتقاط والكبس مفعّلا فألغ تفعيله من الشريط العلوي عن طريق إلغاء خيار Enable snapping لحرية التعديل على العقد في الخطوات القادمة. اختر من الشريط العلوي لأداة التحرير خيار Make selected Nodes symmetric لجعل العقدة متناسبة بمعنى أننا عندما نسحب الذراع الأيمن للعقدة Node handle فإن الذراع الأيسر يسحب في الجهة المقابلة بشكل متناسب، لذا اسحب أحد الذراعين مع الضغط على Ctrl لتكوين الانحناء المطلوب. أضف عقدتين جهة اليمين واليسار في المساحة المنحنية، ثم حدد العقدتين الجديدتين، ومن لوحة المفاتيح نضغط على Ctrl+> لتوسيع المساحة بين العقدتين، ثم ارفع العقدة الوسطى للأعلى قليلا عن طريق أسهم التحكم من لوحة المفاتيح. إذا حصلنا على الشكل المناسب للمنحنى سنرسم بأداة Bezier خطا عاموديا ونحاذيه مع المربع عاموديا وأفقيا من لوحة المحاذاة والاصطفاف، ثم نختار الخط الأول ذا المنحنى والخط الثاني الذي رسمناه توًا، ومن قائمة المسار Path نحولهما إلى مسار عن طريق Stroke to Path. تأكد من كون الخطين ما زالا محددين ثم اختر من قائمة المسار خيار التقسيم division ليقسم لنا الخط الأول لثلاث قطع، ثم احذف القطعة الثالثة اليسرى. لملاحظة القطعة الثانية الصغيرة -والتي هي عبارة عن موضع تقاطع الخطين مسبقا- كبر مساحة الرسم. حدد كلا القطعتين ومن قائمة المسار اختر Union لتوحيدهما في قطعة واحدة. فعّل من الشريط العلوي خيار الالتقاط Enable snapping ومن خيار التقاط النقاط الأخرى Snap other point فعّل خيار التقاط مركز دوران الشكل Snap an item's rotation center. ثم اختر القطعة التي وحدناها للتو إن لم تكن محددة، ثم حددها مجددا لتظهر أسهم التدوير ومركز الدوران على شكل +، واسحب مركز الدوران إلى مركز المربع ليتم التقاطه من مركز دوران المربع. كرّر الخط عن طريق الضغط بالزر الأيمن ثم اختيار Duplicate ثم بأسهم التدوير مع الضغط على Ctrl أثناء التدوير للتحكم بمقدار الدوران؛ دوّره بشكل رأسي، وكرّره مجددا بحيث تقابل النسخة الثالثة الشكل الأول وتقابل النسخة الرابعة النسخة الثانية. قم بتحديد الخطوط الأربعة ثم من قائمة المسار اختر Union لتوحيدها معا. حدد الخطوط الموحدة والمربع بسحب مؤشر السهم حولها جميعا ثم من قائمة المسار اختر أمر الفرق Difference لتتشكل فراغات في المربع مكان الخطوط. حدد المربع ذا الفراغات ومن قائمة المسار اختر Break apart لتقسيمه لأجزاء بحيث تكون كل قطعة منفصلة عن الأخرى. لوّن كل قطعة باللون المناسب من لوحة التعبئة والحدود أو من شريط الألوان السفلي. القيم التي اخترناها للرسمة حسب ترتيبها من اليمين إلى اليسار: e57b3fff ،75b1aaff ،c5a64cff ،ed545bff يمكنك نسخها ولصقها في خانة RGBA في تبويب التعبئة Fill في لوحة التعبئة والحدود أو اختيار اللون الذي ترغب به. حصلنا على قطع التركيب Puzzle إلا أننا نرغب بإضافة بعد ثالث للقطع، لذا سنكرّر القطع الأربعة ونسحبها أسفل القطع الأولى مع الضغط على Ctrl أثناء التحريك لتبقى محاذية للنسخة الأصل. كرّر القطع الأربعة مجددا ولوّنها باللون الأسود وأعطها شفافية Opacity بقية 20 أو قريبة منها، ثم حرك القطع الأربعة معا اتجاه الأسفل لخطوة أو أكثر وكذلك في اتجاه اليسار عن طريق أسهم التحريك في لوحة المفاتيح. أعد القطع الأربعة السوداء لأقصى الخلف عن طريق خيار Lower selection to bottom من الشريط العلوي. حدد إحدى القطع مع ظلها ولتكن الحمراء واستعن لتحديدهما معا بزريّ Shift و Alt للوصول للقطعة الخلفية، ثم قم بإبعادها عن بقية القطع وتدويرها. ارسم مربعا عن طريق الضغط على Ctrl أثناء رسمه كخلفية للقطع ثم أرسله للخلف، ولوّنه باللون الرمادي، وبعد تحديد المربع مع جميع القطع بسحب مؤشر الفأرة حولها للتأكد من تحديد ظلالها معها، قم بتدويرها عن طريق أسهم التدوير مع الضغط على Ctrl أثناء التدوير إلى أن تعطينا شكل المعين. عد لأسهم التحديد عن طريق الضغط مجددا على الأشكال، ثم اسحب السهم العلوي المتوسط للأسفل ليتشكل عندنا البعد. كرّر المربع مجددا ولوّنه بلون أقتم، ثم أرسله للخلف وحركه للأسفل حيث ترغب أن يكون ارتفاع المربع، مع الضغط على Ctrl أثناء التحريك للمحافظة على محاذاته للمربع الأصل. فعّل من شريط الالتقاط والكبس خيار Snap cusp Node لالتقاط العقد الحادة، ثم بأداة Bezier ارسم مستطيلا يصل بين العقد الوسطى للمربعين. حدد المستطيل مع المربع القاتم السفلي ومن قائمة المسار اختر Union لتوحيدهما. في حال رغبنا بإعطاء قطع التركيب مساحة للكتابة داخلها مثلا، يمكننا العودة للنسخة الأولى من القطع وعن طريق أداة التحرير نختار العقد الطرفية اليمنى للقطع اليمنى ونحركها بالسهم الأيمن من أسهم التحكم في لوحة المفاتيح، وبالعكس في القطع اليسرى حيث نحركها يسارا بعد اختيار العقد الأربع اليسرى. بأداة الكتابة يمكننا إضافة ترقيم للقطع مع اختيار اللون والحجم المناسب من الشريط العلوي لأداة الكتابة. النتيجة النهائية النص العربي المستخدم في التصميم بخط جذور.
  19. تُعتبر الأشكال من العناصر المهمة التي تضيف عامل جذب بصري عند إضافتها إلى العروض التقديمية. وهي تُستخدم لتوضيح نقطة معيّنة أو التأكيد عليها، أو لمجرد إضافة لمسة فنية تجذب انتباه القارئ/المشاهد. بالرغم من توفر مجموعة كبيرة من الأشكال الجاهزة التي يمكن تخصيصها بتغيير ألوانها، أحجامها، تأثيراتها، إلخ، إلا أنّه في بعض الأحيان نحتاج إلى أشكال مخصصة، وهذا ما سنتعلّمه في هذا الدرس. إنشاء شكل ثلاثي الأبعاد إذا كنا نرغب في إنشاء شكل ثلاثي الأبعاد علينا أولا أن نقوم بإدراج الشكل ثنائي الأبعاد. نذهب إلى تبويب: إدراج Insert > أشكال Shapes ثم ننقر على الشكل المرغوب من قائمة الأشكال الافتراضية: بعد اختيار الشكل نقوم برسمه داخل الشريحة بالنقر والسحب، وحسب الحجم والموضع المرغوب: نلاحظ ظهور تبويب تنسيق Format السياقي، ومنه يمكننا الوصول إلى العديد من الخيارات الخاصة بتنسيق الشكل، لكن ما يهمنا هنا هو أمر تأثيرات الشكل Shape Effects وبالأخص خيار الاستدارة ثلاثية الأبعاد D3 Rotation: نمرر المؤشر فوق نماذج الاستدارة لمعاينتها بشكل مباشر، وعندما نحدد النموذج المناسب ننقر عليه لاختياره: كما هو واضح في الصورة أعلاه، على الرغم من تطبيق تأثير الاستدارة ثلاثية الأبعاد على الشكل إلا أنّه ما يزال ثنائي الأبعاد، وذلك لأن الشكل يفتقر إلى سمة الأشكال ثلاثية الأبعاد؛ وهو العمق أو السمك Depth. لكي نعطي للشكل مظهرا أقرب إلى الأشكال ثلاثية الأبعاد يجب أن نقوم بفتح جزء تنسيق الشكل (وهو نفسه مربع الحوار تنسيق الشكل Format Shape في الإصدارات الأقدم من 2013 من بوربوينت). ننقر على أيقونة مشغل جزء تنسيق الشكل الموجودة في زاوية مجموعة أنماط الشكل Shape Styles من تبويب تنسيق Format: أو ننقر على الشكل بزر الفأرة الأيمن ونختار Format Shape: وفي كلا الحالتين سيُفتح جزء (أو مربع الحوار) تنسيق الشكل. الخيارات التي تهمنا هنا هي التنسيق ثلاثي الأبعاد 3D Format والاستدارة ثلاثية الأبعاد 3D Rottion والموجودة ضمن تبويب التأثيرات Effects: في قسم الاستدارة ثلاثية الأبعاد يمكننا تعديل دوران الشكل حول المحاور X ،Y، وZ يدويا بالنقر على أزار التدوير إلى اليمين Right أو اليسار Left، إلى الأعلى Up أو الأسفل Down، أو باتجاه عقارب الساعة Clockwise أو عكسها Counter-Clockwise. أو بإمكاننا إدخال قيمة الاستدارة في الحقول المخصصة لكل محور: وكذلك توجد النماذج ذات الإعدادات المسبقة Presets نفسها تلك الموجودة ضمن أمر تأثيرات الشكل في تبويب تنسيق السياقي. من قسم التنسيق ثلاثي الأبعاد يمكننا إضافة بعد ثالث للشكل ليصبح ذو عمق ومظهر ثلاثي الأبعاد. يكون عمق جميع الأشكال في بوربوينت مساويًا للصفر بشكل افتراضي، لكن يمكننا تعديل العمق وإدخال قيم تتراوح بين 0 – 1584 نقطة. نستخدم السهم العلوي لزيادة العمق، أو السفلي لتقليله، أو إدخال قيمة مخصصة في حقل الحجم الخاص بالعمق: يمكننا أيضا أن نقوم بتغيير لون السمك واختيار لون مخالف للون واجهة الشكل: توجد خيارات أخرى يمكننا تعديلها، كلون محيط الشكل Contour وحجمه: وكذلك نوع مادة الشكل Material، إذ توجد العديد من الخيارات، كالمعدن، البلاستيك، أو تأثيرات خاصة، كالحواف الداكنة أو الناعمة، أو حتى إطار هيكلي: يمكننا أيضا أن نتحكم بإضاءة الشكل Lightening وزاوية الإضاءة. توجد نماذج مسبقة لإضاءة حيادية، دافئة، هادئة، إلخ: إذا، لإنشاء شكل ثلاثي الأبعاد، كل ما عليك فعله هو الذهاب إلى جزء تنسيق الشكل والتلاعب بإعدادات التنسيق ثلاثي الأبعاد والاستدارة ثلاثية الأبعاد إلى أن تحصل على الشكل المرغوب: رسم شكل حر إذا كنت ترغب في إدراج شكل مخصص غير موجود ضمن قائمة الأشكال المسبقة، يمكنك استخدام أداة الشكل الحر Freeform أو أداة الخربشة Scribble. تُستخدم أداة Freeform لرسم أشكال تحتوي على خطوط مستقيمة وخطوط منحنية معا: أما أداة Scribble فتُستخدم لرسم خطوط أو أشكال انسيابية شبيهة بالرسم اليدوي باستخدام القلم: لرسم شكل باستخدام أداة Freeform، ننقر على أي منطقة داخل الشريحة لتحديد بداية الخط، ثم نحرّك الفأرة باتجاه موقع آخر وننقر مرة أخرى لرسم الخط، وهكذا نرسم مجموعة الخطوط (أو المنحنيات) التي تشكّل الشكل الذي نرغب في رسمه: عند الانتهاء من رسم الخطوط، ننقر بشكل مزدوج لإلغاء تفعيل أداة Freeform. إذا لم نقم بإغلاق الشكل، كما في المثال أعلاه، سيكون الشكل عبارة عن مجموعة خطوط يمكننا تغيير لونها من تبويب تنسيق Format السياقي. ومع أنّها مجموعة خطوط، إلا أنّه بالإمكان تعبئتها بلون مخصص تماما كما نفعل في الأشكال المغلقة، وفي هذه الحالة سيقوم البرنامج بإغلاق الشكل لتعبئته: أما إذا قمنا بإغلاق الشكل، أي أنّ نقطة النهاية ستكون نفسها هي نقطة البداية، سيقوم البرنامج بتعبئة الشكل تلقائيا: يمكننا بعد ذلك تغيير لون التعبئة من تبويب تنسيق إن رغبنا في ذلك. في بعض الأحيان تحتاج إلى تحويل صورة أو رسم إلى شكل إذا كنت تريد تعديل هذه الصورة باستخدام خيارات الشكل. يمكنك في هذه الحالة رسم الشكل بتعقّب تفاصيل الصورة. مثلا في الصورة أدناه، لدينا شعار أكاديمية حسوب بهيئة صورة (نعرف هذا من خلال تبويب Format الخاص بتنسيق الصور)، وما نريده هو تحويل هذه الصورة إلى شكل بحيث نتمكن من تعبئته بلون مخصص، تحويله إلى شكل ثلاثي الأبعاد، إضافة حركة Animation لكل جزء من الشعار، أو غيرها من خيارات تنسيق الأشكال: سنقوم أولا برسم الحدود الخارجية باستخدام أداة Freeform: ثم سنغير تعبئة الشكل الكبير إلى بلا تعبئة No Fill لنتمكّن من رسم الجزء الداخلي. عند ارتكاب خطأ ما أثناء تتبّع حدود الصورة، يمكننا دائما التراجع عن هذه الخطوة بالضغط على مفتاح Delete من لوحة المفاتيح، وبالإمكان التراجع عن أي عدد من الخطوات وليس خطوة واحدة فقط: ليس بالضرورة رسم الشكل وانحناءاته بشكل مثالي، إذا يمكننا التعديل عليها لاحقا باستخدام خاصية تحرير النقاط والتي سنأتي إلى شرحها في الفقرة التالية من هذا المقال. سنقوم الآن بحذف الصورة، واقتصاص الشكل الداخلي من الشكل الخارجي بتحديد الشكلين معا (نحدد الشكل الأول، نضغط على مفتاح Ctrl ثم نحدد الشكل الثاني)، ثم اختيار Subtract من أمر Merge Shapes: ثم سنقوم بتلوين الشكلين، الصغير والكبير بألوان الشعار الأصلية: أصبح الآن بإمكاننا تطبيق أي من تنسيقات الشكل التي نريدها على الشكل الجديد الذي قمنا برسمه، كتأثير ثلاثي الأبعاد: أو حركة مخصصة: من مزايا هذه الطريقة في رسم الأشكال أنّ الشكل الناتج لا يفقد جودته مهما قمنا بتكبيره، على عكس الصور التي تصبح جودتها أقل وتفاصيلها أقل وضوحا عند التكبير. تحرير النقاط باستخدام خاصية تحرير النقاط Edit Point يمكننا إعادة تشكيل الأشكال لتحويل المربع مثلا إلى دائرة، أو المعين إلى شكل عشوائي. وهي مفيدة جدا في إنشاء أشكال مخصصة تتكون من خطوط مستقيمة ومنحنيات انسيابية أيضا. لإعادة تشكيل شكل معيّن، يمكننا تحريك نقاطه من موقع إلى آخر، تحويل القطع المستقيمة إلى منحنيات، إضافة نقاط، وحذف نقاط أخرى. مثلا، في الصورة أدناه، سنقوم بتحول الشكل المربع إلى شكل شبه منحرف: أولا، نحدد الشكل ثم نذهب إلى تبويب: تنسيق Format > تحرير الشكل Edit Shape > تحرير النقاط Edit Points ستظهر النقاط المكونة للشكل بهيئة مربّعات سوداء صغيرة عند حدود أو زوايا الشكل: نمرر المؤشر فوق إحدى النقاط إلى أن يتحول شكله مربع مع أربعة أسهم سوداء صغيرة، ثم ننقر على النقطة ونسحبها إلى الموقع المرغوب. ونكرر هذه الخطوة على بقية نقاط الشكل: بنفس الطريقة سنقوم بتحويل الشكل المثلث (الموضّح في الصورة أدناه) إلى شكل بيضوي. نحدد الشكل المثلث، ننقر بزر الفأرة الأيمن ثم نختار تحرير النقاط Edit Points (وهذه طريقة أخرى لتشغيل هذه الخاصية): الشكل المثلث يحتوي على ثلاث نقاط فقط، ولذلك نحن بحاجة إلى إضافة نقطة أخرى لتحويله إلى شكل بيضوي. وللقيام بذلك، نمرر المؤشر فوق أحد حافات المثلث إلى أن يتحول شكله إلى + وبوسطه مربع صغير، ثم ننقر بزر الفأرة الأيمن ونختار إضافة نقطة Add Point: أو بطريقة أخرى ننقر على الموقع الذي نريد إضافة النقطة إليه ونسحب بزر الفأرة الأيسر إلى أحد الاتجاهات وستُضاف النقطة بشكل تلقائي. نحرّك النقاط الأربع عند حافات الشكل البيضوي بالنقر فوق النقطة وسحبها إلى الموقع المناسب، وكما وضّحنا في المثال السابق: عند النقر فوق النقطة، سنلاحظ ظهور قطعتين مستقيمتين تنتهي بمقابض بيضاء اللون، يمكننا استخدام هذه المقابض لتحويل القطع المستقيمة إلى منحنيات. نقوم بسحب المقبض إلى الداخل لعمل منحني مقعّر، وإلى الخارج لعمل منحني مقعّر. سنستخدم هذه القطع المستقيمة لتحويل الشكل المستطيل إلى بيضوي: نكرر الخطوة أعلاه على الجهة المقابلة من المستطيل لإكمال الشكل البيضوي. قد لا يبدو الشكل مطابقا بشكل مثالي، لكنّه يعطينا تصورا حول إمكانية رسم منحنيات انسيابية جدا: إذا قمنا بعمل منحني ورغبنا في التراجع عن هذه الخطوة وجعله مستقيما مرة أخرى ننقر بزر الفأرة الأيمن على حافة المنحني ونختار Straight Segment، وسيتحول المنحني إلى خط مستقيم بين نقطتين: وبنفس الطريقة يمكننا تحويل الخط المستقيم إلى منحني تلقائيا وليس يدويا بالنقر على حافته بزر الفأرة الأيمن واختيار Curved Segment: وكذلك بإمكاننا حذف النقاط عند الحاجة إلى ذلك بالنقر بزر الفأرة الأيمن فوق النقطة واختيار Delete Point: لقد قمنا بتعديل منحنيات الشعار الذي قمنا برسمه سابقا باستخدام خاصية تحرير النقاط، لاحظ الفرق بين الشكلين:
  20. سنتعلم في هذا الدرس طريقة استخدام الشبكة المسماة بـ Axonometric grid، وهي شبكة ثلاثية الأبعاد في برنامج إنكسكيب، وسنتناول رسم مطبخ كمثال لطريقة الاستفادة من هذه الشبكة. قبل أن نبدأ سنختار من القائمة View الخيار Zoom ثم Zoom 1:1 من أجل تكبير الصفحة بشكل مناسب. ثم من قائمة File سنختار خصائص المستند Document properties ثم في تبويب الصفحة Page سنزيل العلامة عند عبارة Show page border ليحذف إطار الصفحة. من نفس النافذة نتجه لتبويب الشبكة Grid ومن القائمة المنسدلة سنختار Axonometric grid ثم نضغط على الزر New بجانب القائمة. سنظهر لنا الشبكة ثلاثية الأبعاد في الشاشة وهي عبارة عن شبكة وهمية إلا أنها ستساعدنا في الرسم. من الشريط العلوي سنفعل خيار الكبس والالتقاط Enable snapping ومنه نفعل Snap nodes, paths, and handle وكذلك نفعل Snap to grids وذلك ليسهل علينا الرسم على هذه الشبكة، ثم عن طريق اختيار أداة Bezier tool -والتي ستصحبنا إلى نهاية الدرس- سنرسم شكل متوازي الأضلاع وهو عبارة عن جدار من جدران المطبخ، وسنلاحظ أن الأداة تلتقط خطوط الشبكة الوهمية. نلونه باللون الأخضر وتزيل حدوده من لوحة التعبئة والحدود Fill and stroke. نكرر الشكل عن طريق تحديده وبالضغط على الزر الأيمن نختار Duplicate ثم من الشريط العلوي نعكسه أفقيا، ونحركه للطرف المقابل للجدار الأول. نرسم تحت الجدارين معينا وهو عبارة عن أرضية المطبخ، ثم نلونه باللون المناسب. نرسم مجموعة من المعينات على أرضية الطبخ والزوائد منها نرسم فيها بعض من الأشكال متوازية الأضلاع في الأطراف. لنتمكن من تحديد جميع المعينات والأشكال على أرضية المطبخ، سنختار أحدها ثم بالزر الأيمن نختار Select same ومنها نختار Stroke style ليختار لنا جميع الأشكال بنفس الحدود، ثم نزيل الحدود ونلونها باللون المناسب. سنرسم في زاوية المطبخ شكلا شبيه بحرف L وهو عبارة عن جزء من أثاث المطبخ. ولأن الأثاث ممتدا إلى الأرض سنرسم أشكالا متوازية الأضلاع تصل قطعة الأثاث للأرض، ثم نلونها باللون المناسب. سنرسم فرنا بجانب قطعة الأثاث التي رسمناها، ونلونه باللون المناسب. لاحظ أننا نلون الفرن من جميع جوانبه بنفس اللون إلا أنا نغير في درجات اللون لإضفاء بعدا أو بروزا للرسم. سنرسم في وسط الفرن خطوطا ثلاثة لتعطي الفرن عمقا في داخله. نكرر متوازي الأضلاع الذي في جهة باب الفرن ونلونه بلون أقتم من سابقه، ثم بالضغط على Ctrl+Shift نصغر حجمه ثم نكرر العملية بتكراره مجددا وتصغيره، وباختيار الشكلين الجديدين معا نتبع المسار: Path > Difference نرسم شكلا صغيرا متوازي الأضلاع أعلى باب الفرن وهو عبارة عن مقبضه، ثم نرسم داخل الفرن رفا شفافا. بنفس الطريقة وبنفس أداة Bezier سنرسم ثلاجة في الجهة اليمنى ببابين ولكل باب مقبض. سنرسم في قطعة الأثاث التي رسمناها سابقا أبوابا وأدراجا. سنرسم في أعلى قطعة الأثاث متوازي أضلاع وهو عبارة عن حوض لغسيل الأواني، ونجعل له عمقا برسم مضلع في جانبه الأيسر يتطابق ضلعين منه مع الجهة اليسرى من الحوض، ويمتد أحد أضلاعه لقاع الحوض، بينما يوازي الضلع الأخير ضلع الحوض الأيسر العلوي. سنرسم مضلعا بطريقة المضلع السابق ونجعل أحد أضلاعه يوازي ضلع الحوض الأيمن العلوي. نلونها بلون أقتم من لون الأثاث ونعيد الزوائد منها خلف الثلاجة من الشريط العلوي بخيار Page down. سنرسم الصنبور في زاوية الحوض وسنبدأ برسم مفتاحيّ الصنبور عن طريق رسم مكعبين بأداة الرسم المنحني Bezier، بنفس الطريقة التي رسمنا بها أرضية وجداري المطبخ إلا أنا سنعكس في الاتجاه ونغير الألوان. نجمع الشكل المكعب في مجموعة واحدة بتحديد أجزائه، ثم من الزر الأيمن نختار Group ثم نكرره ونصغر حجمه ونرفعه للأعلى ونضعه حيث الموضع الذي سنرسم فيه الصنبور. نكرر الشكل ونعيده للخلف مع كل تكرار إلى أن يتكون عندنا شكل الصنبور. في الحافة العلوية من الصنبور سنكرر الشكل المكعب ونصغره قليلا ونضعه في الطرف العلوي للصنبور. سنحدد أجزاء قطعة الأثاث السفلية دون تحديد الحوض والأبواب والأدراج ثم نكررها ونرفعها لأعلى جدار المطبخ، مع الضغط على Ctrl أثناء التحريك للمحافظة على نفس المحاذاة. سنلاحظ أن الأطراف للأثاث فارغة لأننا لم نرسمها مسبقا، لذا سنقوم بتكرار الشكل الأصغر من متوازي الأضلاع، ونعكسه ونضعه من الجانبين أو نرسمه مجددا بأداة Bezier. سنرسم بابا في الطرف الأيسر، وبابا زجاجيا في الطرف الأيمن. سنلون القطع الداخلية للباب بلون سماوي ليمثل لون الزجاج. وبأداة Bezier سنرسم أشكال متوازية لتشكل لمعان الزجاج ثم نلون هذه الأشكال بعد تكرارها في الفتحتين الزجاجيتين باللون الأبيض ونزيل حدودها. سنضيف لجميع الأبواب التي رسمناها والأدراج مقابض ونلونها بلون أقتم. اكتمل مطبخنا، وحتى نزيل هذه الشبكة نتجه للقائمة View ثم نزيل علامة صح من أمام عبارة Page grid. وبهذا نصل للنتيجة النهائية، ويمكننا عمل أفكار أخرى بنفس الطريقة.
  21. سنتعرف في هذا الدرس على خطوات رسم جسم كروي ثلاثي الأبعاد في برنامج إنكسكيب، وحتى يسهل عليك تتبع هذه الخطوات يُفضّل أن تستخدم نفس الألوان والأحجام المستخدمة في الشرح، وخصوصا تلك التي سنستخدمها في بداية المقال. في البداية سنزيل الإطار الموجود في الصفحة عن طريق: File > Document properties ثم من النافذة المنبثقة نزيل علامة الصح بجانب عبارة Show page border. ثم نبدأ بخطوات الدرس: ارسم دائرة حمراء اللون بأبعاد متساوية وذلك بالضغط على Ctrl أثناء الرسم، واجعل شفافيتها قريبة من المنتصف. كرر الدائرة ولونها باللون الأزرق وكبرها مع الضغط على Ctrl+Shift أثناء التكبير للمحافظة على بعدها. كرر الدائرة الزرقاء ولونها باللون الأخضر ثم من السهم العلوي المتوسط قم بتصغير الدائرة لنحصل على شكل بيضاوي، ثم اسحبها إلى الأعلى مع الضغط على Ctrl إلى الأعلى بحيث يظهر طرف من الدائرة الوسطى أسفله. من أحد الأسهم الجانبية الوسطى اليمنى أو اليسرى صغر الشكل البيضاوي مع أهمية الضغط على Ctrl+Shift أثناء التصغير إلى أن تصبح حافة الشكل البيضاوي ملاصقة لحافة الدائرة الزرقاء، وللتأكد من ذلك كبر بالضغط على + من لوحة المفاتيح أو من الشريط الأيسر للأدوات اختر أداة التكبير وبمؤشر الفأرة اسحب مربعا وهميا حول المنطقة التي تريد تكبيرها، ويمكنك تكرار التكبير عدة مرات. عند التكبير تأكد أن الشكل البيضاوي الأخضر ليس خارجا عن حدود الدائرة الزرقاء بشكل كبير وفي نفس الوقت لابد من التأكد من أنه ملاصق أو متقاطع مع الدائرة الزرقاء ولو بجزء يسير جدا منه. ملاحظة: لتصغير الشاشة سنختار علامة – من لوحة المفاتيح، أو نضغط رقم 1 لتعود الشاشة لحجمها الطبيعي. نكرر الشكل البيضاوي ونسحبه للأعلى مع الضغط على Ctrl للطرف المقابل، ثم نتأكد بتكبير إحدى حافتي الشكل من ملامسته لجدار الدائرة الزرقاء وتقاطعه مع جزء صغير جدا معها، ولكننا في هذه المرة لن نصغر الشكل من أجل الوصول لذلك بل سنحركه للأعلى أو الأسفل مع أهمية الاستمرار بالضغط على Ctrl أثناء ذلك إلى أن نصل لنفس النتيجة التي وصلناها مع الشكل البيضاوي السابق. نكرر الشكل البيضاوي الأخضر العلوي مجددا، ونحركه لأسفل الشكل الأصل، ثم نكبره بالضغط على Ctrl+Shift أثناء التكبير ونتأكد بنفس الطريقة السابقة من التصاقه بجدار الدائرة الزرقاء، ثم نكرر الشكل الذي كبرناه توًا ونحركه للأسفل مع الضغط على Ctrl أثناء ذلك إلى أن يلامس حافة الدائرة الزرقاء كسابقه. نحدد الأشكال الأربعة البيضاوية ونكررها جميعها وبعد التأكد من كون الأشكال المكررة محددة جميعها سنختار من قائمة المسار Path الخيار Union لنجعلها شكلا واحدا. نختار الدائرة الزرقاء مع الأشكال البيضاوية التي وحدناها ثم من قائمة Path نختار Difference ليتم حذف مواضع التقاء هذه الأشكال مع الدائرة الزرقاء. مع التأكد من كون الدائرة ما زالت محددة سنختار من قائمة Path الخيار Break apart ليجزئ لنا ما تبقى من الدائرة. سنلاحظ أن الدائرة صارت عبارة عن مجموعة من الأجزاء، سنختار الجزء أعلى الدائرة مع الشكل البيضاوي الأخضر الذي يليه ثم نتبع المسار: Path > Union سنقوم بحذف الجزء الذي يلي الجزء العلوي من الدائرة الزرقاء إلا أنا سنبقي على الشكل البيضاوي الذي يليه دون حذفه. نحدد القطعة الوسطى من الدائرة الزرقاء مع الشكل البيضاوي أسفلها ثم نوحدها بالأمر Union ثم نحذف القطعة الزرقاء التي تليها دون حذف الشكل البيضاوي الأخضر. تبقى لنا ثلاث قطع من الدائرة الزرقاء وشكلين بيضاويين نحدد الأعلى منهما ونعيده من الشريط العلوي خطوتين إلى الخلف ليكون خلف الدائرة الحمراء. نكرر الشكل البيضاوي الأخضر ونلونه باللون الأسود، ثم مع الضغط على Ctrl+Shift نصغره مع أهمية جعل حدوده اليمنى واليسرى أكبر من حدود الدائرة الحمراء. ثم نعيد الشكل المكرر خطوتين للخلف بحيث يكون خلف الدائرة الحمراء. حدد كلا الشكلين البيضاويين الأخضر والأسود ثم كررهما مجددا ومع بقاء تحديد الشكلين المكررين اختر من قائمة Path الأمر Difference ليتكون عندنا شكل حلقة تحيط بالدائرة. لون الحلقة باللون البرتقالي واجعل قيمة شفافيتها opacity 100 لتتمكن من تمييزها. كرر الدائرة الحمراء الوسطى واخترها هي والحلقة البرتقالية ثم اتبع المسار: Path > Intersection ثم نجزئ ما تبقى من الحلقة بالأمر Break apart ليظهر لنا شكلين منفصلين عن بعضهما سنحذف العلوي منهما بتحديده ثم من لوحة المفاتيح نضغط على زر الحذف. ثم نحدد الشكل السفلي البرتقالي المتبقي مع الدائرة الحمراء الأصلية ونطبق الأمر Difference من قائمة المسار. الهدف من هذه الخطوات هو أن يظهر شكل الحلقة المحيطة بالدائرة الوسطى لتبدو كأنها في وسط الدائرة الزرقاء التي تحيط بها وهذا سيظهر لنا عند تلوين الشكل وإزالة الشفافية بشكل أوضح. سنكرر نفس الخطوات على الشكل البيضاوي الأخضر السفلي والتي اتبعناها مع الشكل العلوي، يمكنك متابعة الصور أو العودة للخطوات السابقة وتطبقيها كما هي. تأكد بعد حصولك على الحلقة الصفراء أن تكرر الدائرة الحمراء وتحددها مع الحلقة وتختار من قائمة المسار الأمر Intersection كما فعلنا مع سابقتها ثم تتابع بقية الخطوات. وكما فعلنا سابقا سنحدد الدائرة الأصلية الحمراء مع الجزء الأصفر المتبقي ونختار الأمر Difference من قائمة المسارات. وبهذا نكون حصلنا على الشكل الكروي ثلاثي الأبعاد، ويتبقى لنا تلوينه وإضافة الضلال والتدرجات اللونية التي ستعطيه برزا وبعدا. نحدد جميع أجزاء الشكل الكروي ونجعل قيمة الشفافية 100 . نختار الدائرة الوسطى الحمراء ونلونها باللون الوردي الفاقع والذي اخترناه من الشريط السفلي. ملاحظة: يمكنك الاستفادة من القيم الموجودة في لوحة التعبئة والحدود Fill and stroke إذا أردت الوصول للألوان الموجود في الصورة بدقة. نجعل نوع تعبئة الدائرة تدرجا شعاعيا Radial gradient من تبويب التعبئة Fill وعند اختيار نوع التدرج سيظهر لنا في أسفل لوحة التعبئة خيار للتعديل على اللون. نختار أحد العقد الطرفية التي ستظهر على الشكل وفي لوحة التعبئة عند الحرف A سنجعل القيمة 255 أو نسحب المؤشر الموجود لأقصى اليمين وذلك لنزيل شفافية اللون. نحدد العقدة الوسطى ثم من الشريط العلوي سنختار الرمز + لإضافة عقد إضافية. نختار العقدة الوسطى مجددا ثم من الخيار + في الشريط العلوي سنضيف عقد إضافية، ثم من الشريط العلوي أيضا عند كلمة stops يمكننا عرض مجموعة العقد اللونية الأربعة التي حصلنا عليها واختيار العقدة التي نرغب بتغيير لونها ونغير كل عقدة باللون الذي نرغب به. وهذه قيم الألوان التي استخدمناها للعقد بترتيبها من الأعلى إلى الأسفل في القائمة Stops: ff83b5ff ff0066ff a70043ff 2c0012ff والتي يمكنك نسخها ولصقها في تبويب التعبئة Fill في قيمة RGBA أسفل اللوحة. سنسحب العقدة الوسطى ونحركها ليمين الدائرة لإضفاء المزيد من التأثيرات اللونية. نختار القطع الزرقاء الثلاثة ونوحدها معا عن طريق الأمر Union حتى نلونها كقطعة واحدة. نلونها باللون الأصفر ثم نعطيها تدرجا شعاعيا كما فعلنا مع الدائرة الوردية السابقة. نجعل قيمة شفافية اللون في القعد الطرفية كاملة ونضيف المزيد من العقد اللونية كما فعلنا سابقا. القيم التي استخدمناها مع العقد الأربعة هي كالتالي بترتيبها من الأعلى إلى الأسفل في القائمة Stops: ffea97ff ffcc00ff ff9c00ff ff0000ff في حال رغبتنا بتوسعة تدرج الشكل مع المحافظة على التوزيع من الجانبين يمكننا سحب إحدى العقد الطرفية مع الضغط على Ctrl+Shift أثناء السحب. كما يمكننا أن نقوم بتحريك العقد المتوسطة بنفس الطريقة. نحرك التدرج إلى الجزء العلوي من القطع الثلاث الصفراء. نلون الأشكال البيضاوية الخضراء بالتدرج الخطي حيث سنختار للعقدة اليمنى اللون البرتقالي، ولليسرى اللون الأصفر بعد إزالة شفافية اللون. ثم نقوم بتلوين الشكل البيضاوي السفلي باللون الأصفر دون تدرج، ونبقي التي لوناها باللون الأسود كما هي دون تغيير. لإضافة ظل على الدائرة الوردية، سنكرر القطع الثلاث الصفراء التي وحدناها مسبقا، ونلونها باللون الأسود. نحركها قليلا للأسفل إلى الحد الذي نريد أن يبدو عليه ارتفاع الظل، ثم نقوم بتجريئها عن طريق الأمر Break apart ونحذف القطعة الثالثة السفلية لعدم حاجتنا لها، ثم نعيد تجميع القطعتين المتبقيتين عن طريق الأمر Union. نكرر الدائرة الوردية ونختارها هي والظل الذى أنشأناه ثم نختار الأمر Intersection من قائمة Path ليتبقى لنا الظل في حدود الدائرة فقط ثم نعيده خطوة للخلف. نرسم دائرة جديدة متساوية الأبعاد بالضغط على Ctrl أثناء رسمها، ثم من لوحة المحاذاة والاصطفاف Align and distribute نحاذيها عاموديا مع الدائرة الوردية. نرفعها للأعلى لحافة القطعة الصفراء العلوية مع الضغط على Ctrl أثناء التحريك للمحافظة على محاذاتها، ثم من السهم السفلي الأوسط مع الضغط على Ctrl نقوم بتصغيرها للحد المناسب. نكرر القطع الثلاث الصفراء مجددا ونختارها هي والدائرة التي أنشأناها حديثا ثم نختار الأمر Intersection. ونلون الشكل المتبقي باللون الأبيض مع تقليل الشفافية لأكثر من المنتصف. نحدد أجزاء الجسم الكروي جميعها ثم نقوم بتجميعها عن طريق الاختصار Ctrl+G أو بالزر الأيمن نختار Group. ندور الجسم الكروي بالاتجاه الذي نريد، وبهذا نكون وصلنا للنتيجة النهائية للشكل الكروي. الدرس مستفاد من مقطع فيديو بعنوان: Inkscape Tutorial: 3D Sphere لصاحبه Nick Saporito.
  22. إنَّ تقنية الصور والأفلام ثلاثية الأبعاد التي تعتمد على الظلال الحمراء والزرقاء قديمة مقارنة بالجيل الجديد من أفلام 3D التي انتشرت مؤخرًا إلا أنها كانت جيدة وكان الناس يرغبون بها. فقررت أن أكتب هذا الدرس عن كيفية تصميم صور بارزة حقيقية تعمل بشكل صحيح باستخدام هذه التقنية، وبحثت في عِلم تجسيم الصور لإيجاد طريقة لجعل الصور تخرج من الشاشة. لنبدأ بهذا الدرس لتَعلُّم استخدام هذه التقنية القديمة لإنشاء هذا النوع من الصور ثلاثي الأبعاد في برنامج فوتوشوب. حتى نستطيع متابعة هذا الدرس بشكل صحيح ونستطيع رؤية الصور بهذا التأثير ستحتاج إلى نظارات 3D مع العدسات الحمراء والزرقاء. يمكنك الحصول على واحدة من أحد المتاجر أو من التسوق عبر الإنترنت مقابل بضعة دولارات وهي تعمل بشكل ممتاز. أو يمكنكم صناعة واحدة يدويًّا إذا توفرت المواد المُلائمة لديكم من خلال تطبيق التصميم في الصورة التالية. يمكن إنشاء صور ثلاثية الأبعاد بارزة عبر طريقتين. التقنية الأولى هي جمع صورتين منفصلتين من الكاميرا والنتائج في بعض الصور رائعة. التقنية الثانية تُنتج التأثير من صورة واحدة، ما يجعلها مفيدةً بشكل خاص للرسومات، أو أي صورة لم تُلتقط في وضعية ستِريو. إنشاء الصور البارزة من صورتينإنّ تقنية الصورتين تساعد فعلًا على فهم المبدأ خلف تجسيم الصور. يتم إنشاء بروز الصورة من جمع صورتين من زوايا مختلفة، بطريقة مشابهة لعمل العينين. جرّب النظر إلى شيء قريب منك ودقّق النظر فيه ثم أغلق عينًا واحدة ثم افتحها وأغلق الأخرى. ستلاحظ أن هذا الشيء يبدو وكأنه يتحرك باستدارة معينة (جرّب الاستمرار في تبديل فتح عين واحدة وستلاحظ ذلك بوضوح)، هذه التقنية تستخدم ذات القاعدة. سيتم أخذ صورتين، إمّا باستخدام كاميرتين مربوطتين معًا على مسافة محدّدة، أو من كاميرا واحدة متحركة على منصب ثلاثي القوائم. التقط بضعة صور على بعد بضعة إنشات قريبة من الصورة الأولى أو بضعة أقدام للمناظر البعيدة. افتح الصورتين في فوتوشوب. هذه صورتين منفصلتين جاهزتين للتجسيم من موقع Shutterstock. حدّد الكل CMD+A وانسخ CMD+C صورة ثم ألصقها CMD+V فوق الصورة الأخرى. انقر نقرًا مزدوجًا على الخلفية لتحويلها إلى طبقة عادية. تذكّر أي صورة هي اليسرى وأيهما اليمنى. امنح الطبقات أسماءً بناءً على ذلك. انقر مرتين على الطبقة اليسرى لفتح أنماط الطبقة. ألغِ تفعيل القناة الحمراء واضغط موافق. افتح أنماط الطبقة اليمنى وألغِ تفعيل القناتين الخضراء والزرقاء. ستشاهد تأثيرات بروز الصورة مباشرة بعد ذلك. حرّك الطبقة لمحاذاة صور الإزاحة الملونة على النقطة البؤرية في المقدمة والخلفية لتنعيم الصورة وذلك للحد من مشاكل الرؤية المزدوجة. استخدم أداة القص Crop tool لقص المستند ضمن منطقة تداخل الطبقتين. يتم إنشاء عمق المشهد تلقائيًّا من نقطة تحويل النظر بين الصورتين. المثير في هذه التقنية هو أنك لن تعرف كيف سيكون التأثير المطبّق حتى تنتهي من معالجة الصور وهو ما يحقق متعة التصوير. إنشاء الصور البارزة من صورة واحدةلا يزال ممكنًا إنشاء صور بارزة من صورة واحدة. هذه التقنية تحتاج عملًا إضافيًّا في فوتوشوب ولكنها تمنح مزيدًا من السيطرة على التأثير النهائي. فهي تستخدم خريطة العمق مع فلتر Displace لجعل الصورة تخرج من مكانها وبالتالي خلق تأثير 3D المطلوب. افتح الصورة في فوتوشوب. سنحتاج أولًا إلى إنشاء خريطة العمق، التي تستخدم درجات ألوان الأسود والأبيض لتحديد مدى بُعد كل جزء من الصورة. أنشئ طبقةً جديدةً ثم ارسم تحديدًا مستطيلًا رفيعًا ولوّنه بتدرج لوني من الأسود للأبيض. سيكون هذا المستطيل مرجعًا هامًّا للدرجات اللونية. سنبدأ أولًا بالمنطقة الأقرب للكاميرا. أنشئ طبقة جديدة وحدّد العناصر في المقدمة باستخدام أداة تحديد المضلعات Polygonal lasso tool أو باستخدام أداة القلم Pen tool ثم لّون هذه المنطقة المحدّدة بالأبيض. ضع هدفَ أداة الفرشاة Brush Tool على Highlights وخفّف opacity إلى 50%. لوّن المناطق البيضاء الأبعد بقليل بفرشاة ناعمة بلون رمادي فاتح. سينعكس هذا التغيير في التدرج اللوني على التدرج في العمق. أنشئ طبقة جديدة واجعلها تحت الطبقة البيضاء. حدّد العناصر الأبعد بدرجة من المناطق البيضاء. استخدم تدرج لوني بألوان رمادية متوسطة لتلوين هذه الطبقة بحيث ستكون الأجزاء الأبعد داكنة أكثر والأقرب ستكون فاتحة أكثر. كرّر العملية بإنشاء طبقة جديدة وجعلها خلف الطبقة السابقة وتحديد العناصر الأبعد في كل مرة ومن ثم استخدام تدرج لوني داكن أكثر في كل مرة لتلوين الطبقة، هذه العملية لها تأثير كبير عند النظر إلى النتيجة النهائية باستخدام نظارات الرؤية ثلاثية الأبعاد. الطبقة الأخيرة والتي ستكون أسفل كل الطبقات أي أنها ستظهر خلف جميع الطبقات يجب أن تكون باللون الأسود الصافي وهي ستكون فقط للمناطق الأبعد من الصورة. اضغط CMD+A لتحديد الكل ثم CMD+Shift+C لنسخها مدمجة. اضغط CMD+V للصق الصورة المدمجة فوق طبقات لوحة الطبقات ثم طبّق فلتر التمويه Gaussian Blur بقيمة 10px. هذا التمويه سيخفف قسوة وحِدّة الحواف بعد تطبيق displace على الصورة. احفظ الملف بصيغة PSD. وليكن اسمه "displace.psd". افتح الصورة الأصلية مجددًا ثم استخدم الاختصار CMD+Shift+U لتشبيع الصورة. (إنّ التشبيع هو أمر اختياري ولكنه يضيف نمط القِدَم على تأثير بروز الصورة). اضغط CMD+J لمضاعفة الطبقة ثم انقر مرتين على الخلفية لتحويلها إلى طبقة عادية. انقر مرتين على الطبقة العلوية لفتح نافذة أنماط الطبقة. ألغِ تفعيل القناة الحمراء ثم اضغط موافق. افتح أنماط الطبقة للطبقة الثانية وألغِ تفعيل القناتين الخضراء والزرقاء. على عكس التقنية السابقة فلن تشاهد أي تغيير هنا بعد. حدّد الطبقة العلوية ثم اذهب للقائمة: Filter > Distort > Displace وأدخل القيمة 10px في الخانة الأفقية وقيمة 0 للخانة العمودية ثم اختر الملف displace.psd. سيتم عرض الطبقة وفقًا لخريطة العمق البيضاء والسوداء. ضع نظارات الرؤية ثلاثية الأبعاد لمشاهدة بُعد تجويف الخلفية. حرّك الطبقة العلوية لمحاذاة الصور في النقطة البؤرية للحد من مشاكل الرؤية المزدوجة، ثم قص الصورة بالحجم المناسب. الفائدة من هذه التقنية هي أن تمتلك القدرة على السيطرة الكاملة للتلاعب بالصورة. وبعد أن وضعنا الطبقة في خريطة العمق داخل ملف displace يمكننا العودة دائمًا إلى هذا الملف وإعادة ضبط وتعديل الدرجات اللونية والتمويه لتغيير التأثير ثلاثي الأبعاد. ترجمة -وبتصرّف- للمقال: How To Create Anaglyph 3D Images That Really Work لصاحبه: Chris Spooner.
  23. عادة يتم عمل نمط التصميم Low Poly Art باستخدام تطبيقات ثلاثية الأبعاد كبرنامج Cinema 4D لكن يمكننا تنفيذ نفس النمط ويكون ثنائي الأبعاد باستخدام برنامج أدوبي اليستريتور Adobe Illustrator، تابع هذا الدرس لتتمكن من عمل تصميم جميل لجبل باستخدام Low Poly Art ومسارات الفيكتور vector paths. سنضيف أيضا بعض التدرجات اللونية لمحاكاة التأثير 3D، بعدها ننقل التصميم إلى برنامج الفوتوشوب Photoshop لإضافة بعض اللمعان عليه باستخدام خامات textures جميلة. هذه هي النتيجة النهائية التي سنحصل عليها حيث سنستخدم في البداية أدوات برنامج أدوبي اليستريتور Adobe Illustrator المخصصة لإنشاء فيكتور دقيق ثم ننقله إلى برنامج الفوتوشوب Photoshop لإضافة بعض الخامات textures والتي ستجعله أكثر حيوية. نقوم بفتح ملف جديد في برنامج اليستريتور Illustrator ونرسم مخطط لجبل باستخدام أداة القلم Pen tool، أثناء رسم الخطوط نضغط مرة واحدة على أداة القلم لتوليد خطوط مستقيمة بين النقاط أما في الجزء السفلي فنحاول أن نتبع مسارا منحنيا ليساعدنا على ظهوره بشكل 3D في وقت لاحق. نزيل التحديد عن المخطط الذي قمنا برسمه ثم نضيف خطوط متقاطعة عليه تمتد من الأعلى إلى الأسفل، بعدها نستخدم خطوط التوجيه الذكية (CMD+U) ليسهل علينا نزع snap النقاط الموجودة. نستمر في رسم المزيد من الخطوط المتقاطعة بين النقاط لتقسيم المخطط إلى قطع صغير كما يظهر في الصورة. في النهاية ستصبح الخطوط الجديدة قصيرة وبالتالي سنحصل على أشكال مضلعة أصغر، نحاول أن لا نبالغ في إضافة الكثير من التفاصيل للرسمة حتى لا تفقد قالب النمط "low poly". نحدد جميع الخطوط التي رسمناها لحد الآن ثم نضغط على الزر Divide من لوحة تحديد المسارات Pathfinder لتتقاطع الخطوط وينشأ لنا شكل واحد. نضغط على الزر الأيمن للفأرة ونختار فك التجميع Ungroup حتى نستطيع تحديد الأشكال الفردية التي تحصلنا عليها من لوحة تحديد المسارات Pathfinder كل على حدا. نرسم بعض المربعات ا(لتي سنستخدمها بشكل مؤقت) على جانب مساحة العمل ونملأها بتدرجات لونية مختلفة، بالنسبة لي فقد اخترت تدرجات اللون الأسود بين 70-90%، 60-80% و50-70% ثم تدرجات أخف بين 0-20% و10-30%. نضغط على المفتاح Shift ونحدد بعض القطع من مخطط الجبل بشكل عشوائي، ثم نستخدم أداة Eyedropper tool لتعبئة الأشكال المحددة بالتدرج اللوني الأول. نحدد بعض من الأشكال المتبقية ونطبق عليهم التدرج اللوني الثاني، ثم ننهي التعبئة باستخدام التدرج اللوني الفاتح. إذا كان هناك قطع متواجدة في نفس المساحة وملونة بنفس التدرج اللوني فيمكننا تعديلها واختيار تدرج لوني مختلف لخلق نوع من التباين. نستخدم التدرج اللوني الفاتح لعمل قمة ثلجية على الجبل، نلون الجبل بالتناوب بين التدرج اللوني الغامق والتدرج الفاتح لإضافة اختلاف في المظهر. استخدام التدرجات اللونية يساعدنا على التخلص من المظهر الثنائي الأبعاد المسطح للشكل، لكن في تصميمنا هذا فإن جميع التدرجات تتخذ نفس الاتجاه لذلك نستخدم أداة التدرج اللوني لتغيير اتجاه تعبئة كل شكل عشوائيا. تضيف التدرجات اللونية لخلق بعدا آخر للشكل، بعدها نأخذ شكل الفكتور الذي تحصلنا عليه إلى برنامج الفوتوشوب لإضافة بعض اللمسات النهائية. نقوم بلصق الرسم على ملف داخل برنامج الفوتوشوب، ونختار لون أزرق- رمادي غامق لملأ الخلفية. نرسم تحديد باستخدام أداة the Polygonal Lasso tool ثم نقوم بتعبئته بلون بني-بيج لتصميم مساحة أرض أسفل الجبل. نستخدم فرشاة كبيرة ناعمة لإضافة إضاءة بيضاء على طبقة جديدة نضعها فوق الخلفية لكن دون إضافتها على رسمة الجبل. نقوم بتغيير نمط طبقة الإضاءة من blending إلى Overlay حتى تمتزج الألوان وتخلق لنا توهجا أزرق حيوي. نضاعف طبقة رسمة الجبل ونلونها بالأسود ثم نضغط على CMD+T لتحويله، بعدها نحدد الخيار Distort حتى تمتد الرسمة وُتشكل لنا ظل طويل للجبل. نخفض من قيمة شفافية الظل إلى 10% ونضعه تحت طبقة رسمة الجبل الرئيسية. نفتح الخامة subtle grunge texture ونضعها في طبقة جديدة فوق تصميمنا، ثم نضيف الفلتر Sharpen مرة أو مرتين لإظهار التفاصيل الدقيقة. بعد تطبيق الخامة على التصميم نغير نمط الطبقة من blending إلى Color Burn لتركيبها مع الرسمة وخلق تأثير جميل، بعدها نخفض قيمة الشفافية إلى حوالي 35٪. نحدد الفرشاة Spraypaint-Brushes ونرش بعض البقع البيضاء في طبقة جديدة نضعها أسفل رسمة الجبل، نبقي الجزء الرئيسي من الفرشاة خلف الجبل لإضافة بعض الرش المضيئ على قمة الجبل ، نكرر نفس العملية مع اختيار اللون الأسود للجزء السفلي. الخامة التي قمنا بتطبيقها على التصميم باستخدام الفوتوشوب أضافت لها لمسة حيوية من خلال إزالة المظهر المسطح لرسمة الفيكتور، كما أن تأثير low poly في حد ذاته نمط رائع والذي يمكننا استخدامه لجميع أنواع التصاميم. ترجمة -وبتصرف- للدرس How To Create a Low Poly Art Mountain Illustration لصاحبه: Chris Spooner.
  24. سنتعّلم في هذا الدرس طريقة صنع إحدى أدوات التصوير؛ الكلاكيت. سنقوم باستخدام الأدوات الأساسية، تأثيرات 3D، التدرّجات وأوضاع مزج الطبقات. 1. نفتح مستندا جديدا بالإعدادات التالية: الأبعاد: 500px*500px.نمط الألوان: CMYK.الدقة: (Screen (72ppi.ونتأكّد من أنّ مربّع الخيار Align New Objects to Pixel Grid غير مؤشّر ثم نضغط OK. 2. نرسم مستطيلا باستخدام (Rectangle Tool (M. بالأبعاد 295px*190px. نملأ الشكل بلون معيّن. نقوم بعمل نسخة من هذا المستطيل (Ctrl+C ثم Ctrl+F) ثمّ نغيّر ارتفاع المستطيل الثاني إلى 40px ونحرّكه إلى الأعلى باستخدام أسهم الاتّجاهات من لوحة المفاتيح: 3. نحدّد المستطيل الصغير ونذهب إلى: Object > Transform > Rotate ونضع قيمة الزاوية 10 درجات. بعد تدويره نقوم بتحريكه للأعلى باستخدام الأسهم من لوحة المفاتيح إلى أن تبقى الحافّة السفلية اليسرى فقط هي المتّصلة بالمستطيل الكبير. نحدّد المستطيلين معًا ونقوم بتوحيدهما بالضغط على زرّ Unite من لوحة مستكشف المسارات: Windows > Pathfinder 4. نقوم برسم وجه الكلاكيت باستخدام أداة القلم (P) كما موضّح في الصورة أدناه. نختار عرض الخط 3pt أو 5pt حسب الرغبة. نقوم بتحديد جميع الخطوط ونذهب إلى: Object > Expand 5. نقوم بإضافة النصوص أيضًا كما في الصورة أدناه. نحوّل النصوص إلى حدود (Outlines) وذلك بتحديد النصّ وننقر بزرّ الفأرة الأيمن ثمّ نختار Create Outlines. (أو نحدّد النصّ ثم نذهب إلى القائمة Type > Create Outline). هذه الخطوة تفيدنا في تحويل النص إلى خطوط ومنحنيات لا يمكن التعديل عليها، لذلك علينا أن نتأكد من النصوص قبل تحويلها إلى منحنيات: 6. نقوم برسم شكل مستطيل (M) ثمّ نضغط على مفتاح (E) من لوحة المفاتيح لعمل تحويل للمستطيل. نمسك النقطة الوسطية في الأعلى ونقوم بسحبها إلى اليسار بينما نضغط على مفتاحيّ Ctrl +Shift. يجب أن يكون الشكل الناتج كما في الصورة أدناه: 7. ننسخ الشكل الذي قمنا بعمله في الخطوة السابقة ونقوم بتحريكه إلى اليسار باستخدام الفأرة بينما نضغط على مفتاحيّ Alt+Shift. نضغط على Ctrl+F لعمل نسخ أخرى منه. عندما نكتفي بعدد النسخ نقوم بتحديدها جميعًا ونقوم بنسخها نسخة أخرى. من خيارات لوحة التحويل Transform Panel: Window > Transform نقوم باختيار Flip Vertical (نقوم بإظهار قائمة الخيارات من الزرّ الموجود في أقصى الحافّة اليمنى للوحة التحويل). بعدها نذهب إلى: Object > Transform > Rotate ونضع قيمة الزاوية 10 درجات. نقوم بمحاذاة هذه الأشكال مع الجزء العلوي من الكلاكيت باستخدام أسهم لوحة المفاتيح: 8. نقوم برسم مستطيل وتغيير حجمه ومكانه ليتناسب مع الشكل كما موضّح في الصورة أدناه (المستطيل الأخضر). نقوم بتحديد النقطة العلويّة اليمنى من المستطيل وتحريكها إلى الجهة اليسرى باستخدام (Direct Selection Tool (A والفأرة. عندما نتأكّد من أن الشكل أصبح كما هو مرغوب به نقوم بتحريكه جانبًا لكي نستخدمه لاحقًا: 9. نقوم بتحديد الخطوط، النصوص، وجميع الأشكال في وجه الكلاكيت مرّة واحدة، ثم نسحب هذه المجموعة إلى لوحة الرموز (Symbols Panel): Window > Symbols Panel يمكننا إعطاء اسم للرمز الجديد من نافذة خيارات النماذج، ثم نختار نوع الرمز Graphic ونضغط OK.يمكننا الآن حذف المجموعة الأصلية لأنّها أصبحت في حوزتنا في لوحة الرموز. 10. نقوم بتحديد شكل الكلاكيت ونذهب إلى القائمة: Effects > 3D > Extrude & Bevel سنستخدم الاعدادات كما في الصورة أدناه: 11. نضغط على زرّ Map Art من نافذة خيارات 3D Extrude & Bevel، ثمّ نختار المجموعة التي أضفناها في لوحة الرموز من القائمة المنسدلة الخاصّة بالرمز (Symbols) في نافذة Map Art؛ ثمّ نضغط OK. نذهب إلى القائمة: Object > Expand Appearance ثمّ إلى: Object > Ungroup نستمّر بفكّ المجموعات (Shift+Ctrl+G) إلى أن نحصل على أشكال منفصلة (أيّ يصبح الأمر Ungroup غير فعّال). نقوم بتحديد الجهة الأمامية من الكلاكيت، نضغط بزرّ الفأرة الأيمن ثمّ نختار Release Clipping Mask. 12. نحدّد الشكل الذي قمنا بوضعهِ جانبًا فيما سبق، ثم نذهب إلى: Effect > Stylize > Round Corner نغيّر نصف القطر إلى 10 ونضغط OK. نذهب الآن إلى القائمة: Effect > 3D > Extrude & Bevel ونستخدم نفس الإعدادات السابقة (الخطوة 11) ماعدا قيمة العمق (Depth) نغيّرها إلى 2pt. نذهب إلى: Object > Expand Appearance ثمّ إلى: Object > Ungroup نستمّر بفكّ المجموعات (Shift+Ctrl+G) إلى أن نحصل على أشكال منفصلة. نقوم بوضع هذا الشكل فوق الكلاكيت في مكانه المناسب: 13. نحدّد العناصر الثلاث من جانب الشكل ثلاثي الأبعاد معًا ثمّ نضغط على زرّ Unite من لوحة مستكشف المسارات. 14. نملأ الشكل بتدرّج قطري من الأبيض إلى الأسود كما موضّح في الصور أدناه: 15. لكي نملأ الكلاكيت بنفس اللون نستخدم أداة القطّارة (Eyedropper Tool (I، ونضغط على الشكل السابق لنسخ اللون. يمكننا تعديل اتّجاه التدرّج ومكانه باستخدام أداة التدرّج (Gradient Tool (G كما في الصورة أدناه: 16. نحدد الأشكال البيضاء ونملأها بتدرّج خطي من الأبيض إلى الرمادي: 17. نقوم برسم ثلاث أشكال بيضوية باستخدام (Ellipse Tool (L ونملأها بتدرّج قطري من الأبيض إلى الرمادي ونضعها في مكانها المناسب في وجه الكلاكيت كما موضّح في الصورة أدناه: وبذلك نكون قد انتهينا من عمل الكلاكيت. سنقوم الآن بعمل مكبّر صوت باللون الأحمر. 18. نقوم برسم الشكل الموضّح في الصورة أدناه باستخدام أداة القلم (Pen Tool (P. الشكل بسيط يمكن رسمه بالقليل من النقاط. لنتأكد فقط من إغلاق المسار بوضع النقطة الأخيرة فوق النقطة الأولى: 19. نذهب إلى القائمة: Effect > 3D > Revolve ونستخدم الإعدادات التالية: 20. نملأ الشكل بلون أحمر جميل ونذهب إلى القائمة: Object > Expand Appearance ثمّ إلى: Object > Ungroup نستمّر بفكّ المجموعات (Shift+Ctrl+G) إلى أن نحصل على أشكال منفصلة (إي يصبح الأمر Ungroup غير فعّال). نحدّد الأشكال المتبقّية (3 أو 4 اشكال) بينما نضغط على مفتاح Shift ونقوم بتحريكها باستخدام أسهم لوحة المفاتيح. بالإمكان حذف الأجزاء المتبقّية (في الجهة اليسرى) حيث لم نعد بحاجة إليها. بهذه الخطوة سنكون قد حصلنا على بنية بسيطة ومرتّبة للملف الخاص بنا. 21. نحدد الجزء السفلي من مكبّر الصوت ثم نضغط على زرّ Unite من لوحة مستكشف المسارات (Pathfinder Panel): 22. نكرّر الخطوة السابقة مع الأجزاء الأخرى. بعد ذلك نقوم برسم الشكل الموضّح أدناه (الشكل الأخضر) باستخدام أداة القلم (P). سيمثّل هذا الشكل شعاع ضوء على سطح مكبّر الصوت: 23. نحدّد الشكل السفلي من مكبّر الصوت ثم نقوم بنسخه (Ctrl+C) ثمّ نضغط على مفتاح Shift+ شكل الشعاع معًا ونضغط على زرّ Intersect من لوحة مستكشف المسارات. نضغط على مفتاحيّ Ctrl+B لوضعه خلف شكل الشعاع. نغيّر لون الشعاع إلى اللون الأحمر. نحدد الجزء السفلي للكلاكيت وشكل الشعاع معًا ونضغط Ctrl+Alt+B، ثمّ نذهب إلى القائمة: Object > Blend > Blend Options في نافذة الخيارات التي ستظهر نغيّر نوع المسافة (Spacing) إلى Specified Steps من القائمة المنسدلة، ثمّ نضع عدد الخطوات 40. 24. نقوم بتحديد الجزء العلوي من مكبّر الصوت ثم نملأه بتدرّج قطري من الأحمر إلى الأسود. يمكننا تغيير مركز واتجاه التدرّج باستخدام أداة التدرّج (G): 25. يمكننا الآن وضع الكلاكيت بالقرب من مكبّر الصوت. انتهى التصميم تقريبًا، لكن بقِي هنالك شيئًا مفقودًا في الصورة؛ الظلال! فبوجود الظلال تصبح الصورة أكثر واقعية. 26. نقوم بعمل نسخة من كل من الكلاكيت ومكبّر الصوت (Ctrl+ C ثم Ctrl+V). نحدد نسخة الكلاكيت ونضغط على زرّ Unite من لوحة مستكشف المسارات. نكرر هذه الخطوة مع نسخة مكبر الصوت أيضًا. أصبح لدينا الآن أشكال للظل، وكلّ ما علينا فعله هو محاذاتها بشكل صحيح وفي المكان الصحيح: 27. نقوم بوضع ظل الكلاكيت خلف شكل الكلاكيت (Ctrl+X، ثم نحدّد شكل الكلاكيت، ثم نضغط Ctrl+B). نذهب إلى القائمة: Object > Envelope Distort > Make it with Warp ونستخدم الاعدادات كما موضّحة في الصورة أدناه ثمّ نضغط OK. نذهب إلى: Object > Expand ثم نضغط OK. 28. نحدّد ظل مكبّر الصوت ثم نضعه فوق مكبّر الصوت. يتم تحريك الأشكال إلى الأمام أو الخلف عن طريق الاختصار (Ctrl+[) أو (Ctrl+]). يجب أن يكون الشكل الناتج كالتالي: 29. نحدد شكليّ الظلّين ونضغط على زرّ Intersect من لوحة مستكشف المسارات: 30. نملأ الشكل الناتج بتدرّج من الأبيض إلى الأسود. نغيّر الوضع إلى Multiply من لوحة الشفافية: Window > Transparency Panel 31. نقوم بالتعديل على اتجاه التدرّج لنحصل على الشكل في الصورة أدناه. وبذلك يكون الدرس قد انتهى بالفعل: ترجمة -وبتصرّف- للدّرس: Create a Clapperboard icon with Adobe Illustrator.
  25. سنقوم في هذا الدرس باستخدام الأشكال البيضوية وتأثيرات 3D لعمل زرّ رسومي Vector ثلاثي الأبعاد. سنتعلّم أيضًا كيفية إضافة العديد من أشكال الملء واستخدام العديد من أوضاع الطبقات لكي نحصل على بعض التأثيرات الرائعة. 1. نقوم بفتح مستند جديد (Ctrl +N) بالإعدادات التالية: الأبعاد: 800px*600px.نمط الألوان: CNYK.الدقة: 300ppi.ونتأكّد من أنّ مربّع الخيار Align New Objects to Pixel Grid غير مؤشّر: 2. نرسم مستطيلا باستخدام (Rectangle Tool (M بالأبعاد 800px*600px ونملأه بتدرج قطري (Radial Gradient) من الأبيض إلى الرمادي. نقوم بإخفاء شكل الخلفية من لوحة المظهر (Appearance Panel) بالضغط على أيقونة العين بجانب الطبقة: 3. نرسم شكلًا بيضويًا في طبقة باستخدام (Ellipse Tool (L بالأبعاد 245px*245px (أي دائرة). 4. نحدد هذا الشكل ونقوم بإضافة تأثير ثلاثي الأبعاد: Effect > 3D > Extrude and Bevel نقوم بإدخال القيم كما في الصورة أدناه، ثم نقوم بتوسيع التأثير بالذهاب إلى: Object > Expand Appearance 5. بعد توسيع التأثير ثلاثي الأبعاد نقوم بتحديد الأشكال السبعة الصغيرة جميعها ثم توحيدها عن طريق الضغط على زرّ Unite من لوحة مستكشف المسارات (Pathfinder Panel). بعدها نقوم بحذف مسار القطع (Clipping Path) عديم الفائدة كما موضّح في الصورة أدناه؛ فنحن في النهاية نريد الحصول على شكلين فقط. نقوم بفكّ كلّ المجموعات حتى لا تتبقى أي مجموعة (Ctrl +Shit +G). ملاحظة: سنسمّي الشكل البيضوي الكبير بالشكل الرئيسي، وشكل القوس السفلي بالشكل الصغير. أسماء الطبقات مهمّة في هذا الدرس، لذا يُرجى تسمية كل طبقة شكل بالاسم المذكور لتجنّب الالتباس ولتكون الخطوات واضحة وسهلة عند التطبيق. 6. نقوم بتحديد الشكل الرئيسي ونعمل منه نسختين في مقدّمته (Ctrl +C ثم Ctrl +F ثم Ctrl +F)، ثمّ نقوم بتحريك النسخة العلويّة بمقدار 2px إلى الأعلى. نحدّد النسختين معًا ثم نضغط على زرّ Minus Front من لوحة مستكشف المسارات: 7. نملأ الشكل الناتج باللون الأبيض، ثم نقلل قيمة Opacity إلى 30%، ونغيّر الوضع إلى Screen من لوحة المظهر (Appearance Panel). نذهب إلى القائمة: Effect > Blur > Gaussian Blur ونضع القيمة 5px: 8. نقوم بتحديد الشكل الرئيسي من جديد ونعمل منه نسختين في مقدّمته (Ctrl +C ثم Ctrl +F ثم Ctrl +F)، نقوم بتحريك النسخة العلويّة بمقدار 12px إلى الأسفل. نحدّد النسختين ثم نضغط على زرّ Minus Front من لوحة مستكشف المسارات: 9. نملأ الشكل الناتج (سنسمّيه الظل (1)) باللون الأسود، نقلل قيمة Opacity إلى 15% ثم نغيّر الوضع إلى Multiply من لوحة المظهر. نذهب إلى القائمة: Effect > Blur > Gaussian Blur ونضع القيمة 30px: 10. نحدّد الشكل الرئيسي من جديد ونقوم بعمل نسخة واحدة منه (Ctrl +C ثم Ctrl +F). نقوم بتحريك هذه النسخة إلى مقدّمة جميع الطبقات في لوحة الطبقات (Layers Panel) (Shift +Ctrl +])، ثم نقوم بتحديد نسخة الشكل الرئيسي وشكل الظل (1) الذي قمنا بعمله في الخطوة السابقة معًا ونعمل قناع قطع (Clipping Mask) بالذهاب إلى: Object > Clipping Mask > Make 11. سنقوم الآن بإضافة التأثيرات للشكل الرئيسي. في البداية نملأه باللون C=0 M=0 Y=100 K=10، ثمّ نملأه بتدرّج خطّي كما في الصورة رقم (1) أدناه. نقلل قيمة Opacity إلى 10% ونغيّر الوضع إلى Multiply. نملأه مرة ثالثة بتدرّج قطري كما في الصورة رقم (2) أدناه. نقلل قيمة Opacity إلى 50% ونغيّر الوضع إلى Screen. بعد ذلك نعيد تحديد الشكل بالكامل ونضيف Inner Glow بالذهاب إلى: Effect > Stylize > Inner Glow ونضع قيمة التمويه 10px والوضع Screen كما موضّح في الصورة رقم (3) أدناه: 12. نقوم بتحديد الشكل الصغير ونعمل منه نسختين (Ctrl +C ثم Ctrl +F ثم Ctrl +F)، ثمّ نقوم بتحريك النسخة الأولى (لننتبه هنا؛ النسخة الأولى وليست النسخة العلويّة كباقي الخطوات) بمقدار 5px إلى الأسفل. نحدد النسختين معًا ونضغط على زرّ Minus Front من لوحة مستكشف المسارات: 13. نحدّد الشكل الناتج (سنسمّيه الظل (2))، ثم باستخدام (Scale Tool (S نحدد نقطة المرجع كما موضّح في الصورة أدناه مع الضغط على مفتاح ALT في نفس الوقت. في مربع الحوار الذي سيظهر نؤشّر على مربّع الخيار Non-Uniform ثم نغيّر قيمة Vertical إلى 106%: 14. نقوم بتحريك شكل الظل (2) الذي قمنا بعمله في الخطوة السابقة تحت شكل القوس (Ctrl +[) من لوحة الطبقات: 15. نقوم بتحديد الشكل الصغير ونعمل منه نسختين (Ctrl +C ثم Ctrl +F ثم Ctrl +F). نقوم بتحريك النسخة العلويّة بمقدار 4px إلى الأعلى. نحدّد النسختين معًا ثم نضغط على زرّ Minus Front من لوحة مستكشف المسارات: 16. نملأ الشكل الناتج (نسمّيه الظل (3)) باللون الأسود، نقلل قيمة Opacity إلى 90%، ثمّ نغيّر الوضع إلى Multiply. نضيف تمويه (Blur) للشكل بقيمة 10px بالذهاب إلى: Effect > Blur > Gaussian Blur بعدها نحرّك الشكل إلى الأسفل بمقدار 2px: 17. نعود إلى الشكل الصغير ونعمل منه نسخة واحدة (Ctrl +C ثم Ctrl +F). نقوم بتحريك هذه النسخة أمام شكل الظل (3)، ثم نحدد الشكلين معًا ونعمل قناع قطع (Clipping Mask) بالذهاب إلى: Object > Clipping Mask > Make 18. سنقوم الآن بإضافة التأثيرات للشكل الصغير. في البداية نقوم بملئه باللون C=0 M=0 Y=100 K=30. نملأه مرة ثانية بتدرّج خطي كما موضّح في الصورة رقم (1) أدناه. نقلّل قيمة Opacity إلى 25% ونغيّر الوضع إلى Multiply. نملأ الشكل للمرّة الثالثة بتدرّج قطري كما موضّح في الصورة رقم (2) أدناه. نقلّل قيمة Opacity إلى 15% ونغيّر الوضع إلى Screen. نملأ الشكل للمرة الأخيرة بتدرّج قطري أيضًا وكما موضّح في الصورة رقم (3) أدناه. نقلل قيمة Opacity إلى 25% ونغيّر الوضع إلى Multiply. 19. نحدّد شكل الظل (2) الذي قمنا بعمله في الخطوة (12) ونعمل منه نسختين (Ctrl +C ثم Ctrl +F ثم Ctrl +F). نقوم بتحريك النسخة الأولى بمقدار 2px إلى الأسفل. نحدّد النسختين معًا ونضغط على زرّ Minus Front من لوحة مستكشف المسارات. بعدها نحرّك الشكل الناتج بقدار 1px إلى الأسفل: 20. نملأ الشكل السابق باللون الأبيض، نقلّل قيمة Opacity إلى 45%، ثمّ نغيّر الوضع إلى Screen. نذهب إلى القائمة: Effect > Blur > Gaussian Blur ونضع قيمة التمويه 4px: 21. نعيد تحديد الشكل الرئيسي وننسخه مرّة واحدة (Ctrl +C ثم Ctrl +F)، نقوم بتحريكه إلى أسفل بقية الأشكال في لوحة الطبقات. سنقوم بحذف جميع أشكال الملء والتأثيرات الخاصّة بهذه النسخة من لوحة المظهر لأنّ لون الشكل لا يهمّنا هنا. نقوم بإضافة تأثير Drop Shadow من القائمة: Effect > Stylize > Drop Box ثمّ ندخل نفس القيم الموضّحة في الصورة أدناه: 22. نستخدم أداة الكتابة (T) لكتابة الكلمة "OFF". (نوع الخط المستخدم هنا هو Myriad Pro font Condensed Bold style). نذهب إلى القائمة: Effect > 3D > Rotate ثم نذهب إلى: Object > Expand Appearance 23. سنقوم بحذف مسار القطع (Clipping Path) الزائد من لوحة الطبقات، ثم نقوم بفكّ كلّ المجموعات (Shift + Ctrl +G) إلى أن نحصل على مجموعة واحدة تضم الحروف الثلاث: 24. نملأ كل حرف من الحروف بتدرّج خطّي كما موضّح في الصورة أدناه: 25. نحدّد الحروف الثلاثة ثم نضيف لها تأثير Drop Shadow من القائمة: Effect > Stylize > Drop Shadow والقيم موضّحة بالصورة أدناه: وهذه هي نتيجة هذا الدرس بعد تتبع جميع الخطوات السابقة؛ زرّ فيكتور ثلاثي الأبعاد. ترجمة -وبتصرّف- للدّرس Create a simple 3D Vector Button in Adobe Illustrator لصاحبه Andrei-Sergiu.
×
×
  • أضف...