بسم الله الرحمن الرحيم السلام عليكم و رحمة الله. في هذا الموضوع سنستخدم freeglut كما تحدثنا في الموضوع السابق, و الأفضل قراءة المواضيع السابقة قبل قراءة هذا الموضوع. الرسم على الشاشة و opengl حجر الأساس في برمجة الألعاب: الـ Game Loop freeglut ما اريد التحدث عنه اليوم هو تحريك الكائنات في اللعبة .. لنحلل المسألة قبل الشروع في العمل: و لنأخذ أبسط حالة: لدينا كائن واحد, نرسمه على شكل مربع, و نضعه في بداية اللعبة في مكان ما على الشاشة. (هنا أنوه انك لا بد ان تكون فاهما جيدا لمسألة ان الشاشة هي عبارة عن سطح ثنائي الأبعاد, مكون من مجموعة كبيرة من النقاط المتراصة, و لنرسم شيئا على الشاشة علينا ان نحدد موقعه.) السؤال هو, كيف نحرك هذا الكائن؟ حسنا, لنفرض اننا كبداية, رسمنا الكائن هذا في موقع x,y = 100,80 و نريد تحريكه الى اليمين, كيف؟ لا بد ان نعرف أولا الـ coordinate system المستخدم في نظام الرسم .. في الـ opengl عادة تكون نقطة الصفر هي النقطة السفلية اليسرى .. بناءا على ذلك, كلما ازدادت قيمة x سنتحرك باتجاه اليمين, و كلما نقصت قيمة x سنتحرك باتجاه اليسار. و بنفس المنطق, كلما زادت قيمة الـ y تحركنا الى الأعلى, و كلما نقصت قيمة الـ y تحركنا الى الأسفل. إذا, لو اردنا تحريك هذا الكائن خطوة واحدة الى اليمين, يجب ان نمسحه من موقعه القديم و نرسمه في الموقع الجديد و هو x,y = 101,80 قد يكون هذا المقدار ضئيلا جدا بحيث ان المستخدم قد لا يلاحظ فرق .. لذلك يمكن زيادة الازاحة حسب الرغبة. من أجل ان نقوم بذلك في البرنامج, يجب علينا ان "نتذكر" الموقع الحالي للكائن, بحيث كلما نحركه نمسحه من موقعه القديم, نغير قيم x,y حسب المطلوب, ثم نرسمه من جديد على الموقع x,y بعد ان تغير ليعكس الموقع الجديد المفترض للكائن. عملية المحو من الموقع القديم يمكن عملها في opengl عن طريق محو الشاشة بكاملها! باستخدام glClear مسألة اخذ input من الـ keyboard في glut معقدة شوية .. لازم نسجل callback function للـ event اللذي يحدث عن ضغط زر على الكيبورد .. لاحظوا الكود. مسألة رسم مربع, مسألة بسيطة نسبيا .. يمكن رسم مربع عن طريق البدء بـ glBegin و نمرر لها GL_POLYGON ثم نحدد نقاط المربع ثم نستدعي glEnd, النقطة الوحيدة اللتي يجب الانتباه لها هي ترتيب النقاط .. لازم نرسلها بترتيب معين و الا يتخربط الشكل. (لو مش واضحة هالنقطة ممكن نوضحها أكثر إن شاء الله حسب رغبتكم). الهدف هو توصيل الفكرة الأساسية, هذا المثال بسيط جدا, طبعا هناك تفاصيل اخرى قد ينبغى العناية بها في الالعاب الحقيقة .. و لكن الهدف هو توصيل الفكرة الأساسية لتكوين مفهوم جيد عن الموضوع في اللاوعي هذا تطبيق مع بعض التعليقات البسيطة.
#include <windows.h>#include <GL/glut.h> int x, y; //global variables for the location of the objectvoid drawBox( int x, int y ); //a function to draw a small box at a certain locationvoid handleInput( int key, int mx, int my ); //our keyboard event handlervoid init();int main(int argc, char** argv){ glutInit(&argc,argv); glutInitDisplayMode(GLUT_SINGLE |GLUT_RGB); glutInitWindowSize(400,400); glutInitWindowPosition(50,50); glutCreateWindow("Moving Box"); glutSpecialFunc( handleInput ); //register our keyboard handler for special keys (arrows are special keys) init(); //initialize glutMainLoop(); //enter the glut main loop .. return 0;}void drawBox( int x, int y ){ int x1 = x + 20; int y1 = y + 20; glBegin(GL_POLYGON); //note the order of sending the points, it's important glVertex2d( x, y ); glVertex2d( x, y1 ); glVertex2d( x1, y1 ); glVertex2d( x1, y ); glEnd();}void handleInput( int key, int mx, int my ){ //if key is an arrow key, adjust the global x,y accordingly switch( key ) { case GLUT_KEY_LEFT: { x -= 5; } break; case GLUT_KEY_RIGHT: { x += 5; } break; case GLUT_KEY_UP: { y += 5; } break; case GLUT_KEY_DOWN: { y -= 5; } break; default: return; //if it's not an arrow key, we can quit the function } //clear the screen and draw the box in it's new position glClear(GL_COLOR_BUFFER_BIT); drawBox( x, y ); glFlush();}//Typical initialization function .. not how ever that we initlize the object too.void init(){ glClearColor(0.3f,0.3f,0.3f,0.0f); glColor3f(1.0,1.0,0.5); glPointSize(2.0); glMatrixMode(GL_PROJECTION); gluOrtho2D(0.0,768.0,0.0,1024.0); //initialize and draw the object in its initial location x = y = 30; glClear(GL_COLOR_BUFFER_BIT); drawBox( x, y ); glFlush();}