الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

للمبتدئين جدا: عمل لعبة صغيرة من الالف الى الياء

مغلقرائج
بدأه Abdullah.Alshammeri في 3 أغسطس 2006 · 15 رد · 44,603 مشاهدة · في OpenGL
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم .

تنبيهات مهمة ...

1 -

أنا وضعت روابط في هذا الموضوع لمواضيع سابقة .. انا من كتبها ,

وهذا لايعني أنه مواضيعي الافضل .. او اني اعمل دعاية لها ..

لكن لاني اعرف بالظبط محتوى تلك الدروس .. واعرف انها هي ما تحتاجه الان ..

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

2-

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

3- ماستراه من دروس لن تكون بالضرورة هي المطبقة في برمجة الالعاب القياسية . . لكن مجرد اجتهادات.

لماذا هذا الموضوع ؟

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

ماذا قال لي هذا الزميل ؟

قال : المشكلة أنني أريد تعلم برمجة الالعاب لكن لا اعلم ماهي الخطوات المطلوبة ...

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

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

اذا زميلي .. وانا سابقا .. واي مبتدئ .. نبحث عن خطوات بسيطة توصلنا للهدف .. وهو انتاج لعبة ..

من هذه النقطة .. قررت كتابة هذه الدروس المبسطة .

أولا ماهي اللعبة التي سنبرمجها ؟

حقيقة فكرت في أكثر من لعبة ..

لعبة X O .. لعبة بسيطة لكنها ليست شاملة .. فهي لاتقدم للمبتدئ شيء .

لعبة سوبر ماريو ... هذه لا اعرف كيف ابرمج مثلها .. بالتالي انا احتاج لدروس :) .

واخيرا استقريت على عمل لعبة كنت قد عملتها سابقا ..

هنا ..

/index.php?showtopic=80108

لماذا هذه اللعبة بالتحديد ؟

- لانها سهلة .. واعرف لها زين :).

- لانها شاملة ...

وتشمل تعلم عدة مهارات :

1- إنشاء الاشكال البسيطة .

2- التحريك .

3- الاصطدام .

4-نوع من الذكاء الاصطناعي .

مالذي تحتاجه لتفهم هذه الدروس ؟

سأفصل .. في كل خطوة ... حتى تكون على دراية ..

1 - أن تكون ملما بلغة السي ::::

تعرف لهذه المصطلحات .

المتغيرات.VARIABLES

المصفوفات.ARRAYS

الدوال .FUNCTIONS

التراكيب Structures

المؤشرات Pointers .

بالاضافة للجمل الشرطية والتكرارية : ) .

2 - أن تجيد استخدام المكتبة glut .

انتقل لهذا الدرس :

/index.php?showtopic=41970

او هذا

/index.php?showtopic=74564

أريد منك ان تتعلم :

ربط المكتبة glut بـ opengl ... وكيفية تثبيت المكتبة GLUT .

التعامل مع الكيبورد ورسائله.

التعامل مع الماوس .

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

3 - ان تجيد استخدام opengl .

يكفي منك أن تتعلم مايلي :

الدرس الاول : : اساسيات الرسم والالوان

راجع هذا الموضوع . . .

/index.php?showtopic=83784

/index.php?showtopic=84121

الدرس الثاني : الازاحة .

راجع هذا الموضوع ,

/index.php?showtopic=83823

الدرس الثالث الاكساء :

راجع هذا الدرس .

/index.php?showtopic=84349

الدرس الرابع الشفافية :

راجع هذا الدرس

/index.php?showtopic=86956

( طبعا أريدك ان تتعلم باستخدام opengl و glut وليس opengl و win api ) .

خلاص أنت الان جاهز .

خلاصة الموضوع :

تأكد من أنك قمت بتثبيت المكتبة GLUT .

تأكد من أنك تعلمت أساسيات OpenGL ..تحت glut .

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

الحمدلله معنوياتي مرتفعة ولا احتاج للشكر :) .

تم تعديل هذه المشاركة بواسطة الشمري في 3 أغسطس 2006 في 06:22

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#2

موضوع جيد ومجهود كبير لو كل المشرفين مثلك لكان لهذا المنتدى شأن أكبر

فإلى الأمام

تم تعديل هذه المشاركة بواسطة sayedf1 في 3 أغسطس 2006 في 14:23

163374357.gif

#4

حياكم الله ,, الطريق طويل وصعب وشاق وووو .. بس كله يهون عشان شبابنا الطموح . :D

ويا اياس .. انا قلت لك .. اترك dx :D .. وخلك علىopengl .. بس ما طعتني : ( .

يمديك تبدأ بopengl .. انا كنت مثلك تماما .. عندي قناعة انه opengl مكتبة وضيعة بسيطة .. لايمكن ان تقارنها بdx .. لكن كل ذلك طلع كلام فاضي .. GL عملاقة . وكل يوم تكبر في عيني الله يحفظها : ) .

===================================

اللعبة ,

سأعمل على الفيجوال سي 6 .. أي واحد يعمل على مترجم اخر .. يقدر يكمل معنا ,,

لكن اذا واجه مشاكل .. ماعليه الا يقول انا تورطت .. ونعطيه الاسعافات اللازمة .

واحد :

نريد تقسيم عملنا الى ملفين فقط ... حتى مانشتت اذهانكم ..

الملف الاول اسمه

game.cpp

الملف الثاني

game.h

اثنين :

نحن سنبرمج اللعبة على طريقة البرمجة الاجرائية وليست الكائنية .. بمعنى كل شغلنا عبارة عن دوال functions ومتغيرات . . . فلن نقوم باستخدام كلاسات ,,, اطلاقا .

كل ذلك حتى يكود الكود واضح 100% .

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

ثلاثة :

انا لن اشرح أوامر opengl او glut .. هذه سأفرض أنك فاهمها .. وانا حددت المطلوب منك في المشاركة رقم 1

أربعة :

كل ملف أقوم برفعه في المرفقات عليك بتنزيله .. وتفحصه وفهمه 100% .

المرحلة الاولى :

قم بتحميل المرفقات :

ستجد ملفين :

افتح المشروع عن طريق الملف game.dsw اذا كنت تعمل على الفيجوال .

أولا افتح الملف game.cpp

وانتقل مباشرة الى الدالة الرئيسية main ...

int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode ( GLUT_DOUBLE | GLUT_RGB);
   glutInitWindowSize (795, 500); 
   glutInitWindowPosition (0, 0);
   glutCreateWindow ("Pong - Arab Team 2000");

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

المشكلة التي ممكن أن تواجهنا هنا هو اننا لا نعرف ابعاد اي شاشة نتعامل معها ؟؟؟

فقد تكون 800 *600 او غير ذلك .. حينها ستتأثر اللعبة ..

او لنقل مظهر اللعبة ..

صحيح أن هذا التأثير غير مؤشر على اللعبة

لكن من الافضل الاهتمام بهذه الناحية .

ويوجد عدة طرق للتغلب على هذه المشكلة ..

منها أن نستخدم WIN API لمعرفة أبعاد الشاشة

او نعمل على full screen .. اي بملئ الشاشة لننهي هذه الاشكالية ..

على العموم الان لن نقوم بشيء حتى لانشتت اذهانكم , باشياء ثانوية .

ننتقل للكود اللي بعده وهو ايضا في main :

	Setting ();

هنا استدعاء للدالة Setting الموجودة في game.h

وانا قمت بانشائها حتى نضع فيها كل الاعدادات المطلوبة .

حيث قبل ان تبدأ اللعبة نقوم باعداداها .. مثلا لون الخلفية ... تحميل الصور .. الخ ..

بالتالي من الافضل وضع جميع الاعدادات في دالة واحدة ..

لو انتقلت الى الى Setting

// OpenGL Setting
void Setting(void) 
{
   glClearColor (0.0, 0.0, 0.0, 0.0);
   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

}

وهي واضحة ومن اساسيات Opengl .

نعود مرة اخرى للدالة الرئيسية main

   glutDisplayFunc(Render); 
   glutIdleFunc(Render);

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

لو انتقنا للدالة Render وهي تقع في الملف game.cpp

void Render()
{
	glClear(GL_COLOR_BUFFER_BIT );
	glLoadIdentity();




	glutSwapBuffers();
}

الان الدالة فارغة كما ترى ولم نرسم شيء ..

نعود مرة اخرى للدالة الرئيسية main

   glutReshapeFunc(reshape);

هنا اعادة التحجيم .. للنافذة .

وهو من اساسيات opengl و glut ايضا ,, ولكن لو اطلعنا على الدالة reshape

// OnWindowResize 
void reshape (int w, int h)
{
	WINDOW_WIDTH =w;
	WINDOW_HEIGHT =h;

   glViewport (0, 0, (GLsizei) w, (GLsizei) h);

   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();
   gluOrtho2D (0, w, h, 0);


   glMatrixMode (GL_MODELVIEW);
   glLoadIdentity ();

}

طبعا الدالة هذه ستحدث فقط اذا تم تغيير حجم النافذة ..

فنحن نحصل على الابعاد الجديدة للنافذة

ونقوم بعمل اللازم .

لاحظ اننا حصلنا على الابعاد وخزناها في متغيرين

	WINDOW_WIDTH =w;
	WINDOW_HEIGHT =h;

سنستفيد من الابعاد الجديدة عند اكتشاف التصادم بين الكرة وابعاد النافذة .

نعود مرة اخرى للدالة main :

   glutKeyboardFunc(keyboard);

   glutSpecialFunc(inputKey);
   glutSpecialUpFunc(upkey);

   glutPassiveMotionFunc(MouseMotion);

هذه الدوال التي ستحدد الدوال التي تستقبل رسائل الماوس والكيبورد ..

وهي طبعا من أساسيات glut .

اذا الخلاصة :

قمنا بانشاء النافذة

قمنا باعداد opengl .

قمنا بتحديد الدالة التي سنرسم فيها

قمنا بتحديد الدوال التي ستعالج احداث ورسائل الماوس والكيبورد

النتيجة الى الان مجرد نافذة فارغة

انتهت المرحلة الاولى ..

حمل المرفقات .

game_01.zip

تم تعديل هذه المشاركة بواسطة الشمري في 4 أغسطس 2006 في 06:21

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#5

أعتذار .

سأتوقف مدة اسبوع كامل .. وربما اسبوعين او شهر ..او ... !!!

حتى تدب الحياة في المنتدى .. نحتاج لمواضيع تسخين واحماء قبل هذا الموضوع .

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#6

السلام عليكم ..

اقتباس
سأتوقف مدة اسبوع كامل .. وربما اسبوعين او شهر ..او ... !!!

و الله معك حق اخي الشمري ..

بس مع هذا .. لا تيأس ..

لولا انشغالي بغير مواضيع والتي سأعتمد عليها في مشروعي في الكلية ، لكنت اول المتابعين لك ..

و الله راح احاول قدر استطاعتي ان اقتطع من وقتي لمتابعة جميع دروسك القيمة ..

بارك الله فيك

Go On

/index.php/topic/264448-%D8%A7%D9%84%D8%A8%D8%AF%D8%A7%D9%8A%D8%A9-%D9%85%D8%B9-%D8%A7%D9%84%D8%A7%D9%86%D8%AF%D8%B1%D9%88%D9%8A%D8%AF/

 

اني وان كنت الاخير زمانه ---- لأتِ بما لم تستطعه الاوائلُ

#7

المرحلة الثانية :

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

ثم سنقوم بعملية إعداد لمسألة اكتشاف التصادم وكيف تتم ؟

أولا : رسم الشكل الرباعي :

أنت تعرف أنه يمكن رسم أي شكل رباعي في OpenGL بعدة طرق منها هذه الطريقة :

	glBegin(GL_QUADS);
	glVertex2f(0,100);	//Left - Bottom
	glVertex2f(100,100);
	glVertex2f(100,0);
	glVertex2f(0,0);
	glEnd();

طبعا بغض النظر عن الارقام .

لكن أنت لن تقوم بانشاء شكل رباعي واحد .. انما أنت بحاجة لانشاء ثلاثة أشكال رباعية .

الاول :

يمثل الاعب الاول .

الثاني : يمثل اللاعب الثاني .

الثالث :

يمثل الكرة.

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

اذا من الافضل أن تنشئ دالة تضع فيها طريقة رسم هذا الشكل .

void DrawRectangle()
{
	glBegin(GL_QUADS);
	glVertex2f(rect.left,rect.bottom);	 
	glVertex2f(rect.right,rect.bottom);
	glVertex2f(rect.right,rect.top);
	glVertex2f(rect.left,rect.top);
	glEnd();
}

بالتالي اذا اردت رسم اي شكل ما عليك الا انك تستدعي هذه الدالة

DrawRectangle();//1

DrawRectangle();//2

.

.

.

لكن أيضا لازلنا في مشكلة ,

ابعاد الكرة ليست كأبعاد اللاعب .. بمعنى أنت في حاجة للتحكم بشكل أكبر في أبعاد هذا المستطيل .

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

void DrawRectangle(float left, float top,float right,float bottom)
{
glBegin(GL_QUADS);
	glVertex2f(left,bottom);	//Left - Bottom
	glVertex2f(right,bottom);
	glVertex2f(right,top);
	glVertex2f(left,top);
	glEnd();
}

اذا نحن الان نتحكم بشكل كامل في الشكل الذي نريده .

مثال

DrawRectangle(0,0,100,100);

DrawRectangle(0,10,50,100);

لكن ايضا الامر متعب .. :lol: ... انت الان بحاجة لاربع متغيرات للكرة .. left - right - top -bottom .

واربع ايضا للاعب الاول واربع متغيرات للاعب الثاني .

اذا سيصبح لدينا 12 متغير وهذا شيء مزعج .

الحل هو ان نضع تركيب Struct يحوي اربع متغيرات هكذا

struct RECT
{
	float left,top,right,bottom;
};

ثم نعدل بدالة رسم المستطيل

void DrawRectangle(RECT  rect)
{
	glBegin(GL_QUADS);
	glVertex2f(rect.left,rect.bottom);	//Left - Bottom
	glVertex2f(rect.right,rect.bottom);
	glVertex2f(rect.right,rect.top);
	glVertex2f(rect.left,rect.top);
	glEnd();
}

الان لو اردنا رسم كرة

RECT ball={100,100,120,120};
DrawRectangle(ball);

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

كل التغيرات التي حدثت الان .. اننا أنشأنا تركيب ودالة لرسم الشكل الرباعي ..

==================

ثانيا إكتشاف أبعاد الشكل المستطيل تمهيدا لاكتشاف التصادم .

اذا أردنا معرف اكتشاف التصادم في شكل رباعي يجب علينا معرفة أربعة أمور ..

الضلع الايسر left

الضلع الاعلى top

الضلع الايمن right

الضلع الاسفل bottom

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

أحيانا تكون معرفتها سهلة .. اذا كانت المكتبة التي تعمل عليها تقدم لك ذلك على طبق من ذهب .

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

OpenGL لاتوفر طريقة مباشرة لمعرفة ابعاد جسم ما ..

لكن نحن عرفنا تلك الابعاد .. لاننا نحن من حدد موقع كل نقطة من نقاط الشكل الرباعي .

اذا نحن الان نعرف left,top,right,bottom .. للشكل المرسوم .

اذا نريد نوجد طريقة لاكتشاف التصادم بين الكرة واطراف النافذة ..

نحن بحاجة لامرين .. معرفة ابعاد الكرة وهذا معلوم ..

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

نحن أنشأنا في المرحلة الاولى .. متغيرين

static int WINDOW_WIDTH ,WINDOW_HEIGHT;

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

.

void reshape (int w, int h)
{
	WINDOW_WIDTH =w;
	WINDOW_HEIGHT =h;

   glViewport (0, 0, (GLsizei) w, (GLsizei) h);

   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();
   gluOrtho2D (0, w, h, 0);


   glMatrixMode (GL_MODELVIEW);
   glLoadIdentity ();

}

اذا ننتقل لدالة الرسم

RECT ball={100,100,120,120};

RECT wall ;

 void Render()
{
	glClear(GL_COLOR_BUFFER_BIT );
	glLoadIdentity();

	wall.left=wall.top=0;
	wall.right=WINDOW_WIDTH;
	wall.bottom=WINDOW_HEIGHT;





	DrawRectangle(ball);

قمنا بانشاء الكرة .. وانشاء تركيب يمثل ابعاد النافذة واسمها wall

لاحظ ان الطرف الايسر والعلوي من النافذة دائما ثابت وهو صفر .

وان الطرف الايمن والسفلي للنافذة يتغير .. بالتالي نحن نحصل على ابعاد النافذة الجديدية من المتغيرين

WINDOW_WIDTH

WINDOW_HEIGHT

الان نريد ان نصنع دالة بسيطة لاكتشاف التصادم .

#define FROM_RIGHT	1
#define FROM_LEFT	2
#define FROM_TOP	3
#define FROM_BOTTOM	4



int Test_Ball_Wall(RECT  ball , RECT wall)
{
	if(ball.right >=wall.right)
	return FROM_RIGHT; 
	if(ball.left <=wall.left)
	return FROM_LEFT; 
	if(ball.top <=wall.top)
	return FROM_TOP; 
	if(ball.bottom >=wall.bottom)
	return FROM_BOTTOM; 

	else return 0 ;
}

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

وهكذا مع بقية الحالات

واذا لم يحدث تصادم .. اعد القيمة صفر .

سوف ترى تطبيق عملي لكيفية اكشاف التصادم واستخدام الدالة السابقة في المرحلة الثالثة من الكود ..

انتهت المرحلة الثانية ..

في هذه المرحلة تعلمنا مايلي :::

1- أنشأنا دالة وتركيب لرسم الاشكال الرباعية

struct RECT
{
	float left,top,right,bottom;
};


void DrawRectangle(RECT  rect)
{
	glBegin(GL_QUADS);
	glVertex2f(rect.left,rect.bottom);	//Left - Bottom
	glVertex2f(rect.right,rect.bottom);
	glVertex2f(rect.right,rect.top);
	glVertex2f(rect.left,rect.top);
	glEnd();
}
////////NEW//NEW//NEW//NEW
////////NEW//NEW//NEW//NEW

2- أنشأنا دالة لاكتشاف التصادم بين الكرة والنافذة

#define FROM_RIGHT	1
#define FROM_LEFT	2
#define FROM_TOP	3
#define FROM_BOTTOM	4



int Test_Ball_Wall(RECT  ball , RECT wall)
{
	if(ball.right >=wall.right)
	return FROM_RIGHT; 
	if(ball.left <=wall.left)
	return FROM_LEFT; 
	if(ball.top <=wall.top)
	return FROM_TOP; 
	if(ball.bottom >=wall.bottom)
	return FROM_BOTTOM; 

	else return 0 ;
}

حمل المرفقات ,

game_2.zip

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#8

السلام عليكم

مستمتع جدا بمتابعة الدرس

واصل مسيرك

حبيت اوضح نقطة هناك دالة من داول ويندوز تفحص التصادم مباشرة و تطلب متغيرين من نو Rect نسيت اسمها الان :)

ان شاء الله اتناقش معك في بعض امور اللعبة ريثما انهي بعض المشاكل بجهازي المتعثر حاليا

تحياتي

#9

السلام عليكم ،

للأن انا متابع تمام !!

ننتظر الدرس القادم ان شاء الله ..

جزاك الله خيرا

/index.php/topic/264448-%D8%A7%D9%84%D8%A8%D8%AF%D8%A7%D9%8A%D8%A9-%D9%85%D8%B9-%D8%A7%D9%84%D8%A7%D9%86%D8%AF%D8%B1%D9%88%D9%8A%D8%AF/

 

اني وان كنت الاخير زمانه ---- لأتِ بما لم تستطعه الاوائلُ

#10

شكرا الك

بس عندي سؤال

أغلب التوابع المستعلمة من المكتبة glut إما أني أعرفها أو أن عملها واضح

و لكني لم أفهم البعض منها

و لا أريد أن أسأل عن شرحها حتى لا نبتعد عن الموضوع الأساسي .. و لكن هل يوجد guide أو help أو أي شيء مشابه من الممكن الاستعانة به للبحث عن توابع glut .. و شكرا

MAAAAAAAAAAAAAAAAAAAAAAAC

#11

المرحلة الثالثة :

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

اذا نحن بحاجة لامرين مهمين جدا جدا ..

الاول : تريد ان نكتشف التصادم بين الكرة واطراف النافذة .

وهذا سهل وقد تعلمنا كيف يتم ذلك في المرحلة السابقة ,

الثاني : نريد ان نحرك الكرة .. ثم اذا حدث اصطدام نحرك الكرة للاتجاه المعاكس .

يوجد عدة طرق .. منها طرق علمية نوعا ما .. باستخدام المتجهات ,, وهذه دوختني :).

ومنها طريقة بسيطة باستخدام متغيرات فقط.

لاحظ الكود

static float Xspeed=2,Yspeed=2;
static float delta=2;


RECT ball={100,100,120,120};
RECT wall;

 void Render()
{
	glClear(GL_COLOR_BUFFER_BIT );
	glLoadIdentity();

	wall.left=wall.top=0;
	wall.right=WINDOW_WIDTH;
	wall.bottom=WINDOW_HEIGHT;


 	DrawRectangle(ball);

	ball.left+=Xspeed;
	ball.right+=Xspeed;
	ball.top+=Yspeed;
	ball.bottom+=Yspeed;

	  if(Test_Ball_Wall(ball,wall)== FROM_RIGHT)
	Xspeed=-delta;

	if(Test_Ball_Wall(ball,wall)== FROM_LEFT)
	Xspeed=delta;

	if(Test_Ball_Wall(ball,wall)== FROM_TOP)
	Yspeed=delta;

	if(Test_Ball_Wall(ball,wall)== FROM_BOTTOM)
	Yspeed=-delta;



	glutSwapBuffers();
}

سنشرح الجديد فقط .

اولا حركنا الكرة

	ball.left+=Xspeed;
	ball.right+=Xspeed;
	ball.top+=Yspeed;
	ball.bottom+=Yspeed;

لاحظ اننا لم استخدم دالة الازاحة glTranslatef لان التحريك باستخدام تلك الدالة يصعب من مهمة اكتشاف التصادم .

سوف نشرح بالتفصيل كيف يحدث التصادم بين الجزء السفلي من الكرة والجزء السفلي من النافذة ومالذي سيحدث في كل خطوة :

شاهد الصورة .

AAAA(1).JPG

اولا نحرك الكرة للاسفل ,,,

ball.top+=Yspeed;
ball.bottom+=Yspeed;

قيمة Yspeed تساوي 2 ...

بالتالي .. الاحداثي الصادي للكرة سيتزايد كل مرة بمقدار 2 ...

حتى يحدث تصادم ... اذا حدث تصادم ..

	if(Test_Ball_Wall(ball,wall)== FROM_BOTTOM)
	Yspeed=-delta;

جعلنا قيمة Yspeed تساوي سالب اثنين

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

	if(Test_Ball_Wall(ball,wall)== FROM_TOP)
	Yspeed=delta;

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

نفس الامر مع الاحداثي السيني للكرة .

أتمنى من صميم قلبي ان الفكرة صارت واضحة

حمل المرفقات ..

game_3.zip

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#12

السلام عليكم ،

تم التحميل ،، وسأقرء الدرس ان شاء الله في اقرب فرصة ،

تحياتي لك

/index.php/topic/264448-%D8%A7%D9%84%D8%A8%D8%AF%D8%A7%D9%8A%D8%A9-%D9%85%D8%B9-%D8%A7%D9%84%D8%A7%D9%86%D8%AF%D8%B1%D9%88%D9%8A%D8%AF/

 

اني وان كنت الاخير زمانه ---- لأتِ بما لم تستطعه الاوائلُ

#13

المرحلة الرابعة :

الان سننشئ اللاعب الاول ... وهو الذي سيحركه المستخدم ..

عندنا مهمتين رئيسيتين .

الاولى :

نحرك اللاعب ... تبعاً لحركة الماوس ...

الثانية:

نريد اكتشاف التصادم بين اللاعب والكرة ..

أولا: تحريك اللاعب :

RECT player_1 ={0,490,40,500};

أنشأنا تركيب يمثل اللاعب وابعاده .

DrawRectangle(player_1);

رسمنا اللاعب.

وكل ذلك سبق شرحه .

--

الان نريد ان نحصل على احداثيات الماوس .. لتكون هي احداثيات اللاعب

ننتقل الى الدالة التي أنشأناها في اول مرحلة

static mouse_x=0;

.
.
.
void MouseMotion(int x,int y)
{
	mouse_x=x;


}

الان حصلنا على موقع مؤشر الفارة

الان نحرك اللاعب تبعا لحركة الفأرة ..

في دالة الرسم

	DrawRectangle(player_1);
	player_1.left=mouse_x-20;
	player_1.right=mouse_x+40;

بالنسبة للارقام هي غير اجبارية .. لكن وجدت انها افضل قيمة ممكنة .

الان انت قادر على تحريك اللاعب

الان ننتقل للنقطة الاخرى المهمة ..

نريد اكتشاف التصادم بين اللاعب والكرة ..

أنشأنا لهذه المهمة دالة تقوم باللازم

bool Test_Ball_Player(RECT ball,RECT player)
{
	if(ball.bottom>= player.top && ball.right<= player.right && ball.right>=player.left )
		return true; 
	if(ball.bottom>= player.top && ball.left>= player.left && ball.left<=player.right )
		return true;

		return false; 
}

أتمنى تكون الدالة واضحة ..

اذا حدث تصادم أعد القيمة true والا false

الان لنكتشف التصادم

	if(Test_Ball_Player(ball,player_1)==true)
		Yspeed=-delta;

ليكون شكل الكود الجديد بعد التعديل .

#include"game.h"

static float Xspeed=2,Yspeed=2;
static float delta=2;


RECT ball={100,100,120,120};
RECT wall;
RECT player_1 ={0,490,40,500};


bool Test_Ball_Player(RECT ball,RECT player)
{
	if(ball.bottom>= player.top && ball.right<= player.right && ball.right>=player.left )
		return true; 
	if(ball.bottom>= player.top && ball.left>= player.left && ball.left<=player.right )
		return true;

		return false; 
}




 void Render()
{
	glClear(GL_COLOR_BUFFER_BIT );
	glLoadIdentity();

	wall.left=wall.top=0;
	wall.right=WINDOW_WIDTH;
	wall.bottom=WINDOW_HEIGHT;



	DrawRectangle(ball);

 	ball.left+=Xspeed;
	ball.right+=Xspeed;
	ball.top+=Yspeed;
	ball.bottom+=Yspeed;

	  if(Test_Ball_Wall(ball,wall)== FROM_RIGHT)
	Xspeed=-delta;

	if(Test_Ball_Wall(ball,wall)== FROM_LEFT)
	Xspeed=delta;

	if(Test_Ball_Wall(ball,wall)== FROM_TOP)
	Yspeed=delta;

	if(Test_Ball_Wall(ball,wall)== FROM_BOTTOM)
	Yspeed=-delta;

 	DrawRectangle(player_1);
	player_1.left=mouse_x-20;
	player_1.right=mouse_x+40;


	if(Test_Ball_Player(ball,player_1)==true)
		Yspeed=-delta;






	glutSwapBuffers();
}

حمل المرفقات واغلب التعديلات ستجدها في الملف game.cpp

game_4.zip

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#14

مر وقت طويل ,,,

.. عموما لم يبق الا ثلاث مراحل .

- انشاء اللاعب الكمبيوتر ,

- اكساء الاشكال بالصور .

- تحسين سرعة اللعبة وحساب النتيجة .

ما رأيكم ,, هل مثل هذه المواضيع مفيدة ,, هل اكمل ,, نعم أو لا .

تم تعديل هذه المشاركة بواسطة الشمري في 17 يوليو 2007 في 05:03

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#15

والله هذا الموضوع الي كنت استناه من زمان..

والله يوفقك يالشمري وكمل انا من اشد المتابعين للموضوع..

## Al-programmer Will Coming ##

#16

نكمل الموضوع /

المرحلة الخامسة :

اذا حملت اخر مرفق ستجد اللعبة شبه مكتمله ولكن ينقصها ثلاثة أمور :

- تحسين سرعة اللعبة وحساب النتيجة .

- انشاء اللاعب الكمبيوتري .

- اكساء الاشكال بالصور .

الان سنقوم بتحسين سرعة اللعبة :

كنا في السابق نحدث سرعة الكرة داخل الloop .. يعني سرعة الكرة ستعتمد على سرعة الloop أي ستعتمد على سرعة المعالج اللي عندك .

فاذا كان المعالج سريع .. فاللعبة سريعة .. والعكس صحيح .

الحل : نريد اللعبة ثابتة السرعة على جميع الاجهزة .. بالتالي سنستخدمTimer ( مؤقت) .. في كل مدة محددة نحدث سرعة اللعبة ..

مثلا في كل 5 جزء من الالف في الثانية احدث اللعبة ..

أستخدمنا دالة التوقيت الخاصة بالمكتبة GLUT :

 void Timer(int v)
 {
	 /* هنا نحرك الكرة في كل  5 من الالف في الثانية */

	ball.left+=Xspeed;
	ball.right+=Xspeed;
	ball.top+=Yspeed;
	ball.bottom+=Yspeed;

	glutTimerFunc(5,Timer,1); // غير الرقم خمسة الى اي رقم لتسريع وابطاء اللعبة
 }

واستدعينا هذه الدالة في الmain .

------------------------------------

التطوير الاخر الذي سنقوم به ان شاء الله , هو حساب النتيجة .. :

الفكرة بسيطة أيضا :

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

أما اذا اصطدمت اللعبة بأعلى النافذة فإن النقطة لصالح اللاعب .

ونضع عداد ,, متغيرين :

int pcResult =0;/* نتيجة الكمبيوتر نخزنها هنا  */
int playerResult=0;/*نتيجة اللاعب نخزنها هنا  */;

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

// رسم نص على الشاشة
void drawText(char*string,int x,int y)
{
  char *c;
  glPushMatrix();
  glTranslatef(x, y,0);
  glScalef(.1,-.1,1);

  for (c=string; *c != ''; c++) {
		glutStrokeCharacter(GLUT_STROKE_ROMAN , *c);
  }
  glPopMatrix();

}

التصادم :

	if(Test_Ball_Wall(ball,wall)== FROM_TOP)//التصادم فوق الكرة
	{
	Yspeed=delta;//اعكس اتجاه الحركة على المحور الصادي
	playerResult++;
	}

	if(Test_Ball_Wall(ball,wall)== FROM_BOTTOM)// التصادم أسفل الكرة
	{
	Yspeed=-delta;
	pcResult++;
	}

ثم طبعنا النتيجة :

	sprintf(string,"PC : %d ",pcResult); // تحويل رقم الى نص
	drawText(string,10,80); // طباعة النص
	sprintf(string,"Player : %d ",playerResult);
	drawText(string,10,120);

بعد أن تطبع النتيجة ستفاجأ بأن العداد النتيجة لن يزداد بمقدار 1 كما في الكود ... إنما سيزداد بشكل عشوائي ...

ستعرف السبب والحل في المرة المقبلة ان شاء الله :

أهم الاضافات باختصار :

- تحسين سرعة اللعبة : انظر للدالة Timer في الملف game.cpp .

- انشاء دالة لطباعة النص : انظر الدالة drawText في الملف game.h .

- حساب وطباعة النتيجة .. انظر الدالة Render في الملف game.cpp .

طبعا كل التغييرات ستجد حولها كلمة NEW NEW NEW .

أيضا في هذا التحديث استخدمت المترجم Visual Cpp 2005 .

game_5.zip

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

هذا الموضوع مغلق.

مواضيع مشابهة