بتـــــاريخ : 2/28/2011 1:41:37 AM
الفــــــــئة
  • الحـــــــــــاسب
  • التعليقات المشاهدات التقييمات
    0 2238 0


    تطبيق فكرة ال gameloop في برنامج يستخدم glut freeglut في الداخل!

    الناقل : elmasry | العمر :42 | الكاتب الأصلى : hasan_aljudy | المصدر : www.arabteam2000-forum.com

    كلمات مفتاحية  :

    كتبت موضوعا قبل فترة عن الـ 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();


    هناك ايضا glutLeaveMainLoop و هي موجودة لكي تستدعيها بعد الانتهاء من الـ loop تماما ..

    المكتبة فيها اشياء اخرى اضافية على ما اظن ... و لكن على كل حال, هذا هو تقريبا اكثر ما يهمنا!

    في المرفقات ملف مضغوط يحتوي على ما تحتاجه لاستخدام freeglut, مقسم الى ثلاث أقسام:
    include و هذه تضعها في مكان ما بحيث الكومبايلر يستطيع الوصول اليه!! يعتمد على الكومبايلر نفسه ..!
    lib و هذه ايضا تعتمد على الكومبايلر و لازم تكون موجودة في مكان يبحث فيه الكومبايلر عن ملفات .lib
    dll و يحتوي على ما يجب ان تضعه في WINDOWS/system32 على ما اظن ..

    اذا اردت تحميل الحكاية من الموقع الاصلي فستجد الـ source code و عليك ان تقوم بترجمتها بنفسك, انا حصلت على الملفات المرفقة عن طريق عمل compile مع release في VC++ 2005 express و الملفات تعمل عندي, و اظن انها من المفروض ان تعمل إن شاء الله عند الجميع, و لكن لست متأكدا, لذا وجب التنويه.

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

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

    #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;
    }


    لاحظوا اننا لا نحتاج الى display function الان!

    Enjoy
     
    ملف مرفق(ملفات)
     
    ملف مرفق  freeglut.rar (156.16كيلو )

    كلمات مفتاحية  :

    تعليقات الزوار ()