Sprite *S = new Sprite();
ObjectOutputStream::writeObject( S) ;
class Object {
virtual void storeInFile(const Stream& str);
virtual void loadFromFile(const Stream& str);
virtual String toString();
virtual void writeToXML(const XMLStream& str);
}
class Object
{
public:
virtual ~Object() {} // لا تنسى هذا السطر، فهو ضروري جداً
virtual void storeInFile(Stream& strm) = 0
{
strm << PosX;
strm << PosY;
}
virtual void loadFromFile(Stream& strm) = 0
{
strm >> PosX;
strm >> PosY;
}
protected:
float PosX,PosY;
};
class ColoredMesh : public Object
{
public:
virtual ~ColoredMesh() {}
virtual void storeInFile(Stream& strm)
{
Object::storeInFile(strm);
strm << ColorR;
strm << ColorG;
strm << ColorB;
}
virtual void loadFromFile(Stream& strm)
{
Object::loadFromFile(strm);
strm >> ColorR;
strm >> ColorG;
strm >> ColorB;
}
protected:
float ColorR;
float ColorG;
float ColorB;
};
class MonochromeMesh : public Object
{
public:
virtual ~MonochromeMesh() {}
virtual void storeInFile(Stream& strm)
{
Object::storeInFile(strm);
strm << ColorIntensity;
}
virtual void loadFromFile(Stream& strm)
{
Object::loadFromFile(strm);
strm >> ColorIntensity;
}
protected:
float ColorIntensity;
};
void main(void)
{
FileStream strm("C:\\GameFile.bin");
// الآن نريد تحميل الملف، لكننا لا نعلم ما هو نوع الكلاس المطلوب إنشاؤه
// أي السطرين التاليين هو الذي يجب تنفيذه؟
//Object *pObject = new ColoredMesh();
//Object *pObject = new MonochromeMesh();
pObject->loadFromFile(strm);
}
FileStream strm("C:\\GameFile.bin"); // فتح ملف اللعبة
Object *pObject = Object::Load(strm); // تحميل الجسم من الملف
C3DMesh *pMesh = dynamic_cast(pObject);
if (pMesh)
{
pGame->AddMesh(pMesh);
}
else
{
// It is not a mesh, it is something else!
cout << pObject->GetType() << endl;
}
// قائمة بجميع أنواع الأجسام التي ندعمها
enum ObjectType
{
Type_MeshColored,
Type_MeshMonochrome,
};
// الكلاس الأساسي لكل الأجسام في اللعبة
class Object
{
public:
Object(ObjectType type) : MyType(type)
{
}
virtual ~Object() {}
static void Save(Stream& strm,Object *pObject)
{
strm << (int)pObject->MyType; // حفظ نوع الجسم
strm << pObject->PosX;
strm << pObject->PosY;
pObject->storeInFile(strm); // حفظ المعلومات الإضافية الخاصة بالجسم الفعلي
}
static Object* Load(Stream& strm);
protected:
virtual void storeInFile(Stream& strm) = 0;
virtual void loadFromFile(Stream& strm) = 0;
float PosX,PosY;
private:
ObjectType MyType;
};
// جسم ملون
class ColoredMesh : public Object
{
public:
ColoredMesh() : Object(Type_MeshColored)
{
}
virtual ~ColoredMesh() {}
protected:
virtual void storeInFile(Stream& strm)
{
strm << ColorR;
strm << ColorG;
strm << ColorB;
}
virtual void loadFromFile(Stream& strm)
{
strm >> ColorR;
strm >> ColorG;
strm >> ColorB;
}
protected:
float ColorR;
float ColorG;
float ColorB;
};
// جسم رمادي
class MonochromeMesh : public Object
{
public:
MonochromeMesh() : Object(Type_MeshMonochrome)
{
}
virtual ~MonochromeMesh() {}
virtual void storeInFile(Stream& strm)
{
strm << ColorIntensity;
}
virtual void loadFromFile(Stream& strm)
{
strm >> ColorIntensity;
}
protected:
float ColorIntensity;
};
// كود التحميل المركزي في المحرك
Object* Object::Load(Stream& strm)
{
int ObjectType;
strm >> ObjectType; // حمل نوع الجسم المحفوظ في الملف
// الآن ننشئ الجسم الصحيح بناءً على النوع المحفوظ في الملف
Object *pNewObject = NULL;
switch (ObjectType)
{
case Type_MeshColored:
pNewObject = new ColoredMesh();
break;
case Type_MeshMonochrome:
pNewObject = new MonochromeMesh();
break;
}
// تحميل الخصائص المشتركة
strm >> pNewObject->PosX;
strm >> pNewObject->PosY;
pNewObject->loadFromFile(strm); // تحميل المعلومات الخاصة الإضافية
return pNewObject; // جاهز للاستخدام المباشر
}
void main(void)
{
FileStream strm("C:\\GameFile.bin"); // فتح ملف اللعبة
Object *pObject = Object::Load(strm); // تحميل الجسم من الملف
// افعل أي شيء بالجسم الذي تم تحميله
Object::Save(strm,pObject); // حفظ الجسم في الملف
delete pObject; // لا ننسى تحرير الجسم ;)
}
وفي 29 يونيو 2008 10:00 ص، أعرب الشمري عن رأيه بالموقف كالآتي:
المستخدم للمحرك .. لن يستطيع أن يدعم كائناته التي صنعها بنفسه وورثت من Object ..typedef Object* (*ObjectFactory)(int classType); // تعريف نوع (مؤشر إلى إجراء) ـ
static Object* EngineFactory(int classType)
{
switch (classType)
{
case Type_Mesh: return new Mesh();
case Type_Light: return new Light();
case Type_Texture: return new Texture();
}
return NULL; // Unknown type
}
static vector g_Factories; // مصفوفة بكل المصانع المدعومة
// الإجراء الرسمي لإنشاء الكلاسات في البرنامج بشكل عام
Object* CreateObject(int classType)
{
// حلقة تدور على كل المصانع المسجلة لتجد المصنع المناسب
for (unsigned int i=0;i<vector.size();i++)>
{
Object *pNewObject = g_Factories[i](classType); // نداء المصنع
if (pNewObject != NULL)
return pNewObject; // تم إنشاء الكلاس بنجاح!
}
// لو وصلنا إلى هنا فهذا يعني أننا نواجه نوع كلاس غريب غير مدعوم من أي مصنع مسجل
return NULL;
}
// الإجراء الرسمي لتسجيل المصانع في المحرك
void RegisterFactory(ObjectFactory factoryFunction)
{
g_Factories.add(factoryFunction);
}
// هذا الإجراء تخيلي، هدفه إيضاح كيفية تسجيل مصنع جديد
void EngineInit()
{
// إضافة المصنع الأساسي للمحرك والذي يدعم جميع كلاسات المحرك الأصلية
RegisterFactory(EngineFactory);
}
enum GameTypes
{
Type_Car = 1000, // كن حذراً مع هذه الأرقام
Type_Train,
Type_Ship,
};
class Car : public Object
{
...
};
class Train : public Object
{
...
};
class Ship : public Object
{
...
};
Object* GameVehiclesFactory(int classType)
{
switch (classType)
{
case Type_Car: return new Car();
case Type_Train: return new Train();
case Type_Ship: return new Ship();
}
return NULL;
}
void GameInit(void)
{
EngineInit(); // تشغيل المحرك
RegisterFactory(GameVehiclesFactory); // تسجيل مصنع المركبات في اللعبة
...
}
في 29 يونيو 2008 10:00 ص، قال الشمري بهدوء وتؤدة:
( لدي سؤال خارج الموضوع بعد اذنك .. لو أمكنك الاجابة عليه بعد الانتهاء من موضوعنا الرئيسي.object someObject = new Bitmap("C:\\Me.bmp");
Type objType = someObject.GetType();
foreach (PropertyInfo property in objType.GetProperties())
{
Console.WriteLine(property.Name);
}