الفصل الأول: قراءة مدخلات لوحة المفاتيح

تعتبر لوحة المفاتيح أهم أجهزة الإدخال الخاصة بأجهزة الحاسوب الشخصي، فلا تكاد تخلوا لعبة من هذه الألعاب من الاعتماد على مجموعة من المفاتيح التي تقوم بوظائف أساسية. معظم ألعاب الشركات الكبيرة تسمح لك بتغيير إعدادات لوحة المفاتيح بغرض تغيير الارتباط بين المفتاح والوظيفة مما يعطي اللاعب مساحة جيدة لتخصيص اللعبة بما يناسبه.

يساعدنا Unity على قراءة مدخلات لوحة المفاتيح بطريقتين: الطريقة الأولى هي قراءة رمز المفتاح مباشرة، بأن يخبرك أن اللاعب يقوم حاليا بالضغط على المفتاح A أو Z مثلا. أما الطريقة الثانية، فهي أن تقوم كمطور بإنشاء وظائف وربطها مع مفاتيح، بحيث يمكنك لاحقا أن تسمح للاعب بتخصيص المدخلات بما يناسبه. سأتناول في هذا الفصل الطريقة الأولى فقط، وذلك انطلاقا من رؤية الكتاب بأن يكون عامّا قدر الإمكان وتجنب الدخول في الوظائف المخصصة بمحرك Unity، مما يجعله ذا فائدة للمطورين الذين يستعملون غيره من المحركات.

لتعلّم كيفية قراءة المدخلات، لنقم بإنشاء مشهد جديد في المشروع الذي بدأناه في الوحدة السابقة، أو إنشاء مشروع جديد كليا. ما نحتاجه مبدئيا هو مشهد يحتوي فقط على الكاميرا بموقعها الأصلي (10-, 0, 0) وكائن مكعب في نقطة الأصل، مما يجعله مرئيا من قبل الكاميرا في منتصف الشاشة كما في الشكل 16.

الشكل 16: مشهد بسيط بهدف قراءة مدخلات لوحة المفاتيح

الشكل 16: مشهد بسيط بهدف قراءة مدخلات لوحة المفاتيح

بعد الانتهاء من بناء المشهد قم بإنشاء بريمج جديد في المجلد الفرعي scripts والذي قمنا بتخصيصه للبريمجات، وليكن اسمه KeyboardMovement. لنفرض أننا نريد أن نتحكم بموقع المكعب عن طريق لوحة المفاتيح، وسنستخدم مفاتيح الأسهم الأربعة لتحريكه في الاتجاه المناسب، يمينا أو يسارا، أو أعلى أو أسفل. السرد 4 يوضح الكود المطلوب لتطبيق هذه الحركة. قم بإضافة البريمج إلى كائن المكعب في المشهد ومن ثم قم بتشغيل اللعبة لتجرب تحريكه باستخدام الأسهم.

1. using UnityEngine;
2. using System.Collections;
3. 
4. public class KeyboardMovement : MonoBehaviour {
5.  //سرعة الحركة
6.  public float speed = 10;
7.  
8.  // Use this for initialization
9.  void Start () {
10.     
11.     }
12.     
13.     // Update is called once per frame
14.     void Update () {
15.            //للأعلى
16.         if(Input.GetKey(KeyCode.UpArrow)){
17.             transform.Translate(0, speed * Time.deltaTime, 0);
18.         } 
19.         //للأسفل
20.         if(Input.GetKey(KeyCode.DownArrow)){
21.             transform.Translate(0, -speed * Time.deltaTime, 0);
22.         }
23.         //لليمين
24.         if(Input.GetKey(KeyCode.RightArrow)){
25.             transform.Translate(speed * Time.deltaTime, 0, 0);
26.         }
27.         //لليسار
28.         if(Input.GetKey (KeyCode.LeftArrow)){
29.             transform.Translate(-speed * Time.deltaTime, 0, 0);
30.         }
31.     }
32. }

السرد 4: بريمج لقراءة مدخلات أسهم لوحة المفاتيح وتحويلها لحركة

بقراءة السرد 4 نلاحظ أن قراءة مدخلات اللاعب عملية مستمرة طالما أن اللعبة تعمل، لذا علينا أن نقوم بهذه العملية من داخل الدّالّة ()Update. نلاحظ أيضا في الأسطر 16، 20، 24، 28 أننا نستخدم الدّالّة ()Input.GetKey ونزودها برمز المفتاح عن طريق القائمة KeyCode والتي تحوي رموز جميع المفاتيح. في كل مرة نستدعي ()Input.GetKey تقوم بفحص إذا ما كان اللاعب يضغط على المفتاح المطلوب، وتعطينا true في هذه الحالة، أو false في حال لم يكن اللاعب يضغط عليه. وباستخدام الجمل الشرطية if نقوم بربط حركة الكائن بالمفتاح المطلوب. لاحظ أننا قمنا باستخدام ()transform.Translate كما رأينا في الوحدة السابقة وذلك لتحريك الكائن على المحورين x و y مع ملاحظة استخدام قيمة سالبة للسرعة لتكون الحركة في الاتجاه السالب بالنسبة للحركة يسارا أو لأسفل.

قد نحتاج أحيانا لأن نقرأ المفتاح مرة واحدة فقط بدلا من قراءته بشكل مستمر. مثال على ذلك عملية القفز في ألعاب المنصات، حيث يحتاج اللاعب عادة لأن يقوم بالضغط مجددا على المفتاح ليقفز مرة أخرى، لا أن تتكرر عملية القفز بإبقاء مفتاح القفز مضغوطا. من أجل تحقيق ذلك يمكننا استخدام دّالّة أخرى وهي ()Input.GetKeyDown والتي تعطيك true مرة واحدة فقط عند الضغط على المفتاح لأول مرة، ثم تعود لتعطي false مع استمرار الضغط، وبهذا تجبر اللاعب على رفع اصبعه عن المفتاح والضغط مجددا. جرب استبدال ()GetKey بـ ()GetKeyDown في السرد 4 ولاحظ الفرق.

إن كنت مبتدئا في البرمجة ولا تعرف الفرق بين استخدام if بشكل منفصل أو استخدام else if سأوضح فيما يلي الفرق بينهما مستعينا بالسرد 5: باستخدامنا للجملة الشرطية if بشكل منفصل لكل مفتاح، فإننا نسمح بقراءة أكثر من مفتاح في نفس الوقت ونسمح لكل منها أن يؤثر في حركة الكائن. أي أن اللاعب إذا ضغط السهمين الأعلى والأيمن فإن الكائن سيتحرك بشكل قطري لأعلى يمين الشاشة. أما إذا ضغط لأعلى وأسفل فإنهما سيلغيان تأثير بعضهما وسيبقى الكائن في مكانه. إذا أردنا أن نسمح فقط بمفتاح واحد دون الآخر على كل محور حركة (أفقيا أو عموديا)، يمكننا استعمال else if كي نمنع مثلا أن يأخذ قراءة جهتين متقابلتين في نفس الوقت، بحيث تعطى الأولوية للمفتاح صاحب الجملة الشرطية الأولى.

16. //حاول قراءة السهم الأعلى وفي حال لم يكن مضغوطا حاول قراءة الأسفل
17. if(Input.GetKey(KeyCode.UpArrow)){
18.     transform.Translate(0, speed * Time.deltaTime, 0);
19. } else if(Input.GetKey(KeyCode.DownArrow)){
20.     transform.Translate(0, -speed * Time.deltaTime, 0);
21. }
22. 
23. //حاول قراءة السهم الأيمن وفي حال لم يكن مضغوطا حاول قراءة الأيسر
24. if(Input.GetKey(KeyCode.RightArrow)){
25.     transform.Translate(speed * Time.deltaTime, 0, 0);
26. } else if(Input.GetKey (KeyCode.LeftArrow)){
27.     transform.Translate(-speed * Time.deltaTime, 0, 0);
28. }

السرد 5: استخدام else if لحصر القراءة بمفتاح واحد وتحديد تفضيل مفتاح على الآخر

ما ينطبق على الأسهم في المثال الذي ذكرته ينطبق على جميع المفاتيح الأخرى، كل ما عليك هو اختيار المفتاح الذي ترغب بقراءته من القائمة KeyCode. يمكنك الاطلاع على المشهد scene2 في المشروع المرفق لترى المثال الذي استعملناه في هذا الفصل كاملا.

السابقالتالي

تعليقات واستفسارات