(س ص ع) (X Y Z) : المحاور الثلاث ….. هكذا سنرمز للأبعاد الثلاثة في الفراغ “الثلاثي الأبعاد” …. قد يتبدّل القصد من كل رمز على حسب التطبيق الذي تستعمله ….. فعلى سبيل المثال … الارتفاع في اليونتي يرمز له بـ”ص , Y” , في حين يرمز له بـ”ع , Z” في 3D Studio Max ….على أي حال … سنستفيد من هذه الرموز في تحديد الاتجاهات التي قد نرغب أن يتحرك فيها الجسم …. وهذا ينقلنا لنقطة أخرى … “المتجهات” .
(أ.1) |
(أ.2) |
(المتجهات) (Vectors) : في الفضاء الثنائي الأبعاد … على ورقة مثلاً …. إذا أردت تحديد اتجاه فيجب على الأقل أن تعرف نقطتين …. وإذا كان عندك إطار مرجعي فيجب أن تعرف نقطة واحدة على الأقل …. كما في الرسم التوضيحية (أ.1) …. نفس الطريقة نتبعها في المتجهات الثلاثية الأبعاد …. عليك أن تعرف نقطتين في الفراغ على الأقل … أو نقطة واحدة إذا كان لديك إطار مرجعي …. في حالتنا مع اليونتي فغالباً سيكون هناك إطار مرجعي ونقطة أصله هي (0,0,0) سواء كان الإطار المرجعي محلّي -Local أوشامل – Global …. وسنفهم القصد من هؤلاء لاحقاً ولكن الآن فلنضرب مثالاً لمتجه في الفراغ الثلاثي الأبعاد …. المتجه الثلاثي يُرمز له بـ Vector3 في البونتي …و لهذا إذا أردنا مثلا أن نحرك جسم ما عمودياً للأعلى فسيكون متجه الوحدة له هكذا :
Vector3(0.1.0)
وهكذا مع بقية الاتجاهات …. ماذا لو أن يتحرك الجسم في اتجاه زاوية معينه ؟! … 45 درجة مثلاً على الأرض …. للقيام بهذا علينا أولا تجاهل بعد الارتفاع “ص – Y في هذه الحالة” …لأن الحركة ستكون في مستوى الأرض “أفقي” …. ولأن ظل الزاوية 45 يساوي 1 …. فهذا يعني أن كلا من “س و ع – X,Z” قيمتهم تساوي واحد لنقطة تقع على هذا المتجه وتتقاطع مع دائرة قطرها الوحدة …. والنتيجة ستكون كالآتي :-
Vector3(1,0,1)
إذا كان هناك شئ غير مفهوم في موضوع المتجهات فربما عليك مراجعة كتب خارجية في هذا الموضوع والتي قد تساعدك أكثر في توظيف المتجهات بشكل أفضل في لعبتك كفهم كيفية الضرب الاتجاهي والقياسي ..إلخ من المواضيع المرتبطة, أو انتظر فسنتعرّض للموضوع كثيراً خلال هذه السلسلة ..
الأسطح في الفراغ الثلاثي الأبعاد : فلنتخيل معاً شكل بسيط كالمكعب, به ستة أسطح, ياترى كيف يتم التعبير عن هذه الأسطح في العالم الثلاثي الأبعاد ؟! …. تعال نحلل هذا المكعب ببساطة …. يوجد في هذا المكعب ستة “أسطح/مضلعات – Polygons” كما ذكرنا مسبقاً … وكل سطح/مضلع يوجد به “وجه – Face” ….هنا يخلط الكثيرون بين الوجه والسطح …. يتعامل الحاسب بطريقة مختلفة مع الفراغ الثلاثي الأبعاد عن ماهي موجود في الواقع … فلكل سطح وجه واحد تستطيع النظر من خلاله … فإذا نظرت من خلف هذا الوجه مثلاً لن تتمكن من رؤيته …. وهذا يعني أن السطح هو الهيكل مثلاً …. وأن الوجه هو المتجّه الذي سيظهر فيه هذا السطح …. وهنا نأتي لتعريف شئ آخر وهو العموديات – Normals …. وهو المتجه العمودي على الوجه “عمودي على الوجه فقط ولكن يمكنك تغير اتجاهة بالنسبة للسطح وعندها تحصل على اتجاه آخر للوجه”… وهو الذي يحدد كيف سيظهر السطح بالنسبة للإضاءة مثلاً … هناك شئ آخر وهو “النقاط – Vertices” … النقاط تحدد لك قمم الأسطح/المضلعات … ويمكنك تحريكها في الفضاء لتغير من شكل المجسم كما يحلو لك …. وعند إيصال نقطتين ينتج لنا ما يسمّي “الحرف-Edge” ….. انظر لهذه الرسم فستساعدك على فهم الموضوع :
والآن … ماذا لو أردنا إعطاء هذا المكعب لوناّ ؟!! أوأردنا أن نرسم عليه صورة ليبدو كصندوك مثلاً …. سنقوم بتطبيق خامة – Material على كل وجه … لينتج الشكل المطلوب ….
حسناً , هذه كانت مجرد نبذة عن الأساسيات … عليك أنت أن تبحث في الموضوع أكثر …. والآن فلننتقل لنقطة أخرى …. وهي نبذة أخرى ولكن هذه المرة عن أساسيات البرمجة, سأشرح بعض المفاهيم بإيجاز …. وأنت عليك الباقي :-
var myPocket : EP ;
دالة – Function : فلنكتفي للآن بتعريفها على أنها مجموعة من الأوامر التي يمكن تفيذها أكثر من مرة ….
وصف اللعبة : ببساطة ستتحكم في دبابة بمفاتيح التنقل الأساسية (<- , -> , ^ , V ) … يطلق قذيفة بالضغط على “المسطرة – Space” … يقابل دبابات تتحرك في اتجاه عمودي عليه في نفس المستوى الأفقي …. عليه تدميرها بإطلاق قذيفة … و إذا اصطدم بأحدى الدبابات المتحرك فسيخسر ….
الباقي سنبنيه بالعناصر المبدأية الموجودة في اليونتي …. كالمكعب …إلخ إلخ ….
إنشاء مشروع جديد : كما أوضحنا في الجزء الثاني من السلسلة … المشروع هو اللعبة ككل … المشروع سيكون به كل الموارد والملفات التي قد تستخدمها في اللعبة … والآن فلنبدأ مشروعاً جديداً ….. File >> New Project …. سيطلب منك تحديد مكان حفظ المشروع … اختر المكان الذي تشاء … وأيضاً هناك خيارات لتضمين موارد “حزم” جاهزة الإعداد لتستخدمها في لعبتك …. الغ تحديدها الآن إذا كانت مفعّله …. فلن نحتاج لها الآن ….. كما في الصورة :-
سترى أمامك مشهد خال من أي شئ عدا الكاميراً … كما في الصورة ….. يمكنك التعديل في نسق (تشكيلة) التبويبات بالتغير في Layout كما هي معلمه في الصورة … أنت حر في إعداد مساحة العمل الخاصة بك بالصورة التي تريحك …. يمكنك تقل أي تبويب و إدراجة في أي منطقة ترغب :-
يستحسن أن تبدأ في تنظيم مجلد مشروع قبل البدأ في أي شئ … التنظيم إختياري ولكن مستحسن حتى تعتاد …. ففي المشاريع المعقدة بعض الشئ سيختصر عليك الكثير من الوقت … لأن هذا اللعبة بسيطة فسيكون هناك فقط أربعة مجلدات كالآتي :-
علىّ هنا أن أوضّح أن كل مجلدات مشروعك يجب أن تكون في Assets … لا علاقة لك بـ Liberary و Temp الآن …
تصدير مجسّم : الآن فلنصدّر مجسّم الدبابة للمحرك …. للقيام بذلك كل ما عليك فعله هو نسخ الملف Tank.max إلى مجلد Objects وافتح اليونتي ستجده يقوم بتصدير النموذج آلياً ….. بعد ان ينتهي من التصدير ستجد الآتي :-
كما تلاحظ فيوجد النموذج الأساسي وسنطلق عليه الشبكية “Mesh” وبه كل المعلومات المطلوبه عن النموذج … لو تذكر عندما تحدثنا عن الأسطح في الجزء الثالث من السلسلة … هناك الخامة التي تضاف لتعط اللون/الصور المطلوبة للمجسّم … وهذا بالضبط الموجود في مجلد Materials …
والآن فلندرج Tank في المشهد/Scene …..عن طريق السحب والإدراج …. بعدها حدد Tank من الـ Hierarchy …. ستجد أن خصائصه ومكوناته ظهرت في تبويب المفتش/Inspector …. يوجد مكوّن أساسي موجود في كل العناصر التي قد تظهر في اللعبة وهو مكون الـ Transform ويمكنك من خلاله تحديد موقع/Position واتجاه دوران/Rotation وحجم/Scale العنصر ….. ستكون إعدادات الـ Transform للـ Tanks كالآتي :-
كذلك سنعدّل قليلاً في إعدادات الـ Transform للكاميرا الأساسية في اللعبة/Main Camera كالآتي :-
يمكنك الآن بناء البيئة بوضع أرضية مثلاً من خلال أن تضيف Plane وتغير في أبعادها …
أعد تسمية السكربت إلى tankController وافتحه …. ستجد التالي أمامك :-
function Update () {
}
هذه أول دالة ستتعامل معها في اليونتي …. ببساطة كل ماتكتبه بين الـ{} سيدخل في دوّارة اللعبة/Game Loop ويتكرر بمعدّل معين في الثانية الواحدة … مثلا 60 مرة في الثانية …. مثلاً لو حجزت متغير و كتبت كود لإضافة 1 للمتغير ووضعته في دالة Update() …. فستجد أنه بعد ثانية مثلا أصبح المتغير قيمته 60 أو أي رقم آخر يدل على معدل تنفيذ العملية في الثانية على حسب سرعة الجهاز ….
if(Input.GetButton(“Vertical”))
{
transform.position += Input.GetAxis(“Vertical”) * transform.right * tankSpeed * Time.deltaTime;
}
ماحدّث هو كالآتي …. دالة Input.GetButton ترجع قيمة صحيح/True أو خاطئ/False بناءاً على الزر المضغوط عليه … فهنا مثلا Vertical معرّفة في اليونتي على أنها زر التقدم أو التأخر … بحيث إذا ضغط على أي من الزرين فستعيد دالة Input.GetButton قيمة صحيحة/True …. وهكذا فعندما يضغط اللاعب على زر التقدم مثلاً “^” … فسينفذ الكود الموجود بين الـ {} …. و الكود الموجود بينهما يقوم بالآتي …. يأخذ قيمة الـ Position الموجودة في مكوّن Transform الموجود في العنصر (هل تذكره ؟!) … ويقوم بإضافة “transform.right*tankSpeed*Time.deltaTime” … تعالوا نرى ما في هذا الكود … أولا هذا ضرب اتجّاه في قيمة …. الاتجاه وهو transform.right والذي يعتبر متجه الوحدة في اتجاه اليمين…. والقيمة وهي tankSpeed والتي عرّفناها بـ 2 في بداية السكريبت … و Time.deltaTime وهذه لها وظيفة معينة ولكن منعاً للتعقيد الآن فلنكتفي بأن نعرف وظيفتها وهي الإبقاء على ما تدخله وما تراه متزامناً …. أما Input.GetAxis(“Vertical”) فوظيفتها بسيطة جداً …. هل سألت نفسك كيف يفرق اليونتي بين زر التقدم والتأخر ؟! … فكلاهما سيرجع True عند الضغط عليهم …. هنا تأتي وظيفة GetAxis …. فهي ترجع قيمة مختلفة هذه المرة , 1 أو -1 … أي القيمة سالبة أو موجبة … وببساطة إذا ضربنا هذه القيمة عند إضافة متجّه الحركة الجديد …. فسيعكس مثلا لو كانت القيمة سالبة وبهذا يتأخر اللاعب عند ضغط زر التأخر … وسيتقدم اللاعب عندما تضغط زر التقدم لأنه أرجع قيمة +1 و التي هي المحايد الضربي … أي لا تؤثر في قيمة الضرب …..
الناتج النهائي للكود كالآتي :-
var tankSpeed : int = 2.0 ;function Update () {if(Input.GetButton(“Vertical”))
{
transform.position += Input.GetAxis(“Vertical”) * transform.right * tankSpeed * Time.deltaTime;
}
}
… يمكنك الآن تطبيق الكود على الدبابة ورؤية النتيجة والتي من المفترض أن تكون كالآتي : http://dl.dropbox.com/u/9047337/TankGame/001/TankGame001.html
… اممممم … أعتقد أن الدبابة بطيئة بعض الشئ ….. يمكنك التعديل في tankSpeed كما تريد حتى ترى السرعة المناسبة …
يمكنك تحميل ملف المشروع والذي به ما تمّ حتى الآن من هنا : http://dl.dropbox.com/u/9047337/TankGame/TankGame.rar
في المرة القادمة سنضيف بعض التعديلات على الكاميرا و حركة الدبابة وربما بعض الأعداء ……