كيف يزيد التوليد الإجرائي من متعة اللعب ؟

كيف يزيد التوليد الإجرائي من متعة اللعب؟

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

لماذا يجب أخذ التوليد الإجرائي دائماً بعين الاعتبار؟

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

كما أنه إضافة للفوائد التقنية التي ذكرت سابقاً، فحقيقةً يمكن للتوليد الإجرائي أن يزيد من متعة طريقة اللعب (Game Play)، وأن يعطي اللعبة عمقاً أكبر يدعو اللاعب لاتخاذ قرارات دقيقة لا يمكن تقديمها للعبة إلا عن طريق هذا الإجراء، بالطبع الكثير من الألعاب لا تتناسب مع التوليد الإجرائي مطلقاً، فجميعنا يعلم أن Super Meat Boy لن تكون كما هي لولا التصميم المتقن والدقيق لتصميم المراحل. ولكن يجب أخذه بعين الاعتبار قبل بدأ المشروع فهو قد يعطي فرقاً كبيراً في المنتج النهائي.

كيف يزيد التوليد الإجرائي من متعة اللعب؟

الفكرة ليست فقط في تقليل الملل الناجم عن تكرار نفس المرحلة، هذه بالطبع أحد أهم الفوائد -التلقائية- للتوليد الإجرائي، ولكن تصميم التوليد بشكل احترافي سيقدم للاعب المتعة ذاتها عند إعادة اللعبة والسبب هو أن قواعد اللعب تكون ثابتة ولكن المشكلة تكون جديدة في كل مرة؛ الفكرة هنا هو تقديم تجربة جديدة مختلفة عن سابقتها في كل مرة يلعب اللاعب اللعبة.

وهذه أهم النقاط التي وجدت أن ألعاب التوليد الإجرائي الناجحة تتبناها بشكل أو بآخر:

1) اجعل من التجربة تحدٍ جديد في كل مرة

في لعبة Spelunky؛ لا يهم كم من الخبرة تمتلك أو كم مرة تمكنت من إنهاء اللعبة، فاحتمالية الخسارة دائماً موجودة، يجب عليك أن تلعب بتركيز من أول مرحلة، فإضاعة "قنبلة" واحدة قد تكون الفارق بين الفوز والخسارة. اللعبة تفوقت على Don’t Starve من هذه الناحية؛ فعندما تمتلك خبرة كافية في Don’t Starve فإنك ستتمكن من الفوز في كل مرة. هذا الأمر أفقد اللعبة الكثير من الحماسة بعد أن تصبح متمرساً عليها. هذا الأمر مهم جداً، فعندما يصبح اللاعب قادراً على الفوز بنفس الطريقة كل مرة ستفقد اللعبة رونقها وستصبح مملة حتماً.

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

2) يجب ألا تكون التجربة مستحيلة

ستكون بعض المرات في اللعبة أصعب أو أسهل من مرات أخرى، هذا طبيعي بالنسبة للتوليد الإجرائي. مالا يمكن أن يطيقه اللاعب هو كون اللعبة مستحيلة، عندما تجتمع جميع الظروف للقضاء على اللاعب فإنه حتماً سيضجر من اللعبة، لأنه خسر بسبب "الحظ". في Spelunky المراحل تتولد عشوائياً ولكن صممت المراحل بطريقة تضمن أن يكون هناك مسار مفتوح من البداية وحتى النهاية، ولولا الطريقة التي تم بها تصميم المراحل؛ فإنه من الممكن جداً أن تنفد الموارد التي تفتح لك الطريق (القنابل) بسرعة، وتبدأ مرحلة جديدة لتجد نفسك محبوساً ولا يوجد أي شيء تفعله.

أما في Don’t Starve فالمبرمج جعلك تبدأ في مكان هادئ في الخريطة، لو أنك بدأت في مكان مليء بالوحوش وانتهت اللعبة قبل أن تبدأ، لكانت قمة في الإحباط، لذلك فعندما تبدأ فإنك تبدأ في مكان فيه بعض الطعام والأشياء الأساسية لإشعال النار والبقاء على قيد الحياة!

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

3) اهتم بتصميم المراحل (Level Design)

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

تصميم المراحل في سبلنكي

تصميم المراحل في سبلنكي

تصميم المراحل في Don’t Starve مختلف، هناك بعض الأشياء المحددة الشكل والتي تظهر دائماً في خريطة اللعبة، لكن ما يظهر فيه تصميم المراحل بشكل واضح هو طور المغامرة (Adventure Mode) والذي يتألف من مجموعة من المراحل. فهناك مثلاً مرحلة تتكون من جزيرتين، جزيرة جداً سهلة وفيها الكثير من الموارد، وجزيرة أخرى صعبة للغاية. في مرحلة أخرى قام المطور بعمل مجموعة من المناطق المتصلة مع بعضها البعض بممرات، هذه الممرات تكون مسدودة بعقبات مختلفة. بالطبع فإن هذه المراحل تتولد بشكل عشوائي مختلف كل مرة، لكن التقسيمة الأساسية لها ثابتة. في مرحلة أخرى كان التحدي هو أن تتمكن من النجاة في الشتاء، حيث تلعب في مكان بارد جداً فلا تتمكن من الزراعة أو تربية النحل، بالإضافة إلى مواجهة خطر التجمد، هنا غير طبيعة التحدي عن طريق تغيير الظروف وليس الخريطة. وجود مثل هذه التقسيمات والظروف قدمت تحديات مختلفة عن أسلوب اللعب العادي مما أعطى المزيد من التحدي والتنوع، وبالتالي تتطلب تقديم حلول مختلفة من قبل اللاعب، مما يطيل عمر اللعبة.

4) مزيج جديد في كل تجربة

"الأدوات" في Binding of Isaac

"الأدوات" في Binding of Isaac

بعض الألعاب تقدم مزيجاً مميزاً في كل مرة تلعب اللعبة، هذا الأمر يزيد من التنوع ويحقق النقطة الأولى (والأساسية). ما أقصده بالمزيج هو أن تتفاعل مجموعة من العناصر مع بعضها فتقدم طريقة لعب مختلفة تماماً. المثير للاهتمام هنا أن تغيير عنصر واحد من هذه العناصر سيغير التجربة بأكملها. من الصعب فهم هذه النقطة تماماً إلا عندما تجربها بنفسك، وأفضل مثال لها هو لعبة The Binding of Isaac؛ ففي كل مرة تلعب اللعبة تختلف طريقة اللعب كثيراً، فإذا كان لدينا (طلقات ليزر، طلقات تخترق الجدران، وطلقات تتحرك بشكل متموج) فيمكن للاعب أن يجرب كل واحدة على حدة أحياناً وفي أحيان أخرى سيجرب طلقات ليزر تخترق الجدران، أو طلقات ليزر متموجة، أو طلقات متموجة تخترق الجدران، أو الثلاثة معاً) ولك أن تتخيل ما يمكن توليده كل مرة حيث تحصل وسطياً على 15 قوة (power-up) من مجموعة تفوق المئتين!

في ألعاب أخرى كلعبة Civilization لا يكون هذا المزيج عشوائياً؛ بل بناءاً على اختيار اللاعب، بحسب الظروف والأخطار وشكل الأرض التي بدأ فيها. بنفس الطريقة؛ الدولة العسكرية العلمية تختلف كثيراً عن الدولة العسكرية التوسعيّة، أو التوسعيّة العلمية. وبالطبع هناك الكثير من السياسات الأخرى لتتبناها مع مرور الوقت والتي لن تجعلك تلعب بطريقة مختلفة فحسب بل ستجعلك تفكر بطريقة مختلفة.

5) لا تجعل التوليد الإجرائي سبباً للملل

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

للاستزادة: شرح المطور حول كيفية تصميم المراحل في Spelunky [بالإنجليزية]

أعجبك المحتوى؟

تفضل بتسجيل بريدك الإلكتروني حتى نرسل لك التدوينات القادمة فور نشرها في المجالات التي تهمك:

لا تقلق، نحن أيضاً لا نحب السبام 🙂

مهتم بتدوينات:

كما نرجو منك عزيزي القاريء بأن تدعمنا بنشر هذا المحتوى على الوسط المفضل لديك من الشبكات الاجتماعية بالأسفل:

عبدالرحمن خلوف

مصمم ألعاب مستقل, مبرمج مهتم بأكشن سكربت, مدوّن في مجال تطوير الألعاب, أحب تطوير الألعاب وأتابع مواضيعها بشغف .

اخر المقالات
التعليقات ( 3 )
  1. نحو تصميم ألعاب " نقية " | Xash | زاش
    سبتمبر 17, 2014 at 8:10 م
    رد

    […] تدوينة سابقة، تحدثنا عن كيف يمكن للتوليد الإجرائي (Procedural Generation) في الألعاب أن ي…، مما يجعل ممكناً للاعب أن يلعب اللعبة مرة تلو أخرى، […]

  2. [قصة نجاح] كيف يحقق Ido Yehieli آلاف الدولارات من لعبته؟ | زاش
    فبراير 24, 2015 at 7:08 م
    رد

    […] المفضلة القديمة، مثيل D&D و AD&D و تجمع خصائص كثيرة تمنع اللاعب من الشعور بالملل أثناء مراحل […]

  3. Enas Fahed
    نوفمبر 28, 2015 at 11:01 م
    رد

    مسا الخير انا طلبة سنة اولى جامعة تخصص برمجة ان شاء الله بدي اسال كيف فيني اضيف توقيت للعبة واخليها نظام ثلاثي الابعاد وهاد الكود للعبة الي بدي اعدلها ‪#‎include‬
    #include
    #include
    #include
    #include
    using namespace std;
    int main()
    {
    HANDLE hConsole;
    hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    //————————— local variables ——————————
    int ball[80][24];
    void gotoxy(int, int);
    int noOfCoords = 0;
    int origX, origY;
    char mov1, mov2;
    int x, y;
    int W = 80, H = 24;
    //—————————– user prompt ——————————–
    SetConsoleTextAttribute(hConsole,249);
    cout << "Enter the Width of the window for the ball bounce in (between 0 and " << W <> W;
    cout << endl;
    cout << "Enter the Height of the window for the ball to bounce in (between 0 and " << H <> H;
    cout << endl;
    cout << "Enter the X coordinate for the ball (between 0 and " << W <> origX;
    cout << endl;
    cout << "Enter the Y coordinate for the ball (between 0 and " << H <> origY;
    cout << endl;
    cout <> mov1;
    cout << endl;
    cout <> mov2;
    cout << endl;
    system("CLS"); //clear the screen
    x = origX; //make x and y equal the original entries
    y = origY;
    //initialize the ball array's elements to 0
    for(int row = 0; row < W; row++)
    { for(int col = 0; col < H; col++)
    ball[row][col] = 0;
    }
    gotoxy(x, y);
    SetConsoleTextAttribute(hConsole,252); //go to the coordinate
    cout< 0) { y–; }//endif
    else { mov1 = ‘d’; }//endif
    }//endif
    if (mov1 == ‘d’)
    { if (y < H) { y++; }//endif
    else { mov1 = 'u'; }//endif
    }//endif
    if (mov2 == 'r')
    { if (x 0) { x–; }//endif
    else { mov2 = ‘r’; }//endif
    }//endif
    gotoxy(x, y); //go to coordinate
    cout < 0) { y–; }//endif
    else { mov1 = ‘d’; }//endif
    }//endif
    if (mov1 == ‘d’)
    { if (y < H) { y++; }//endif
    else { mov1 = 'u'; }//endif
    }//endif
    if (mov2 == 'r')
    { if (x 0) { x–; }//endif
    else { mov2 = ‘r’; }//endif
    }//endif
    gotoxy(x, y);
    cout << "O"; //print O at the coordinate
    if (ball[x][y] == 0)
    { ball[x][y] = 1;
    noOfCoords++;
    }//endif
    system("CLS");
    }//endwhile
    //output the number of coordinates the O passed through
    cout << endl;
    cout << "The ball crossed " << noOfCoords << " unique coordinates.";
    cout << endl;
    system("PAUSE");
    return 0;
    }//endmain
    //gotoxy definition
    void gotoxy(int eex, int eey)
    {
    COORD coord;
    coord.X = eex;
    coord.Y = eey;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    }//endgotoxy
    وشكرا

‎اضف رد