Unconfigured Ad Widget

تقليص

إعـــــــلان

تقليص
لا يوجد إعلان حتى الآن.

برمجة Half-Life2 بواسطة الـ Source SDK

تقليص
X
 
  • تصفية - فلترة
  • الوقت
  • عرض
إلغاء تحديد الكل
مشاركات جديدة

  • برمجة Half-Life2 بواسطة الـ Source SDK

    بسم الله الرحمن الرحيم



    السلام عليكم و رحمة الله و بركاته.

    هل تريد صناعة لعبة على مستوى عالي من الاحتراف؟ هل انت جديد إلى عالم صناعة الألعاب؟ لم تصنع لعبة من قبل أبدا في حياتك؟ هل تريد صناعة الالعاب بنفس الاساليب اللتي يستخدموها صانعوا الالعاب الحقيقيون؟ هل سئمت من الجيم ميكر و ما شابه؟ (نعم .. انا من أعداء الجيم ميكر! )

    لقد وصلت الى المكان اللذي سيساعدك إن شاء الله!

    هل سمعت عن شي اسمه Mod؟ طيب هل تعرف لعبة counter strike؟ هذه اللعبة هي mod! هل تعرف ما هو المود؟ كلمة mod هي اختصار لكلمة modification و تعني تغيير ولكننا سنستخدم كلمة تحوير لأنها اكثر تعبيرا في هذا السياق. فكرة المود هي اخذ لعبة حقيقية جاهزة ثم اجراء تغييرات عليها لتصبح بالشكل اللذي تريد.

    كونتر سترايك هي عبارة عن Mod او تحوير للعبة half-life الشهيرة. ماذا يعني ذلك؟

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

    ماذا يفيد كل ذلك؟ يفيدك انك ايضا تستطيع استخدام نفس الادوات و استخدام السورس كود للعبة (يعني برمجة اللعبة برمجة حقيقية) و عمل اي تغييرات تريد ..!



    لحظة لحظة .. ماذا تقصد؟ هل الكود هذا هو نفسه كود اللعبة الحقيقي ام مجرد سكربتات مثلا او ان في الامر لعبة خفية؟!

    اطمئن .. السورس هو نفسه سورس اللعبة الحقيقي و هو مكتوب بلغة C++ يعني كلام مظبوط و شغل حقيقي! لكنه ليس الكود الشامل لكل ما في اللعبة!! فهو لا يتضمن محرك الرسم ولا الفيزياء .. لكنه يتضمن اغلب بقية الأشياء (لا تخف من هذه الناحية اطلاقا .. فالكود حقيقي تماما!)



    و ماذا تستفيد الشركة؟

    تستفيد كثيرا .. يكفي ان التحويرات تنشيء الكثير من التجمعات الانترنتية الصغيرة و التابعة للعبة .. فهذا يطيل من عمر اللعبة .. فأنا مثلا اشتريت هاف لايف من اجل كاونتر سترايك فقط! و كاونتر سترايك طبعا ليس المود الوحيد, لكنه الاشهر (و قد قامت الشركة بتبنيه و اظن حتى وظفت صانعيه عندها) فأبسط فائدة تجنيها الشركة من التحويرات هو اطالة عمر اللعبة و بالتالي زيادة المبيعات.

    ماذا تقصد؟ ما دخل التحوير بالمبيعات؟

    لا تستطيع تحوير اللعبة دون ان تكون قد اشتريتها, و كذلك لا تستطيع لعب التحويرات دون ان تملك اللعبة, و اغلب التحويرات هي ملتي بلير (على الانترنت) و هذه عادة كسر حمايتها صعب لذلك يضطر اللاعبون لشراء النسخة الاصلية.



    و ماذا أستفيد أنا؟

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



    و لكن هل يعني هذا انني ساغير اللعبة مباشرة؟يعني لن استطيع المحافظة على اللعبة الاصلية؟

    كلا كلا .. من قال هذا؟ اللعبة الاصلية تبقى كما هي, تستطيع تنزيل كونتر سترايك و هاف لايف في نفس الوقت دون أن تؤثر واحدة على الأخرى.

    ما تقوم به هو انشاء مجلدات جديدة تماما و ملفات جديدة تماما دون المساس باللعبة الاصلية .. و لكن عندما تقوم بتشغيل لعبتك (المود) فانك ستقوم بتشغيل اللعبة الاصلية و تخبرها ان تأخذ الملفات اللتي تحتاجها من مجلدات المود و ليس مجلدات اللعبة الحقيقية (نقوم بذلك عن طريق ارسال parameters لوصلة اختصار اللعبة) و عموما هذه المهمة يقوم بها ستيم بالنيابة عنك فهو يضع المود في قائمة الالعاب بحيث تستطيع تشغيله بمجرد الظغط عليه.



    ماللذي احتاجه للبدء في تحوير الالعاب؟ تبدو مهمة صعبة خاصة بالمحترفين ..؟!

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

    باقي الاشياء تحتاجها حسب مهمتك في الفريق, ففي البرمجة تحتاج خلفية في السي بلص بلص و البرمجة الشيئية (او الكائنية كما يسميها البعض) object oriented programming اما للمراحل فتحتاج الى تعلم برنامج hammer و هو سهل التعلم و لكن المشكلة تكمن في انك يجب تكون فنان و مخيلتك واسعة (كل الناس تستطيع استخدام القلم و الالوان, لكن ليس كل الناس يستطيع رسم رسومات فنية جميلة) اما للنماذج و الشخصيات و الاسلحة فتحتاج احد برامج تصميم الثريدي .. و هناك نسخ مجانية من بعض هذه البرامج خاص لهواة تحوير الالعاب.

    و قبل هذا وذاك تحتاج للتوكل على الله و كذلك الى الكثير من الحماسة.





    طيب, لكن هاف لايف قديمة شوية و صورها تبدو سيئة مقارنة بالالعاب الجديدة .. اليس كذلك؟

    و من قال لك اننا سنستخدم هاف لايف الأولى .. انا ضربتها كمثل فقط لاني اظن ان اغلب الناس تعرف كاونتر سترايك. نستطيع استخدام half-life2 (هاف لايف الثانية) و هي حديثة و محركها ربما افضل محرك حتى الان (و هل تصدق بانك تستطيع برمجة هذه اللعبة و انت مجرد هاوي!!) الشركات الحقيقية تقوم بشراء ليسنس للبرمجة على المحرك مقابل مبالغ ضخمة .. و انت هنا تستطيع الحصول عليه مجانا (باستثناء سعر اللعبة الأصلي).

    طبعا الشركات تحصل على اكثر بكثير مما نحصل نحن عليه ..فهم يحصلون الكود كله (حتى المحرك و اظن حتى الفيزياء) كما انهم يقومون ببيع العابهم في الاسواق .. اما نحن فألعابنا مجانية!!



    (ملاحظة: اظن ان شركة فالف تخطط للسماح للهواة ببيع تحويراتهم على ستيم .. لكني شخصيا من معرفتي بطبيعة الوضع اظن ان هذه الفكرة لن تنجح .. فلا يوجد كثير من الناس يريدون صرف خمسين دولار للعبة ثم عشر دولارات لكل مود يريدون تجريبه! هم اصلا عندما دفعوا الخمسين دولار كانوا يتوقعون الحصول على الكثير من التحويرات المجانية).



    طيب الان, ماذا نفعل؟ من اين نحصل على الكود و الخ؟

    الجواب: تحصل عليه من ستيم .. و اذا اردت التعرف على بنية المود و تركيب المجلدات و غيره, فعليك بهذه الصفحة http://www.valve-erc.com/srcsdk/ اللتي اعدتها الشركة للمساعدة و فيها كذلك الكثير من الدروس.

    طبعا محرك half-life2 اسمه source engine او source اختصارا, و ادوات تغيير اللعبة يطلق عليها SDK و بما انه هذه الادوات خاصة بمحرك السورس فيطلق عليها Source SDK.



    و أنا هنا أيضا سأقوم إن شاء الله بمحاولة لشرح الكود و كيف يمكن ان نسختدم الكود في برمجة اللعبة .. و سافترض في القارئ انه هاوي برمجة يعرف السي و ربما السي بلص بلص لكنه لا يعرف ما المقصود بالبرمجة الشيئية .. او ربما يعرف ما معنى الكلاس و كيف يستخدمه, و لكن لا يدري ما فائدته .. الخ.

  • #2
    آلية العمل:

    يمكننا تقسيم اللعبة الى قسمين: محرك الرسومات من جهة .. ومحرك اللعب و ملفات اللعبة من جهة أخرى.
    (ملاحظة: هذا التقسيم غير حقيقي و أقوم بافتراضه فقط من أجل التوضيح)


    محرك الرسومات هذا لا نستطيع التدخل فيه ..

    ما نستطيع تغييره هو ملفات اللعبة و محرك اللعب.

    من أجل ان تلعب اللعبة, تقوم اولا بتشغيل محرك الرسم, اللذي يقوم بدوره بالبحث عن محرك اللعبة و عن ملفات اللعبة.

    محرك الرسم عندما يشتغل فإنه يعرف مسبقا المكان اللذي تتواجد فيه ملفات لعبة و محرك لعب هاف لايف 2 لذلك فهو يحملها دائما بشكل تلقائي (افتراضي).

    في حالة إنشاء مود جديد, فإننا نقوم بإخبار محرك الرسم ان يقوم بتحميل محرك لعبنا نحن و ملفات لعبتنا نحن.

    علينا أولا انشاء مجلد جديد نضع فيها ملفات اللعبة (و هذا يتضمن محرك اللعب), ثم ننشيء shortcut لمحرك الرسم و نضع فيها بارامترات تخبر المحرك بأن لا يبحث عن ملفات هاف لايف تو بل ان يبحث عن ملفات المود اللذي قمنا بإنشائه.

    نقوم بذلك عن طريق اضافة –game بارامتر, و نتبعه بمكان مجلد المود.

    مثلا .. لو فرضنا ان مكان المحرك هو

    Path1\hl2.exe

    و مسار المود هو

    Path2\mod_folder

    فالشورتكت تكون كالتالي:

    "path1\hl2.exe" –game "path2\mod_folder"


    مجلد المود (او مجلد لعبتنا الجديدة) يحتوي على الخرائط و النماذج و الاصوات و غيرها من الملفات .. و لكن ما يهمنا كمبرمجين هو ملفات dll

    Mod_folder\bin\server.dll

    Mod_foler\bin\client.dll

    هذه هي الملفات اللتي مصدرها مفتوح لنا و هي الملفات اللتي ستنتج لنا عندما نقوم بعملية compilation للسورس كود.

    السرفر هو ببساطة محرك اللعب .. فهو يقوم بتحريك و التحكم في كل شيء على مستوى اللعبة.

    الكلاينت هو جزء من محرك الرسم .. لكنه لا يرسم شيئا في الحقيقة .. كل ما يقوم به هو توجيه محرك الرسم لعمل شيء معين, مثلا اذا اردت رسم شيء جديد على الشاشة او اضافة عنصر الى الـ HUD فتقوم بذلك من الكلاينت .. لكن كود الرسم نفسها لن تجدها هنا بل كل ما تجده هو استدعاء لأوامر الرسم من المحرك.



    و لكن ... لو قمت بعمل مود جديد للتو, فعلى الأغلب انه لن يكون لديك اي خريطة ولا نماذج (مودلز) ولا شي .. فهل معنى هذا انك لن تستطيع لعب اللعبة لانه لا يوجد شي اطلاقا؟!

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

    اللذي يحصل ان المحرك عندما يبحث عن ملف معين (عن خريطة مثلا) فإنه يقوم اولا بالبحث في مجلد المود, و اذا لم يجده هناك فإنه يبحث في مجلد هاف لايف تو, فإذا لم يجده هناك يبحث في ملفات cgf (ملفات اللعبة اللتي حملها ستيم) فإذا لم يجدها هناك فإنه يستسلم و يطبع رسالة بأنه لم يستطع ايجاد الملف.

    (لست متأكدا من هذه هي الاماكن اللتي يبحث فها بالظبط .. لكن شي من هذا القبيل)



    حسنا دعنا من الكلام .. فلنأتي الى العمل: كيف احمل و ارتب الـ Source SDK؟



    كيفية إعداد الاس دي كي (أتحدث هنا عن الكود بشكل أساسي):

    من قائمة ستيم, هناك قسم tools اختر منه Source SDK ثم انتظر قليلا حتى تظهر واجهته (قد تضطر لتحميله اذا كانت هذه اول مرة) الآن اضغط Create a Mod هناك اربع خيارات .. اذا كنت مبتدءا فالأفضل ان تختار الأول او الثاني, و ربما الأول أسهل (لم اجرب الخيار الثاني بعد, حيث انه لم يكن موجودا في السابق سوى الخيار الأول و الثالث) الان ستختار المجلد اللذي سيذهب اليه الكود و تختار اسما للمود ...

    مجلد الكود هو المكان اللذي يستم وضع الكود فيه بعد قليل, اما اسم المود فسيكون مجلدا في هذا المسار .. اي داخل المجلد التالي:

    ….\steam\SteamApps\SourceMods

    فلو فرضنا ان ستيم موجود عندك في E:\Valve\Steam و انك اخترت اسم modx فإن المجلد اللذي يحتوى على مواد اللعبة (المود) سيكون:

    E:\Valve\Steam\SteamApps\SourceMods\modx



    هنا سيتم وضع الخرائط و الاصوات و النماذج و السكربتت و كل شيء خاص باللعبة .. ملفات اللعبة كلها هنا: هذه هي لعبتك!! و هذا هو المجلد اللذي تضعه في بارامتر الـ -game



    الآن إضغط next و سيبدأ البرنامج في نسخ الملفات اللتي تحتاجها (بما في ذلك ملفات البرمجة) .. في النهاية ستحصل على العديد من ملفات السي بلص بلص .. ستحتاج برنامج Microsoft Visual C++ .NET 2003 من اجل البرمجة ..

    افتح Game_sdk.sln .. هذا هو المشروع (solution .. لم اجد ترجمة اخرى لها) اللذي يحتوي على اهم شي و هو مشروعين: client.dll و server.dll

    قم بكومبايل للمشروعين (اضغط F7) العملية ستأخذ بعض الوقت .. هناك حوالي الف ملف يحتاج "كمبلة"

    الان لو ذهبت الى مجلد modx يجب ان ترى بداخله مجلد bin و بداخله ملفين server.dll و client.dll .. هنا تكمن اللعبة! ابسط مثال, عندما تعمل كليك عالماوس و تطلق النار .. كيف يتم ذلك؟ كله هنا! الذكاء الصناعي هنا .. باختصار اي شي تريد اضافته او ازالته من اللعبة هنا.



    و على فكرة الـ wizard يقوم بإعداد أغلب الاشياء اللتي تحتاجها, بحيث انك عندما تقوم بعملية compile فإنه يقوم أيضا بنسخ الملفات srever.dll و client.dll الى مجلد bin داخل مجلد المود .. فهذه النقطة تمت معالجتها من قبل ستيم ولا نحتاج نحن للقيام بأي شيء اضافي حيالها.

    لكن هناك بعض الاشياء اللتي سنحتاج لتعديلها نحن و هي اشياء ليست ضرورية %100 لكنها ستساعدنا كثيرا في البرمجة إن شاء الله.



    قبل ان تبدأ اللعب هناك شيئان عليك القيام بهما: أولا هذين الملفين عندما قمت بكومبايلتهما (هههه عالمصطلحات) فهما في الاساس debug build يعني فيهما معلومات اضافية تسمح لك بأن debug "تدبكهما" و لهذا يجب ان تخبر هاف لايف تو بذلك .. لفعل ذلك:

    افتح قائمة ستيم و رايت كلك على هاف لايف تو و اضغط launch parameter و اكتب (او اضف)

    –allowdebug

    الشي الاخر اللذي تحتاجه .. اذهب الى مجلدك (و اللذي سافترض ان اسمه modx) و افتح gameinfo.txt هناك سطر (حوالي ثالث سطر) يحدد اسم اللعبة كما يظهر في قائمة ستيم .. غيره الى اي شي تحب .. انا بالنسبة لي عملته



    game "Mod X"



    لكن لا تحاول ان تكتب كلمة عربية ..! لأنها لن تظهر.

    المهم, الان ما عليك الا أن تفتح قائمة ستيم و تضغط على اسم لعبتك و اللتي يجب ان تظهر تحت Third party games ..

    و تستطيع البدء في اللعب!

    طبعا لن تجد كل شي جاهزا تماما .. فلو ضغطت new game لن يحدث شيء يذكر .. لذلك إن اردت تحميل اي مرحلة يجب ان تفعل ذلك يديوا عن طريق الكونسول و اللذي تستطيع جلبه عن طريق الزر ` و هو نفس الزر ~ و هو حرف الذال "ذ" ثم اكتب map متبوعا باسم الخريطة .. مثلا:

    map test_map

    مع العلم ان test_map غير موجودة و ضربتها فقط كمثل!

    تعليق


    • #3
      السلام عليكم
      شكرا لك اخي العزيز على هذا الشرح و لكن لدي سؤال
      معظم MODs التي شاهدتها خاصة باللعب الجماعي فقط Multiplayer MODs
      سؤالي هو هل يمكن عمل MOD عبارة عن Single player compagne يعني قصة و اشخاص و كل شيئ جديد؟
      شكرا.

      تعليق


      • #4
        نعم فى لعبه مثل Operation FlashPoint

        سقوط الإنسان ليس فشلاً ولكن الفشل أن يبقى الإنسان حيث سقط
        العلم فى الصغر كالنقش على الحجر
        الغايه تبرر الوسيله

        تعليق


        • #5
          نعم, المفروض تستطيع عمل mod من نوع single player . على الأقل تستطيع ذلك على Half-Life 2

          تعليق


          • #6

            قبل أن ادخل في تفاصيل الـ SDK, أريد ان اتحدث عن بعض المفاهيم في البرمجة اللتي قد لا يعلمها كثير من المبتدئين .. فأنا اول ما نظرت الى كود هاف لايف لم أفهم شيئا .. لذلك سأحاول إن شاء الله ان اتكلم عن بعض الأشياء اللتي اظن انها كانت ستفيدني لو كنت أعرفها.

            طبعا شي طبيعي ان الانسان لا يفهم برنامج ينظر اليه لأول وهلة .. و لكن لأنني كنت مبتدئا جدا, كانت هناك الكثير من الاشياء اللتي لم افهم فائدتها و لماذا هي مرتبة بهذا الشكل.

            النقطة الأولى هي استخدام الـ classes بكثرة . فأنا كنت جديد ولا اعرف شي عن البرمجة الشيئية ولا أعرف فائدة الـ class ولا لماذا قد يحتاج اي شخص لاستخدامه!

            المسألة الثانية هي الـ pointers حيث انها مستخدمة بكثرة هي الأخرى .. صحيح انا كنت افهم ما معنى البوينتر جيدا و لكني لم اكن اعرف ما فائدته و كنت اظن انه لا يمكن الاستفادة منه بأي شئ!!

            البرمجة الشيئية:

            لنبدأ بسؤال .. ما هو المتغير؟ يبدو سؤالا بسيطا .. لكني لا ابحث عن اجابة سطحية.

            البعض قد يقول "هو مساحة في الذاكرة يمكن تغيرها و قرائتها" و هذا صحيح, لكنه تعريف سطحي جدا.

            لماذا نستخدم المتغيرات؟ اصلا لماذا نكتب برنامج؟

            في معظم الاحوال عندما كتابة برنامج حقيقي فإنه يؤدي لنا غرضا معينا, البرنامج هو حل لمشكلة معينة.

            هل هذا واضح؟ اذا كان عندك مشكلة مع كلمة "مشكلة" ففكر كالتالي: كل شي هو مشكلة .. و كل البرامج تريد حل مشكلة. اللعبة مثلا .. اي لعبة .. هي مشكلة: "كيف نرسم عالم واقعي على شاشة الكومبيوتر بتفاعل اللاعب معه؟" فأنت عندما تقوم ببرمجة لعبة فإنك تقوم بحل تلك المشكلة .. و هكذا.

            فعندما نعرف بعض المتغيرات, فنحن نريد التعبير عم بعض عناصر المشكلة, مثلا مكان اللاعب (احداثياته) في العالم الافتراضي هو عنصر من المشكلة .. نحتاج لمتغير لتخزينه و التعامل معه.

            لكن حتى هذا ليس تعريفا جيدا ..

            أنا حاليا ادرس هذه المفاهيم في الجامعة .. و قد قام الاستاذ بتقديم مبدء او فكرة جديدة علينا "State"! يعني "الحالة" او "الوضع". مالمقصود بهذا المصطلح؟

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

            الكومبيوتر طبعا لا يفهم لغة البشر, فلو قبت لكومبوتر "اللاعب يحمل سلاحين" , فلن يفهم شيئا من هذا .. فهو لا يفهم سوى الاصفار و الآحاد, لذلك لو كانت لدينا حالة معينة نريد ان نمثلها في ذاكرة الحاسوب فعلينا ترميزها بشكل يفهمه الحاسوب, لذلك نستخدم المتغيرات .. مثلا نعلن عن متغير نسميه number_of_weapons و نغير هذا المتغير بحسب الحاجة. كمثال بسيط فقط.

            فالمتغير هو تشفير "للحالة" في ذاكرة الحاسوب.

            طيب .. لننتقل من المتغيرات الى العمليات\الوظائف\الدوال\الفنكشنز (كل واحد يسميهة شكل! هه!) ما هي؟ او ما الهدف منها؟! هي ببساطة – حسب تعريف المتغير اللذي عرفناه قبل قليل- تعريف لكيفية استخدام الحالة و تغييرها. مثلا دالة تأخذ قطر الدائرة و ترسمها .. هذه الدالة تستخدم حالة الدائرة لعمل شيء معين. او دالة تقوم بتحريك شيء ما .. فهي تغير حالته.

            عادة عندما تحلل المشكلة اللتي بين يديك, تقوم بالبحث عن الحالات الموجودة و كيف تتغير هذه الحالات .. و تقوم بناءا عليه بتحديد المتغيرات و العمليات (الدوال).

            هذا طبعا في البرمجة العادية (الاجرائية .. غير الشيئية) او الـ procedural programming و لكن في البرمجة الشيئية object oriented programming فإننا لا نفرق بين الحالة و العمليات اللتي تغيرها, فنجمعهما معا .. بحيث ان الحالات و العمليات المتعلقة بكائن معين نجمعها في بنية او وحدة واحدة.. هذا هو الكلاس, او الصنف, او الفئة.

            فالكلاس هو التصنيف .. مثل ما يوحي اسمه .. هو يصنف الأشياء و يوصف خصائصها و يحدد تصرفاتها. لكن الكلاس مجرد تصنيف ..فهو ليس شيئا او كائنا بحد ذاته, و لكن عندما نقوم بإنشاء الكائنات, فإننا نستخدم الكلاس كـ"وصفة" لإنشائها .. فالكلاس لوحده يمكنك اعتباره تعريف لنوع جديد من المتغيرات .. فالتعريف نفسه ليس متغيرا .. بل هو مجرد تعريف لنوع من المتغيرات ..

            الفكرة من البرمجة الشيئية هي انك تريد تمثيل أشياء حقيقية داخل البرنامج, فكل شيء له وضع و له تصرف, فنحن نعبر عن هذه الأوضاع عن طريق متغيرات (member variables) و نعبر عن التصرفات عن طريق عمليات (methods or member functions)

            السيارة مثلا لها أوضاع قد تكون واقفة او متحركة, ربما ابوابها مفتوحة او مغلقة .. ربما تكون مقفلة!!
            هل هناك سائق يقود السيارة؟ من هو مالك السيارة؟ ما هو نوع السيارة؟ الخ .. كل هذه حالات تحدث للسيارة او اوضاع تتخذها.

            هناك ايضا افعال او تصرفات تقوم بها السيارة (او يقوم بها كائن آخر على السيارة) تستطيع تشغيل السيارة .. تستطيع فتح احد بيبانها او إغلاقه, تستطيع إقفاله, تستطيع ضغط على مكبس البنزين, تستطيع الضغط على المكابح, تستطيع لف المقود مثلا .. الخ.

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

            فالخلاصة اننا عند تحليل المشكلة في البرمجة الشيئية, نقوم بالبحث عن كائنات ..

            مثلا اريد برمجة نظام يتابع سجل الطلاب و المواد اللتي سجلوا عليها و المواد اللتي يحجتاجونها .. الخ.
            عند التحليل سأجد مثلا ان هناك مجموعة من الطلاب, هؤلاء الطلاب يسجلون في كورسات, فإذا يبدوي ان لدي كائن الطالب و كائن الكورس, حسنا .. الطلاب قد ينهون الكورس و يأخذون درجة فيه .. هممم .. اين ستذهب الدرجة؟ حسنا سنعدل التصميم, سنقوم بإنشاء كائن "التسجيل" و هذا الكائن يربط الطالب بالكورس, و درجة الطالب في نهاية الكورس هي جزء من عملية التسجيل لأنها مرتطبة بها.

            لاحظوا ان الانضمام لكورس ليس كائنا بحد ذاته في الحقيقة, و لكننا نعبر عنه بكائن لأنه يتصرف بطريقة معينة و له حالات معينة.
            الحقيقة فإن الكائنات ليس فقط اشياء حسية ملموسة .. بل أي مفهوم عام نعبر عنه بكائن.

            طبعا لو واصلنا التحليل السابق .. هناك ايضا اساتذة يدرسون هذه الكورسات .. فربما سننشئ كائنا للاستاذ, طبعا هذا الاستاذ جزء من قسم داخل الكلية, فلنشء ايضا كائنا للقسم, الخ ... المهم وضحت الصورة.



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

            هناك مفهومين مهمين في البرمجة الشيئية: الوراثة و الـ polymorphism

            الوراثة أو الـ inheritance هي انك تعرف كلاس على انه مشتق من كلاس آخر .. مثلا عندك كلاس مركبة .. تشتق منه كلاس سيارة.

            لنفرض انك اثناء التخطيط للبرنامج وجدت انك تحتاج كائنات للطلاب و الموظفين و الاساتذة و الكوادر ..

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

            المفهوم الآخر و هو تابع للوراثة (و هو الأهم) و اللذي هو polymorphism فسنتحدث عنه بعد قليل إن شاء الله.

            المؤشرات Pointers

            موضوع مخيف للمبتدئين .. لكنه ليس بذلك التعقيد. السبب الأساس في انه يبدو معقدا بحسب رأيي هو عدم وجود أمثلة تطبيقية .. يعني الواحد يسمع بالبوينتر و يقعد يقول لنفسه "ما فائدته؟" فسأحاول إن شاء الله ان اتحدث عن احد اهم تطبيقاته .. الـ linked lists, و لكن بطريقة عامة بحيث اتحدث عن المفاهيم دون الخوض في تفاصيل التطبيق.

            الـ arrays (أرَّيز) او المصفوفات, هي طريقة لربط سلسلة او قائمة من المتغيرات بحيث نستطيع الوصول لأي عنصر من عناصر القائمة و قراءة محتوياته و تعديلها دون الحاجة لتعريف كل عنصر كمتغير بحد ذاته. مثلا عندك شركة فيها مئة موظف .. ايهما افضل, ان تنشئ مئة متغير كل على حدة ام ان تنشئ مصفوفة و تحصل على نفس النتيجة؟

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

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

            هذه بعض النقائص الموجدة في المصفوفات و رغم ان هناك بعض الحلول لها (مثل استخدام الـ vectors) و لكن هناك وسائل بديلة (و أسهل) لربط سلسلة طويلة من العناصر .. و احدى هذه الوسائل هي linked list يعني سلسلة مترابطة. باختصار هي سلسلة من الكائنات (معرفة كنوع struct او class) يحتوي كل كائن على مؤشر pointer الى العنصر اللذي يلي في السلسلة.

            ابسط مثال:

            كود:
             struct list_s
            كود:
             
            [left]{[/left]
             
            [left]char ch;[/left]
             
            [left]list_s *next;[/left]
             
            [left]};[/left]
            [left][/left]


            فهذا struct بسيط كل ما يحويه هو حرف و مؤشر (المؤشر هو فعليا مجرد رقم .. يعني هذا الـstruct لا يحتوي نفسه .. بل يحتوي حرف و رقم)

            الان نستطيع ربط عدد من العناصر ببعضها عن طريق ربط المؤشة next في كل عنصر بالعنصر التالي بحيث يصبح عندنا قائمة من العناصر كل عنصر منها يشير الى العنصر التالي, و العنصر الاخير سيشير الى NULL.

            نستطيع الوصول الى اي عنصر من هذه العناصر اذا كان لدينا مؤشر الى العنصر الأول, نستطيع عمل loop للوصول لأي عنصر و ذلك عن طريق تحريك المؤشر الى الـ next و بنفس الطريقة نستطيع اضافة عنصر جديد الى القائمة عن طريق تحريك الـpointer حتى النهاية ثم اضافة عنصر جديد عند الـ next.

            هذه مثلا طريقة إنشاء عشر عناصر مترابطة بحيث كل عنصر يشير للتالي:


            كود:
            [left]list_s *p = NULL, *head = NULL;[/left]
            
            [left]p = new list_s;[/left]
            
            [left]head = p;[/left]
            
            [left]p->ch = 0;[/left]
            
            [left]p->next = NULL;[/left]
            
            
            
            [left]for( int i = 1; i < 10; i++ )[/left]
            
            [left]{ [/left]
            
            [left]p->next = new list_s;[/left]
            
            [left]p = p->next;[/left]
            
            [left]p->ch = i;[/left]
            
            [left]p->next = NULL;[/left]
            
            [left]}[/left]
            
            [left][/left]


            إذا كان اي من هذه الاسطر يبدو غريبا مثل new فراجعوا http://cplusplus.com/doc/tutorial/tut3-4.html

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

            ربما يبدو هذا السطر غريبا بعض الشئ:



            كود:
             p = p->next;


            نحن ببساطة نغير عنوان المؤشر ليصبح العنصر التالي ..

            طيب .. نلاحظ ان العناصر كلها يتم حجزها ديناميكيا و ان السلسة مترابطة عن طريق المؤشرات. لذلك نستطيع بكل بساطة اضافة عنصر جديد الى السلسلة .. و نستطيع ادخال عنصر في وسط السلسلة (مجرد تلاعب بسيط بعنواين المؤشرات) و نستطيع كذلك حذف اي عنصر من السلسلة. الخ.

            اهم نقطتين هنا هما الآتي:

            أولا: نستطيع داخل البرنامج ان نحجز مساحة جديدة في الذاكرة من أجل متغير جديد في اثناء تنفيذ البرنامج runtime عن طريق new .. هذا الحجز يتم بطريقة ديناميكية بحيث اننا لا نعرف مسبقا كم مرة سيحدث, ولا يوجد اسم معين لمتغير محدد يصل لهذا المتغير (على الأغلب يكون كائنا object) لذلك نستخدم الـ pointers للوصول لهذه المساحات.

            ثانيا نستطيع ربط سلسلة من العناصر ببعضها عن طريق وضع مؤشر في كل عنصر للعنصر التالي .. فبذلك نستطيع انشاء العديد من العناصر ووضعها في سلسلة ثم الوصول لأي عنصر و الحصول على عنوانه بحيث يكون عندنا مؤشر للكائن لكي نتعامل معه.



            هذه كانت احدى العقبات اللتي واجهتني اول ما نظرت الى كود هاف لايف .. كنت وقتها جديدا على البرمجة و لم افهم ما فائدة المؤشرات (و لم اكن حتى أعلم بـ new او حتى فائدتها) و م اكن اعرف كثيرا عن الـ classes و لكنني وجدت كل هذه الاشياء اللتي لا اعلم فائدتها مستخدمة بكثرة .. فكان هذا يحيرني كثيرا (مع أنني لم أفهم شيئا من الكود أصلا!!! بغض النظر عن المؤشرات و الكائنات!!)



            لذلك لا تستغربوا إن وجدتم أن كود "هاف لايف تو" تستخدم المؤشرات بكثرة ..و أن كل شي فيها عبارة عن كائن .. و كل التعاملات مع الكائنات تكون عن طريق المؤشرات ..

            لكن لماذا؟ ببساطة لان المبرمج ليس لديه أية فكرة عن عدد الأشياء داخل اللعبة اثناء كتابة البرنامج .. فهذا الأمر يعتمد اولا على الخريطة (المرحلة) بعض المراحل ربما يكون فيها عشرة وحوش و خمسة جنود .. مرحلة اخرى قد لا يكون فيها اي وحش لكن فيها ثلاثين جنديا!! مثلا. او في الملتي بلير .. ليس لديك فكرة كم لاعبا سينضم للسرفر .. و كذلك لا تدري متى ينضم اللاعبون او يتركون السرفر!!

            فلادارة مشكلة مثل هذه, نقوم بكتابة كود مثلا لقراءة الخريطة و انشاء العناصر بحسب المعلومات الموجودة في المرحلة .. ثم عمل loop على كل العناصر اثناء اللعبة و ارسال مؤشراتها الى methods معينة لتقوم بتحديث كل الكائنات في اللعبة, في الغالب سنستخدم الـ polymorphism لكي يقوم كل كائن بتحديث معلوماته بطريقته الخاصة. يمكنكم مراجعة بعض الدروس من الانترنت عن هذا الموضوع

            http://cplusplus.com/doc/tutorial/tut4-4.html

            http://forums.dreamincode.net/index.php?act=Attach&type=post&id=106448



            بصراحة الـ polymorphism احد اهم مفاهيم البرمجة الشيئية لذلك ربما يجب ان اتحدث عنها أكثر قليلا. لكني لا اريد شرح كل شيء .. اريد اعطاء مفاهيم عامة و اترك الباقي لكم .. كما أنني اريد هنا ان اتحدث عن برمجة "هاف لايف تو" و هذا الكلام عن البرمجة مجرد مقدمة .. كما ان النت مليء بدروس عن البرمجة, سأتحدث عن الموضوع باختصار إن شاء الله

            تعليق


            • #7
              تحدثنا عن الوراثة .. و عن المؤشرات.

              اول شي نحتاج ان نعرفه لفهم "البوليمورفزم" انك تستطيع ان تجعل مؤشرا للكلاس الأب يؤشر الى كائن من كلاس مشتق عنه.

              مثلا لو كان عندنا class CShape و كلاس مشتق عنه class CCircle : public CShape فنستطيع عمل الآتي:



              كود:
              [font=Courier New]CShape *shape = [color=blue]new[/color] CCircle();
              [/font]



              انظروا الى الكود .. مؤشر لفئة الأشكال يشير الى كائن من فئة الدوائر.

              قد يبدو غريبا لكن لو فكرتم فيه .. فهو منطقي؛ الدائرة هي في النهاية شكل .. ولا بد ان نستطيع ان نشير اليها على أنها شكل.

              الفائدة هنا هي اننا نستطيع ربط كائنات مختلفة (بعض الشيء) في سلسلة واحدة, لأن السلسلة تعتمد في ترابطها علىالمؤشرات .. فكل عنصر في السلسلة يرث مؤشر الـ next و هذا المؤشر يستطيع الإشارة لأي كائن من فئة الأشكال!! فممكن نحصل على قائمة بحيث يكون عنصرها الأول دائرة, و الثاني مثلث, و الثالث مربع .. الخ.

              في اللعبة مثلا .. كل شي متحرك (و حتى بعض الاشياء غير المتحركة) هو عبارة عن entity ففي تعريف اللعبة, كل شيء له خصائص مشتركة و هي: ان هناك model يجب تحميله لعرض الكائن .. هذا المودل له animations و كل الكائنات يجب ان يتم تحديثها مرة في كل أطار frame .. و غيرها من الخصائص المشتركة.

              فنستطيع ربط كل شيء في اللعبة بسلسلة و نستخدم لأجل ذلك مؤشرات لـ entities فبذلك لا نحتاج للقلق عن تفاصيل الكائن اللذي يشير إليه كل مؤشر .. يكفي انه entity في اللعبة.



              الأمر الآخر .. و هو الأهم: نستطيع تعريف method في الكلاس الرئيسي ثم نعيد تعريف هذا الـ method في الكلاس الفرعي بحيث نغير طريقة تنفيذه .. في هذه الحالة نستطيع تعريف ميثود معين مثل Draw و هو بالنسبة لفئة الأشكال مفهوم عام .. تطبيقه يختلف من شكل معين الى آخر.

              فكل نوع من الأشكال (كل كلاس فرعي) يعيد تعريف هذا الـmethod حسب نوع الكلاس .. فالدائرة ستقوم برسم دائرة .. و المربع يقوم برسم مربع .. و الملث يرسم مثلث .. الخ.



              الآن .. هنا بيت القصيد, عندما يكون عندك بوينتر من الكلاس الأساسي يشير الى كائن من كلاس فرعي, و تستدعي الميثود Draw فإن الفنكشن اللذي سينفذ لن يكون CShape:raw بل سيكون الـ Draw الخاص بالكائن المعني بالشأن .. فلو كان لديك مؤشر CShape يشير الى كائن CCircle كما في المثال السابق .. فإن السطر:

              كود:
              shape->Draw();



              سيقوم بتنفيذ CCircle:raw لأن الكائن هنا هو من نوع CCircle لذلك عندما تستدعي الـ Draw() فأنت تستدعي هذا الـ method على الكائن اللذي هو دائرة .. و سيتم استدعاء ذلك الـ method الخاص بالدائرة بالذات .. رغم ان المؤشر shape هو من نوع CShape.

              قد تقول: كيف يعرف الكومبايلر ذلك؟

              الحقيقة ان الكومبايلر لا يعرف ذلك .. فهذه العملية تتم اثناء تنفيذ البرنامج.

              يمعنى .. ممكن يكون عندك قائمة مترابطة linked list بها عشرة أشكال .. لكن كل شكل هو من نوع مختلف عن الآخر (واحد مثلث و الاخر دائرة و آخر مربع .. الخ) و قمت بعمل loop على القائمة بحيث تمر على كل عنصر و تستدعي Draw على ذلك الكائن باستخدام مؤشر للكلاس الرئيسي .. فإن كل عنصر من هذه العناصر سينادي الفنكشن الخاص به ..

              طبعا لما يكون عندك حلقة تكرارية loop فإنك ستكتب السطر shape->Draw() مرة واحدة .. لكن في كل حلقة من حلقات الـloop ستستدعي فنكشن مختلف عن الآخر .. اي فنكشن سيتم استدعائه؟ هذه يتم تحديدها أثناء تشغيل البرنامج.

              (على فكرة .. لهذا اسمه method .. لأنه تعريف طريقة تنفيذ مهمة معينة .. فالمهمة هي نفسها .. لكن "طريقة" تنفيذها تختلف من كلاس الى آخر).



              فهذه هي البولي مورفزم: انك عندك فنكشن معرف عدة مرات .. و عندما تكتب سطرا في البرنامج يستدعي هذا الفنكشن .. فأنت لا تعرف بالظبط أثناء كتابة البرنامج أي نسخة من الفنكشن سيتم استدعائها .. فهذا يتم تحديده اثناء تنفيذ البرنامج .. يعني at run time.



              هناك تطبيقات مهمة جدا لهذه الخاصية .. و هي مستخدمة بكثرة في هاف لايف تو, فكل entity في اللعبة موجودة في سلسلة مترابطة و في كل إطار frame من اللعبة يتم المرور على كل هذه الكائنات و تحديثها عن طريق استدعاء methods معينة لذلك. (هذا الكلام مختصر شوية و ربما غير دقيق تماما لكنه يعطيكم فكرة عامة عن تطبيق هذه الخاصية في كود اللعبة).



              أعرف ان هذا الكلام ربما نظري جدا و قد يبدو غامضا لأنه ربما كلام عام و عائم جدا لا يحتوي الكثير من الأمثلة .. لكنني أحببت أن أعطيكم فكرة مسبقة عن طبيعة الكود التي ستقابلونها إن شاء الله كي لا تُفاجَئو كثيرا.

              تعليق


              • #8
                مجهود رائع أخي hasan-rtaq تشكر و بالنسبة للمشرعة فأنا مستعد و سأكون من يصنع المراحل لأني محترف في برنامج Hammer

                تعليق


                • #9
                  السلام عليكم
                  الحقيقة والله موضوع رائع
                  ولكن أخي هلا وضعت رابط المحرك لأني لم أجده
                  وشكرا
                  http://mojazef.incohost.com/3.jpg

                  تعليق


                  • #10
                    للأسف لا يمكنني وضع رابط للتحميل لأنه لا يوجد ..
                    لا يمكنك تحميله إلا من خلال Steam

                    تعليق

                    يعمل...
                    X