الكسل نعمة..
نعم، إنه نعمة، ولهذا سنستفيد منه في البرمجة، وسنسمي هذه الطريقة بـ "تقنية الكسل".
تخيل أنك تصمم لعبة تشبه نوعا ما لعبة Sims ولديك في هذه العبة أكثر من عشرين شخصية متواجدة في نفس المكان، ولهذه الشخصيات نفس قدرات شخصيات Sims إن لم يكن أكثر..
بالطبع ستقوم بتحديث كل متغيرات اللعبة ضمن دورتها الأساسية Main Loop وستجد نفسك تحدث الخصائص الفيزيائية للأشخاص (ناهيك عن الأغراض الموجودة في المكان) وتفاعلات عقل كل شخصية والتحقق من شروط وأحداث اللعبة وتحديث مواقع الأشخاص وحالتهم البيولوجية والنفسية (الجوع، العطش، الملل، التقدم في السن...) والرسوميات والصوت وغيره متمنيا بعد كل ذلك أن يكون أداء اللعبة سريعا..
ولكن جزء من سرعة الأداء لا يقع على مواصفات الجهاز، بل عليك أنت كمبرمج، أنت تقوم بالكثير من الجهد فقط من أجل التأكد من سرعة أداء اللعبة.
سأناقش هتا إحدى هذه التقنيات وهي غاية في البساطةـ وهي كما سميناها "تقنية الكسل".
أولا، علينا تحديد بعض العلميات التي لن يلاحظ اللاعب فيها أي بطئ في تنفيذها، وذلك لأنها هي أساسا بطيئة أو لأن أثرها غير مباشر، لنأخذ على سبيل المثال، جوع أحد الشخصيات في اللعبة، من المنطقي في هذه الألعاب أن الشخصية لن تجوع فجأة، ولن تموت فجأة إذا جاعت، بل تحدث هذه الأمور بشكل متدرج وغير مرئي، لذا فلا مشكلة إذا أهملنا تحديث الجوع مقابل توفير المعالج للقيام بالحسابات الفيزيائية والتي غالبا لا يتم التساهل بها.
كيف نقوم بهذا؟
أظن أن عنوان الموضوع نفسه قد أوحى لنا بطريقة التنفيذ، على أي حال، لنرى كيف تنفذ..
كما قلنا، نحدد كل المتغيرات الكسولة، وفي مثالنا هذا أجد أن متغيرات الحالة البيولوجية (جوع، عطش، تقدم في السن، نعاس..إلخ) ومتغيرات الحالة النفسية(ملل، رغبة بالحوار، رغبة باللعب..إلخ) هي أنسب ما يكون للمتغيرات الكسولة.
نقوم سلفا بتخزين الشخصيات ضمن سلسلة نسميها مثلا CharacterLazy وعند الدخول كل مرة في دورة اللعبة، نأخذ فقط شخصية واحدة CurrentCharacter من السلسلة ونقوم بتحديث متغيراتها الكسولة.
الكود التالي مجرد توضيح للفكرة لا أكثر
MainLoop(true)
{
//Do update lazy variables
If(CurrentCharacter == CharacterLazy.length)
{
CurrentCharacter = 0; //Start again from first character
}
processLazyVariables(CharacterLazy[CurrentCharacter]); //process the lazy
CurrentCharacter++; //Get the next character
//End of updating lazy variables
.
.
.
.
The rest of the code
}لك أن تلاحظ حجم التوفير في المعالجة، شخصية واحدة كل دورة بدلا من عشرين!! واللاعب نفسه لن يلاحظ شيئا عدا تحسنا في الأداء.
هناك طريقة أخرى لتطبيق كسلنا هذا في البرمجة، وكمثال واضح جدا، في لعبة GTA لاحظ أن أضواء سيارتك المنعكسة على الطريق (بقع الضوء) يتم تحديثها بشكل أسرع من أضواء سيارة أخرى، تقريبا تحتاج السيارات الأخرى إلى ثلاث دورات ليتم تحريك الضوء من مكانه!!
هذه الطريقة تنشئ مؤقت (لا تخافوا هو عداد أكثر من مؤقت) عند وصوله إلى قيمة ما، يقوم بتحديث المتغير، الكود التالي ليوضح الفكرة:
constant NowDoLazyThings = 5;
MainLoop(true)
{
LazyCounter++; //Always runs from 1 to 5
If(LazyCounter == NowDoLazyThings)
{
LazyCounter = 0;
processLazyVector(CharacterLazy[]);
}
.
.
.
.
The rest of the code
}نلاحظ أن هذه الطريقة تنتظر اللحظة المناسبة! لتقوم بتحديث كل المتغيرات الكسولة، وهذا قد يحدث اختناقات دورية(إذا كانت المتغيرات الكسولة كبيرة) تشبه الاختناقات المرورية أول يوم دوام من كل أسبوع، ولكن هذه الطريقة تستخدم في حالات يجب فيها معالجة كل المتغيرات الكسولة دفعة واحدة، مثال ذلك الرسوميات، فلا يعقل رسم عنصر وإهمال آخر.
بالدمج بين هذه الطرق يمكن أن نصل إلى نتائج جيدة، طبعا ليس كل تحسن الأداء هو بواسطة هذه الطرق، فبعض اللعب لا يمكن لها استيعاب هذه الطرق.. ولكن هي إحدى الوسائل.
أرجو أن لا أكون قد أصبتكم بالكسل، وبانتظار أفكاركم وإضافاتكم.