كتبت موضوعا قبل فترة عن الـ game loop قدمت فيه فكرة مبسطة عن الموضوع, و كتبت ايضا موضوع عن استخدام glut مع opengl و هو في الحقيقة لم يحتوي شي جديد سوى تذكير فقط بما هو موجود في مواضيع اخرى في المنتدى. طيب, اذا مع glut حلينا مشكلة النوافذ .. و الان نريد ان نعمل برنامج صغير يحتوي على loop من اجل تحديث اللعبة باستمرار .. كيف نقوم بذلك؟ في glut هناك function اسمه glutMainLoop, عند استدعائه, سيدخل البرنامج في حلقة لا نهائية تقوم بتشغيل البرنامج و ادارة المهام المتعلقة بالنافذة و استقبال المدخلات .. الخ! المشكلة ان glut لا يوفر لك طريقة من اجل عمل gameloop ... لانك عندما تستدعي glutMainLoop فإنك تفقد السيطرة على البرنامج و يصبح تحت سيطرة glut و لا توجد طريقة لكي تقوم حضرتك بإدخال كود معين يتم تنفيذه كل فريم .. هذه المشكلة يمكن حلها عن طريق اقتحام السورس كود الخاص بـ glut و تعديل glutMainLoop و هذا سيقود الى عدة مشاكل تحتاج لحلول, و لكن لا داعي لكل هذا العناء, فهناك اناس قد واجهوا هذه المشاكل من قبل و قاموا بحلها!! و الحل هو استخدام freeglut http://freeglut.sourceforge.net حيث يوفر لك function إسمه glutMainLoopEvent حتى تقوم باستدعائه داخل الـ loop الخاصة بيك .. فتستغني بذلك عن glutMainLoop يعني, نحن نحتاج glutMainLoop من اجل القيام بخدمات ضرورية لا نستطيع تشغيل البرنامج من دونها (مثل متابعة النافذة و استقبال الرسائل .. الخ), يعني من اجل ان يقوم بالمهام اللتي من أجلها لجأنا الى glut من الأساس. في كل حلقة من حلقات glutMainLoop يتم تنفيذ كود معين ... فلو استطعنا استخلاص هذا الكود ووضعه في دالة منفصلة (و ليس حلقة) سيكون بإمكاننا استدعاء هذه الدالة داخل الحلقة الخاصة بنا! هذه هي وظيفة glutMainLoopEvent حيث انك من المفروض ان تستدعيه مرة واحدة داخل كل دورة من الـ gameloop الخاصة بك,
while( true ){ glutMainLoopEvent(); //your code ..}glutLeaveMainLoop();
#include <windows.h>#include <algorithm>#include <ctime>#include <GL/glut.h> #include <GL/freeglut_ext.h>int gx, gy;GLubyte * picture = 0;GLubyte * getPicture( int w, int h ){ int length = w * h * 4; GLubyte * bytes = new GLubyte[length]; for( int i = 0; i < length; i++ ) { bytes[i] = 0; } int m = std::min(w,h); //draw a line! int c = 100; for( int i = 0; i < m; i++ ) { int p = i*4; p = p+p*w; int pe = p + 4; while( p <= pe ) { bytes[p] = c; p++; c++; } c++; } return bytes;}void drawBox( int x, int y ){ glRasterPos2d( x, y ); glDrawPixels( 20, 20, GL_RGBA, GL_UNSIGNED_BYTE, picture );}void myInit(){ glClearColor(0.3,0.3,0.3,0.0); glColor3f(1.0,1.0,0.5); glPointSize(2.0); glMatrixMode(GL_PROJECTION); gluOrtho2D(0.0,60.0,0.0,60.0);}void myMainLoop(){ int counter = 0; while(true) { glutMainLoopEvent(); counter++; if( ! (counter % 50) ) { gx++; gy++; } Sleep(20); glClear(GL_COLOR_BUFFER_BIT); drawBox( gx, gy ); glFlush(); } glutLeaveMainLoop();}int main(int argc, char** argv){ gx = gy = 0; picture = getPicture( 20, 20 ); glutInit(&argc,argv); glutInitDisplayMode(GLUT_SINGLE |GLUT_RGB); glutInitWindowSize(400,400); glutInitWindowPosition(50,50); glutCreateWindow("Moving Box"); myInit(); myMainLoop(); return 0;}