السلام عليكــم ورحمـة الله وبركاتــه ،،
هذا الموضوع ناتج بعد الاتفاق على بدء مشروع محرك ألعاب .. سيتم تسميته وبشكل مؤقت بالأندلس كاسم حركي للمشروع .
Al-Andalus Game Engine
قد تجدون الموضوع ممل .. وروتيني .. ولكن ليس أمامنا حل .. الا الاتفاق على طريقة في العمل .. اذا كنا فعلا نريد أن نحقق شيء .. كل ما سأذكره مجرد اقتراحات .. أي شخص لديه ملاحظة أو اعتراض فليطرحها دون تردد .. لن نطيل في هذا الموضوع .. لنبدأ بالعمل مباشرة ان شاء الله خلال سويعات أو أيام قليلة .. وسيكون هذا الموضوع مرجع ومستند للمشروع ككل .
الأدوات المستخدمة :
- النسخة 0.1
- لغة السي بلس بلس
- سيتم الاعتماد على مكتبات السي بلس القياسية بما فيها STL وذلك فيما يخص هياكل البيانات + الملفات + النصوص std::string .. الخ .
- نظام ويندوز اكس بي - فيستا :
- Visual C++ 2008 Professional
- OpenGL 1.1 تأتي مع المترجم بشكل تلقائي
- سيتم استخدام Win32 API في انشاء النافذة وربطها مع المكتبة الرسومية
- مبدئيا سنستخدم Win32 APIs لاستقبال المدخلات من الكيبورد والماوس اذا لم توجد طريقة أفضل
- Direct3d 9.c ولن تأتي مع المشروع .. على من يريد دعم الدايركت ثري دي أن يقوم بتحميل النسخة المناسبة وربطها مع المحرك ووضع شرح لرقم النسخة المستخدمة من sdk وطريقة الربط
[*]نظام لينكس :
- لا أعرف ماهي المكتبات والأدوات المطلوبة , من يريد التطوير على لينكس المساعدة في شرح المطلوب
- في الغالب سيتم استخدام SDL + OpenGL
[*]يمكن استخدام المكتبة QT لمن أراد دعمها , وتستخدم لانشاء النافذة وربطها مع OpenGL واستقبال المدخلات من الكيبورد والماوس وغير ذلك .. وهذا كاضافة للمحرك وليس ركن أساسي فيه .
- Visual C++ 2008 Professional
[*]لغة الجافا:
- JDK 6 Update 16 with NetBeans 6.7.1
- مكتبة OpenGL للرسوميات وسيتم استخدام المكتبة LWJGL لدعم OpenGL :
لتثبيت المكتبة وتطبيق درس أساسي بسيط انظر :
/index.php?showtopic=165722
لاتحتاج الى اتقان OpenGL , يمكنك تجنبها والمساهمة في تطوير الاجزاء التي لاتعتمد على المكتبة OpenGL . - سيتم استخدام مكتبات الجافا القياسية في التعامل مع الملفات + هياكل البيانات+أي شيء اخر
[*]لغة السي شارب
- يمكن لأي شخص أن ينشئ مشروع خاص بهذه اللغة ويختار أحد الخيارين التاليين:
- Visual C# 2005 + XNA 2
- Visual C# 2008 + XNA 3
[*]تسمية المتغيرات والدوال والأصناف
- في لغة السي بلس , أرى أن نعتمد طريقة الجافا في كتابة الكود .. أجد أنها الافضل , مثال :
namespace Andalus
{
namespace Gfx
{
class Graphics
{
virtual void drawPoint(int x,int y ,Color color)=0;
};
class D3dGraphics : public Graphics
{
private:
Color pointColor;
int xPos;
int yPos;
void _privateFunction();
public:
void drawPoint(int x,int y,Color color)
{
const int MAX_XPOS = WINDOW_WIDTH ;
int tempVariable = 0;
int i,j,k;// counters
this->pointColor = color;
this->xPos = x;
this->yPos = y;
.
.
.
}
};
}//gfx
}//andalus - كل كلاس class يكون في ملف مستقل ( ملف header للتعريف فقط وخالي من أي implementation قدر الامكان وملف source لكتابة الكود ) , ويكون اسم الملف مطابق تماما لاسم الكلاس حتى بحالة الاحرف.
- يتم حراسة ملف الهيدر بالـ preprocessor بهذا الشكل :
#ifndef GFX_Graphics_H #define GFX_Graphics_H . . #endif
- الجافا والسي شارب تتبعان أسلوب كتابة الأكواد الأصلي في اللغة :
[*] اسماء الفئات و الـ strcut و enum و union كلها تبدأ بحروف كبيره و بدون استخدام بادئة , وجميعها تكون داخل namespace معين.
[*] اسماء المتغيرات تبدأ بحروف صغيره و اى كلمه تليها بدأ بحروف كبيره.
[*] اسماء الدوال تبدأ بحروف صغيرة و اسماء المعاملات تكون بحروف صغيره دائما.
[*] يتم تعريف المتغيرات قبل استخدامها و يتم كتابة ملاحظات فوقها لسبب تعريف هذا المتغير و فيما استخدامه
[*] التوثيق ( شرح واجهة المحرك وذلك من أجل انشاء ملف تعليمات للمحرك ) يكتب فوق كل انواع البيانات و سيتم استخدام مايلي :
doxygen في كتابة شرح الكود , للغة السي بلس , ابحث عن أمثلة وشرح لهذه الاداة , هذا مثال :
/** * @file tutorial.h * @author Chris Olsen * @date 2-26-04 */ #ifndef __TUTORIAL__ #define __TUTORIAL__ /** * An example class for the Doxygen tutorial */ class Tutorial { public: /// The Constructor Tutorial(); /** The Destructor */ virtual ~Tutorial(); /** Takes three inputs and does something @param a A float paramater @param b An int paramater @param c A char paramater @return Returns an integer */ int Method1(float a, int b, char c); int var; ///< This was commented after declaration }; #endifjavadoc للغة الجافا , مثال :
/** * Returns an Image object that can then be painted on the screen. * The url argument must specify an absolute {@link URL}. The name * argument is a specifier that is relative to the url argument. * <p> * This method always returns immediately, whether or not the * image exists. When this applet attempts to draw the image on * the screen, the data will be loaded. The graphics primitives * that draw the image will incrementally paint on the screen. * * @param url an absolute URL giving the base location of the image * @param name the location of the image, relative to the url argument * @return the image at the specified URL * @see Image */ public Image getImage(URL url, String name) { try { return getImage(new URL(url, name)); } catch (MalformedURLException e) { return null; } }السي شارب , سيتم استخدام وسم xml ( انظر المشاركة رقم 7 ) .
أما فيما يتعلق بكتابة تعليقات على الكود الداخلي للمحرك , فيتم بطريقة عادية ( مثل // أو /* */ )
[*] يتم تنظيم الكود و يتم استخدام الأقواس { } دائما مع for او if حتى لو كان الكود مكون من سطر واحد و ذلك لوجود ملاحظات فوق الكود و ايضا لتسهيل قرائة الكود، ايضا يمكنك استخدام تلك الأقواس فقط مع بعض الأكواد لتجميعها و ذلك لتنظيم الكود.
[*]للغة السي بلس :سيتم استخدام الكلمة interface للدلالة على الواجهات , والكلمة pure للدلالة على pure funcion , هكذا :
#define interface struct #define pure = 0 . . . interface X { virtual void pureFoo() pure; }كما سيتم اعتماد Alias معين لبعض الانواع .. سيتم شرحه أثناء مراحل المشروع
[*]طريقة اكتشاف الأخطاء ومعالجتها :
ماهي أفضل طريقة ؟!!
اقترح استخدام الاستثناءات Exceptions , في اقتناص الاخطاء خصوصا عن التعامل مع الملفات أو عمل أمور حرجة , في الامور البسيطة مثل الموجودة في الحزمة core الخاصة بالدوال الرياضية مثلا .. لاحاجة الى الاستثناءات حتى لايؤثر على اداء المحرك .
أيضا سنستخدم log (كتابة الى الملف ) وهو على مستويين .. DEBUG لتتبع اي عملية حجز أو الغاء للكائن أو في أي مكان حرج مثل تحميل صورة من ملف هل نجحت العملية أم لا ؟
.. المستوى الاخر INFO لكتابة معلومات عن المحرك والعتاد الذي يعمل عليه .. وفي الغالب ستكون معلومات بسيطة عن كرت الشاشة والعتاد الذي يستخدمه المستخدم النهائي .
[*]الطريقة التي سنسير عليها في المشروع + مثال :
- كل حزمة package من المشروع سيفرد لها موضوع خاص - تقريبا - ( سنأخذ مثال , على حزمة الصور image . )
- في كل موضوع سيكون الحديث عن أربع نقاط بالترتيب :
- التحليل الأولي للموضوع : ( لايوجد علاقة للغة البرمجة هنا )
- هنا نعرف فائدة هذه الحزمة , في حالتنا هذه image , وهي تضم واجهات interfaces و فئات Classes لتحميل صورة من ملف وتخزينها في كائن موجود في الذاكرة مصمم لهذا الغرض .
- يأتي مبرمج , ويقترح ان ندعم نسقين من الصور BMP - TGA .
- يأتي مبرمج اخر , ويقترح أن تكون الصور المدعومة غير مضغوطة Uncompressed , وتكون من نوع 32Bits و 24Bits فقط .
- يأتي مبرمج ثالث , ويقترح اضافة ميزة امكانية تغيير أبعاد الصورة بعد تحميلها واضافة تاثيرات عليها مثل ازالة الألوان الغير مرغوبة من الصورة .
- هنا تبدأ تتضح معالم Classes و Interfaces و Enumerations التي سنحتاجها .. والعلاقات بين الكلاسات Classes :- ImageBuffer <class>
{
int width,height,bpp;
bytes color[] ;
ImageFormat format;
}
- ImageUtil .
- ImageReader <interface>
- ImageWriter <interface>
- BmpImageReader <class that implements ImageReader>
- BmpImageWriter <class that implements ImageWriter>
- ImageFormat
{
IF_RGBA,IF_RGB .....
} - كتابة مواصفات Specification للكلاسات Classes التي سيستخدمها المستخدم النهائي . ( لايوجد علاقة للغة البرمجة هنا )
هنا .. الكلاسات التي سيستخدمها المستخدم النهائي هي ImageReader و ImageWriter و ImageBuffer و ImageUtil ، فنكتب مواصفاتها :// Interface that read an image from specific file into ImageBuffer
ImageReader <interface>
{
/// @Purpose : load an image from specific file and create new object of ImageBuffer
/// that holds image info .
/// @Parameters:
/// - fileName : image file name ( full path ) .
/// @return :
/// on success :new ImageBuffer object holds image info
/// on failure : NULL;
/// @Exception :
/// FileNotFoundException if the image does not exist .
/// FileFormatNotSupportedException if the image format is not supported.
[byRef] ImageBuffer read( [iN] string fileName) ; <pure virtual method >
};
بهذا تكون المعلومات واضحة لكل من اراد تحويل الكلام السابق الى كود . - اسناد مهمة تحويل هذه الكلاسات الى كود أي عمل Implementation لواجهة المحرك المذكورة في هذا الموضوع
- الان كل شخص يتحمل جزء من مسؤولية تحويل بعض الواجهات والكلاسات الى كود .. قد نواجه مشاكل .. نبحث .. ونتساعد حتى نحل الاشكال , في الغالب المشاكل ستخص المفاهيم وليس مشاكل بسبب عدم معرفة في لغة البرمجة المستخدمة .. نفرض أن المشاركين , يتقنون اللغات المستخدمة .
طبعا كل لغة برمجية .. سيكون لها ملفاتها الخاصة دون وجود تعارض بينها .. كل شخص يركز على اللغة التي يريد لتحويل ما سبق من نقاش الى كود . - عمل اختبارات للناتج النهائي ثم تجميع الأكواد في حزمة واحدة وضمها للمحرك
حيث يتم تجميع كل ماقام به الاعضاء واضافتها للمشروع ( ملفات السي بلس تضاف الى مشروع السي بلس و ملفات الجافا تضاف الى مشروع الجافا , كل مشروع مستقل عن الاخر ولكن واجهة المحرك واحدة وان اختلف الكود الداخلي ) .. ونختبر الكود لتحميل صورة معينة وعرض بيانتها .
ثم نغلق هذا الموضوع لننتقل الى الحزمة التالية . - في بعض الحزم - بعض أجزاء المشروع - نحتاج الى أكثر من موضوع , وذلك بسبب اختلاف بنية الكود بشكل جذري من لغة الى أخرى .. وفي هذه الحالة يتم مايلي .
1- الموضوع الرئيس , وهو كما تم وصفه في النقطة السابقة .. يناقش ويحلل الحزمة بغض النظر عن اللغة البرمجية ثم يتم كتابة كود الحزمة باستخدم لغة السي بلس
2- في موضوع منفصل يتم مناقشة كيفية تحويل المناقشات التي وردت في الموضوع الرئيس .. الى كود في الجافا
3- يتم فتح موضوع منفصل للغة السي شارب يتم مناقشة كيفية تحويل المناقشات التي وردت في الموضوع الرئيس .. الى كود في السي شارب
- التحليل الأولي للموضوع : ( لايوجد علاقة للغة البرمجة هنا )
- Visual C# 2005 + XNA 2
- سيتم الاعتماد على مكتبات السي بلس القياسية بما فيها STL وذلك فيما يخص هياكل البيانات + الملفات + النصوص std::string .. الخ .


