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

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

مغلق
بدأه hasan_aljudy في 23 ديسمبر 2005 · 6 رد · 2,653 مشاهدة · في OpenGL
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

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

#2

دائما ما تأتي بالجديد : ) .

لكن لماذا لا :

استخدم glutMainLoop التي تؤدي الخدمات الضرورية ..

واستخدم glutDisplayFunc .. لعرض الرسوم ..

واستخدم glutIdleFunc .. التي تؤدي الانيمشن ..

:) ,,

رأيي loop في glut سيء .. ودائما ما الجأ الى WIN API لان loop فيها واضح واكثر دقة ..

لكن انت لماذا تستخدم glutMainLoopEvent بدلا من الدوال المعتادة مثل .. glutIdleFunc ..

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

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

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#3

حسب ما اذكر, جربت استخدم glutIdleFunc بس ما نفعت .. جرب اذا تريد و قلي النتيجة.

#4

أعتقد أن الفائدة من إستخدام دوال freeglut بدلا من win 32 api هو إمكانية نقل الكود بدون تغيير إلى أنظمة أخرى.

#5
اقتباس
حسب ما اذكر, جربت استخدم glutIdleFunc بس ما نفعت .. جرب اذا تريد و قلي

النتيجة.

ماذا تقصد بـ " ما نفعت " .. على العموم شوف المرفقات .

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

اقتباس
أعتقد أن الفائدة من إستخدام دوال freeglut بدلا من win 32 api هو إمكانية نقل الكود بدون تغيير إلى أنظمة أخرى

صحيح ..لكن السبب الرئيسي ..اعتقد فقط لانها اسهل .

loop.zip

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

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

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#6

نزلت freeglut .. طبعا بالسورس كود ... وانصدمت ... قولوا ليه ؟؟ ... ليه ؟ ..... طلعت ي عبارة عن تغليف لـ win api ..

مثلا لو قلنا

glutCreateWindow....

النتيجة

if(WINDOWS)

CreateWindow(...)

if(MAC)

CreateWindowMac(..)

ايضا glut تستخدم التركيب PIXELFORMATDESCRIPTOR .. لاعداد opengl ..

نفس الامر مع menu ايضا ...

المسألة بسيطة ... كنت متوقع ان glut مكتبة من الصفر ,,,,, او على الاقل اعتمادها بسيط على دوال النظام .

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

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

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#7
الشمري كتب:
نزلت freeglut .. طبعا بالسورس كود ... وانصدمت ... قولوا ليه ؟؟ ... ليه ؟ ..... طلعت ي عبارة عن تغليف لـ win api ..

مثلا لو قلنا

glutCreateWindow....

النتيجة

if(WINDOWS)

CreateWindow(...)

if(MAC)

CreateWindowMac(..)

ايضا  glut تستخدم التركيب  PIXELFORMATDESCRIPTOR  .. لاعداد opengl ..

نفس الامر مع menu ايضا ...

المسألة بسيطة ... كنت متوقع ان glut مكتبة من الصفر ,,,,, او على الاقل اعتمادها بسيط على دوال النظام .

ههههه طبعا .. ماذا كنت تتصور!!

:D

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

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