8.8 مكتبة Allegro كتاب لينكس الشامل >>

8.8 مكتبة Allegro لبرمجة الألعاب

8.8.1 مقدمة

لاحظت أن الكثيرين يبحثون عن بيئة لتطور الألعاب سهلة الإستعمال وقوية وطبعا نعرف كلنا أن أقوى لغة تبرمج عليها الألعاب هي C ( أقصد الألعاب التجارية الحقيقية وليس الفلاشات) ولكنها صعبة خصوصا إذا كنت تتحدث عن DirectX و MS-VisualC وغير موثوقة وغير قابلة للدوام لأن Backword Compitability ليست من سياسة مايكروسوفت؛ لهذا أنت بحاجة لمثل هذه المكتبة التي توفر لك كل ما تريد بطريقة سهلة من التعامل مع الشاشة في طور النافذة أو بكامل حجم الشاشة وتعطيك طريقة لإخراج المؤثرات الموسيقية والأصوات (وأكثر من صوت دفعة واحدة) على Linux و MacX و windows دون أن تغيّر في الكود شيئا وتستعمل أفضل طريقة في كل واحد ويمكنها التكامل مع OpenGL في ما يسمى AllegroGL ويمكنها عمل رسومات ثلاثية الأبعاد بدون OpenGL انظر www.talula.demon.co.uk/allegro/docs.html. الموقع الرئيس لهذه المكتبة هو http://alleg.sf.net وتتوفر لها أمثلة وألعاب وإضافات على موقع www.allegro.cc.

لتعرف قدرات هذه المكتبة انظر هذه لعبة بسيطة وكودها سهل الفهم allegro-demo وليعمل البرنامج المكتوب على allegro فأنت بحاجة إلى ملف alleg40.dll في ويندوز أو allegro.so.4.0 في لينكس وهذا الملف حجمه حوالي 200 كيلوبايت أو يمكنك دمجه في برنامجك ستاتيكياً مما يزيد من حجم برامجك 200 كيلوبايت. أما لتصمم برنامج على allegro فأنت بحاجة إلى المكتبات والأدوات والوثائق ملفات لينكس هي ثلاثة حزم واحدة هي allegro تحتوي على ملف .so وأخرى تسمى allegro-devel التي تحتوي ملفات header وأنظمة المساعدة الثلاث (man و info و html ) وملفات .a والأخيرة allegro-tools وهي تحتوي على أدوات للتصميم وغيرها، ولمستخدمي dev-cpp على ويندوز يوجد ملف alleg-install.exe وملفات المساعدة alleg.chm ويمكن أيضاً أن تستعمل google لتجد هذه الملفات ل MSVC بالبحث عن allegro zip ويمكنك أيضاً تنزيل الملف المصدري وتصنيفه بنفسك

tipتلميح

أسهل طريقة لعمل برامج allegro لويندوز هي استخدام برامج dev-cpp فهو يستخدم جزء مصغر من أدوات جنو ومنها minigw أي mini-gcc-for-windowz وأسهل طريقة في ليكنس هي استعمال نظام الحزم الخاص بتوزيعتك حيث ستجد حزم rpm لريدهات وماندريك وغيرها في الموقع الرئيسي ل allegro

سنشرح هنا تركيب أي برنامج مكتوب على allegro لا تفزع من كثرة الأسطر لأنها ستتكرر في كل برنامج بمعنى أنك فقط ستعمل "نسخ ولصق" يبدأ البرنامج ب #include "allegro.h" ثم يأتي ال main على الشكل الآتي int main(int argc,char *argv[]) ثم الحاصرتين {} وبينهما البرنامج ثم في نهاية نضيف بعض من سحر allegro هكذا END_OF_MAIN(); هنا يكمن جمال هذه المكتبة بحيث أن هذا الذي أضفناه في الأخير يحول main إلى بعض الخزعبلات المتعلقة بالمنصة التي تعمل عليها في windowz مثلا winmain في بعض المصنفات compilers وفي بعضها الآخر main بحيث يضمن أن برنامجك سيعمل فيهم جميعن دون تعديل. ولربط برامجك مع مكتبة allegro أضف -l alleg إلى خيارات الربط

tipتلميح

في لينكس يمكن استعمال الأداة allegro-config مع الخيار allegro-config --libs للتصنيف الديناميكي و allegro-config --static للتصيف الستاتيكي ل allegro (ولها فقط أي سيبقى يعتمد على libc وغيرها) مثلاً لتصيف ملف باسم mygame
gcc mygame.c -o mygame `allegro-config --libs`

داخل الحاصرتين اكتب الآتي قبل كل شيء allegro_init(); ثم نختار عدد الألوان الذي نريد set_color_depth(8); لعمق لوني 8 بت يعني 256 لون أو set_color_depth(16); لعمق لوني 16 بت يعني 64 ألف لون أو ثم نحجز شاشة رسومية بالأمر set_gfx_mode(GFX_AUTODETECT_FULLSCREEN , 320, 200, 0, 0); أو set_gfx_mode(GFX_SAFE , 320, 200, 0, 0); الأولى تحجز شاشة على fullscreen والثاني fullscreen فإن لم تنجح تفتح في نافذة يعني دائما تعمل طبعا ليس كل الكروت تدعم كل الكثافة النقطية resulutions لذلك يجب أن نفحص "هل ذلك جائز" أي يصبح الكود كما يلي

allegro_init();
set_color_depth(8);
// 1st try full secreen with acceleration
if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN , 320, 200, 0, 0) != 0) {
	// if fail try safe (may be windowed mode)
	if (set_gfx_mode(GFX_SAFE , 320, 200, 0, 0) != 0) {
		// if fail return to text mode and exit
		set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
		// the format of allegro_message is like printf
		allegro_message("Unable to set any graphic mode\n%s\n", allegro_error);
		exit(1);
	}
}

طبعا تستطيع استبدال 320x200ب 640x480 أو أي شي آخر ، نستطيع أن نرسم الأشياء الآن مثلا putpixel(screen,x,y,makecol(255,0,0)); ترسم نقطة حمراء على الشاشة screen في الموقع x,y makecol تعطيها R G B فتعطيك اللون بغض النظر هل الشاشة 256 لون أم 16 بت ، هذه بعض الأمثلة الأخرى
line (screen,x1,y1,x2,y2,makecol(0,0,255)); خط أزرق
rect(screen,x1,y1,x2,y2,makecol(255,255,255)); مستطيل أبيض
triangle(screen,x1,y1,x2,y2,x3,y3,makecol(0,255,0); ترسم مثلث أخضر
وهناك مضلع ودوائر .... واذا اردت أن ترسم في Bitmap بدل الشاشة استبدل screen باسم الBitmap أقصد بال Bitmap هو مكان في الذاكرة يمكنك أن تخزن فيه صور

tipتلميح

screen هي Bitmap معرف داخل allegro كل ما يرسم فيها يظهر على الشاشة فورا

create_bitmap(320, 200); حجز مكان بالذاكرة من نوع BITMAP * ويتسع لصورة 320x200
clear_bitmap(screen); لمسح الشاشة
clear_to_color(screen,makecol(255,255,0)); لطلاء الشاشة بالأصفر
وفي نظام 256 لون نعمل جدول الألون palette نسميه pal1 عن طريق

PALETTE pal1
تستطيع تحميل ملفات tga bmp lbm pcx عن طريق load_bitmap
BITMAP *myBMP = load_bitmap( "delme.bmp", pal1);
ثم يتم تفعيل جدول الألوان pal1 عن طريق
set_palette( pal1 );

هذا الكلام فقط في طور ال 256 لون

warningتحذير

اذا وجدت بعض الأمثلة لاتعمل وتعترض على نوع مؤشر العنوان pointer ربما لأن معايير ANSI تمنع التحويل من void * إلى أي شيء آخر بشكل ضمني ويجب ذكره صراحة يعني بدلا من BITMAP *pic1=data[PIC1_ID].dat الصواب أن تكتب BITMAP *pic1=(BITMAP *) data[PIC1_ID].dat

كل الذي مضى لم يكن مهما جدا لأنه من النادر أن نستعمله أما الآن فهذه الأوامر هي التي يجب تذكرها وهو blit ومشتقاته المختلفة وهي blit masked_blit streach_blit وأخيرا masked_streach_blit وهذا مثال: لنفرض أنك تريد أن ترسم صورة محملة من ملف bmp ومخزنة في متغير اسمه myBMP على الشاشة في الموقع x,y blit(myBMP, screen, 0, 0, x,y, myBMP->w, myBMP->h); اما masked_blit فتعني أن تجعل الخلفية شفافة اللون الشفاف هو أول لون في pal أي 0 هذا في طور ال 256 لون وهو أيضا الزهري السحري 255,0,255 في طور الألوان الحقيقية وهي مفيدة جدا لرسم الشخصيات في اللعبة أما streach_blit تعني مع تغير حجم الشكل و masked_streach_blit هي تغير الحجم مع شفافية.

وللتعامل مع لوحة المفاتيح ضع install_keyboard في بداية البرنامج بعد allegro_init وعند الرغبة في معرفة إذا كا زر معين مضغوط كل ما عليك هو قراءة ما يمثل هذا الزر في مصفورفة الأزرار key فإذا وجدتها بقيمة غير الصفر فهذا يعني أنه مضغوط مثلا key[KEY_ESC] تشير إلى حالة المفتاح Esc وبالمثل key[KEY_LEFT] و key[KEY_RIGHT] و key[KEY_UP] و key[KEY_DOWN]

8.8.2 التطبيق الأول

وإليك أول تطبيق برامج عارض الصور خزن هذا الملف باسم alared.c ثم اكتب

gcc -O2 -s alared.c -o alared `allegro-config --libs`
أو في dev-cpp
gcc alared.c -o alared -l alleg
ولعرض الصورة كل ما عليك هو تفيذ alared متبوعا باسم الصورة ثم اضغط Esc للخروج

warningتحذير

إذا حصلت على Bad command or filename في ويندوز اضف دليل dec-cpp إلى سطر ال path في ملف autoexec.bat بحيث يصبح كما يلي path=C:\windows;...;C:\dev-cpp\bin;

/*
 *
 * alared.c
 * tga bmp pcx Image Viewer by Moayyad Al-Sadi <alsadi[at]gmail.com>
 * This program is GPLed visit www.gnu.org and read GPL
 *
 */
#include<stdio.h>
// include the Allegro lib
#include<allegro.h>
BITMAP *myPic;
PALETTE pal1;
int main( int argc,char *argv[]) {
 if (argc==1) {
 	allegro_message("\tSyntax:\n%s filename\n",argv[0]);
	return 1;
 }
 myPic= load_bitmap( argv[1], pal1);
 if (!myPic) {
 	allegro_message("Error loading %s",argv[1]);
	return 2;
 }
 allegro_init();
 install_keyboard();
 set_color_depth(16);
 if (set_gfx_mode(GFX_SAFE , myPic->w, myPic->h, 0, 0) != 0) {
	set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
	allegro_message("Unable to set any graphic mode\n%s\n", allegro_error);
	retrun 3;
 }
 if (bitmap_depth(myPic)==8) { set_palette( pal1 );}
 blit(myPic, screen, 0, 0, 0,0, myPic->w, myPic->h);
 while(!key[KEY_ESC]); // wait ESC	
 return 0; // return success	
}

8.8.3 برنامج graber

ولأن تحميل الملفات بشكل مفرد غير عملي هناك ما يسمى Allegro data file وهو ملف له الإمتداد dat يمكن أن يحتوي على الكثير من ملفات الصور والأصوات وأي شيء آخر مجمعة في ملف واحد أو أكثر ومضغوط ومشفر بكلمة سر إن رغبت . يمكن عمل هذا الملف باستعمال الأداة graber وهي أداة رسومية سهلة الإستعمال ويمكنك تسمية كل ملف داخله باختصار macro ليكون متغير لتستعمله في البرامج ويعمل لك ال graber ملف بامتداد h يمكن استخدامه داخل كود السي ليعرف هذه المتغيرات وهذا توضيح ذلك

	...
#include "mydata1.h" // generated by graber	
	...
DATAFILE *data1;
BITMAP *pic[2];
SAMPLE *midi1;
MIDI *wav1;
int loading() {
    data1 = load_datafile("mydata1.dat"); // load mydata1.dat
    if (!data) return 1; // return Error
    // MY_PIC_1 is the name you gave when you make the .dat file ,it's from mydata1.h
    pic[0]=(BITMAP *)data[MY_PIC_1].dat;
    pic[1]=(BITMAP *)data[MY_PIC_2].dat;
    midi1=(MIDI *)data[MY_MID_1].dat;
    wav1=(SAMPLE *)data[MY_WAV_1].dat;
    return 0;// return Success
}
	...

لعمل ملف dat شغل برنامج graber واختر من القوائم object -> new -> bitmap ثم أعطها اسماً مثلا MYPIC1 ،ثم اختر grab أو CTRL+G لتحميل ملف الصورة إذا كانت الصورة ذات 256 لون ستظهر مشوشة لأنك لم تأخذ جدول ألوانها بعد لحل المشكلة أضف جدول ألوان new -> palette أعطها اسماً مثلاً MYPAL1 ثم CTRL+G لتحميل الجدول من ملف الصورة انتقل بالأسهم إليها ستجد مكتوب عل اليمين أنك لا تستعمل هذا الجدول اضغط مفتاح الإدخال لتفعيل هذا الجدول فتصبح الصورة واضحة.

grabber

وقبل أن تحمل صورة أخرى حول الصورة الحالية إلى طور الألوان الحقيقية "لا يحتاج جدول ألوان" لأن كل صورة لها جدول ألوان خاص والآن حمل صورة جديدة وأعطها اسما MYPIC2 واذهب إلى MYPAL1 وحمل منه جدول ألوانها وفعله وحول الصورة إلى الألوان الحقيقية وهكذا حتى تنهي الصور كلها عندها فعل جدول الألوان الذي يحتوي على أكبر تنوع في الألوان وعلم كل الصور وحولها إلى 256 لون بهذا تكون كل الصور لها نفس جدول الألوان مما يمكنك من عرضها جميعا دفعة واحدة في طور 256 لون دون تشوه.

tipتلميح

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

tipتلميح

الملفات المرسومة على برنامج غبي مثل PaintBrush لها نفس جدول الألوان ولكن مع تشويه الألوان

tipتلميح

قبل أن تحول الصورة من عمق لوني إلى آخر حول الصورة من Bitmap إلى RLE Sprite حتى لا تفقد الأماكن الشفافة ثم قم بعملية التحويل اللوني ثم أعد الصورة إلى نوع Bitmap

ولأن هناك أشياء تتكرر في معظم الألعاب حجز الشاشة والتحكم في الوقت ولوحة المفاتيح وتحميل الملفات عملت قالب يمكنك تنزيله من هنا يحتوي على ملفين الأول g_main به اجراءات الإستهلالية مثل حجز الشاشة والثاني g_game وهو الذي يحتوي منطق اللعبة كاملة الأول لن تعدل عليه كثيرا والثاني ستعيد كتابته تقريبا

8.8.4 الزمن

توفر allegro طريقة لإستدعاء وظيفة بشكل متكرر يفصل فترات زمنية معينة تقاس بالميللي-ثانية msec باستعمال الإختصار MSEC_TO_TIMER(msec) أو بتحديد كم مرة في الثانية باستعمال الإختصار BPS_TO_TIMER(bps) والأخيرة هي الطريقة المفضلة عندي ويتم تشغيل هذه الوظيفة باستعمال install_int_ex فإذا أردنا تنفيذ mytimer 30 مرة في الثنية الواحدة install_int_ex(my_timer, BPS_TO_TIMER(30)); حيث mytimer هي وظيفة عامة لا تأخذ معاملات ولا تعيد نتيجة. ويفضل أن لا تحتوي هذه الوظيفة أي أعمال طويلة أو تستخدم أي متغير عام إلا إذا حجزته ويجب وضع END_OF_FUNCTION(my_timer); بعد إغلاق الحاصرة الخاصة بالوظيفة {} لتقوم allegro ببعض السحر كما في END_OF_MAIN(); ويجب أن يتم إقفال هذه الوظيفة والمتغيرات العامة التي تستعملها لمنع التعليق في بعض الأنظمة وذلك باستعمال

    LOCK_VARIABLE(global_variable); // allegro magic to prevent system halt
    LOCK_FUNCTION(my_timer); // allegro magic to prevent system halt
في مكان ما قبل استدعاء install_int_ex

للحصول على أفضل النتائج أجعل وظيفة my_timer تقوم فقط بزيادة قيمة متغير عام بمقدار واحد، هذا المتغير العام أحب أن اسميه عداد time_counter أو speed_counter أو skip_counter وفي الحلقة الرئيسية في البرنامج تقوم بالإنتظار حتى انتهاء اللعبة وذلك بفحص قيمة متغير عام لهذا الغرض في هذه الأثناء داخل هذه الحلقة ابق ساكناً طالما هذا العداد لم يتغير عن الصفر فإذا تغيّر فهذا يعني أن الوقت حان للقيام بحركة قم بجميع الحسابات المتعلقة بالحركة القادمة ثم أنقص هذا العداد بمقدار واحد فإذا كان لا يزال أكبر من صفر فهذا يعني أن الجهاز بطيء فقد حان وقت حركة جديدة قم بالحسابات اللازمة مرة أخرى واطرح منه واحد وهكذا حتى تعود قيمة العداد للصفر ثم قم بعض كل هذه التغيرات دفعة واحدة على الشاشة كما يلي

// ...
      // this 3 lines to have same speed game in slow and fast PCs
      volatile int speed_counter = 0; // how many frame(s) to move on(skip)
      void my_timer()  { speed_counter++;}
      END_OF_FUNCTION(my_timer); // some allegro magic
// ...
void main() {
// ...
    allegro_init();
    install_keyboard(); // you can see if a ESC is pressed by key[KEY_ESC] 
// ...
    //Install timer ...
    // speed_counter is var dente how may frame to skip in the computer is slow
    // my_timer is a func that increase that var by 1 each frame
    LOCK_VARIABLE(speed_counter); // allegro magic to prevent system halt
    LOCK_FUNCTION(my_timer); // allegro magic to prevent system halt
    //use MSEC_TO_TIMER(msec) or BPS_TO_TIMER(bps)
    // msec=x mean to call the func each x milly sec
    // bps =x mean to call the func x times in a sec
    install_int_ex(my_timer, BPS_TO_TIMER(30)); // call my_timer() 30 times per sec
// ...
   while (!GameOver)
    {
        while (speed_counter==0); // wait until next frame time come
        NoSkipUpdate();
                // what needs to be done seq ie to show counter 5 to 1
                // and if the computer is slow it may skip to show 3
                // so if you want to view them all put them in NoSkipUpDate();
                // normally you do not need such thing
        while (speed_counter > 0) {Update(); --speed_counter;}
        speed_counter=0;
        update_display();
    }
}
حيث update_display و Update و NoSkipUpdate هي وظائف أنت تكتبها حسب حاجتك

8.8.5 الأصوات

حتى تتمكن من إصدار الأصوات يجب أن تستدعي install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL) في الجزء الإستهلالي لبرامجك وحتى قبل حجز الشاشة فاذا أعاد قيمة غير الصفر هذه يعني لايوجد بطاقة صوت يمكن أن تعتذر يتهي البرنامج أو تجعل متغير معين ليدل على أنه لا يوجد صوت فلا تصدر أصوات. ولعزف موسيقى من نوع midi نستخدم play_midi(midi1,true); حيث midi1 هي مؤشر انظر المثال أعلاه الخاص بتحميل ملف dat و true تعني دون توقف ولإيقاف هذه الموسيقى stop_midi(); لعمل مؤثر صوتي أو كلام wav نستدعي play_sample(wav1, 255,127 , wav1->freq, false); حيث wav1 قدمت من مثال dat أعلاه و false تعني لمرة واحدة كما يلي

	int SOUND_OK=1;
	if (install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL))
		SOUND_OK=0;
	.
	.
	if (SOUND_OK) set_volume(digi_volume, midi_volume);
	if (SOUND_OK) play_midi(midi1,true);
	if (SOUND_OK)
		play_sample(wav1, 255,127 , wav1->freq, false);

8.8.6 عمليات على الألوان

تحدثنا سابقا عن makecol نعطيه لون حقيقي فيعطيا رقم اللون في طور 256 لون ولتسريع عملية البحث عن لون مناسب في جدول الألوان وعمليات المزج والإضاءة وغيرها الكثير من العمليات التي ستصبح أسرع بوجود جدول البحث هذا نستدعي التالي في الجزء الإستهلالي للبرنامج ولمرة احدة فقط وبعد تحميل جدول الألوان pal1

	RGB_TABLE rgb_table;
	create_rgb_table(&rgb_table,pal1,NULL);
	rgb_map=&rgb_table;

وتمكنا مكتبة allegro من رسم رسومات شبه شفافة أو عمل اضاءة أو مزج ألوان حتى في طور 256 لون باستعمال جدول معرف مسبقا اسمه color_map ونحدد التأثير الذي نريده نستعمل واحدة من التالية
create_light_table(color_map,pal1,r,g,b,NULL); عمل جدول يقوم بتأثير الإضاءة بلون r,g,b كل منها أقل من 63
create_trans_table(color_map,pal1,r,g,b,NULL); عمل جدول يقوم بتأثير الشفافية لكل لون r,g,b كل منها 0-255 فاذا كانت 128 تعني نصف شفافة
create_color_table(color_map,pal1,myblend,NULL); حيث myblend هو وظيفة تأخذ المعاملات (pal1,c1,c2,RGB *) وهي لعمل تأثير خاص
create_blender_table(color_map,pal1,NULL); وهو ما يكافئ ال blenderfunc في طور 256 لون
وأما في طور الألوان الحقيقية نستعمل blenderfunc ولتطبيق المؤثر نستخدم draw_trans_sprite(screen,mypic,x,y); رسم مع مؤثر الشفافية و draw_lit_sprite(screen,mypic,x,y,light); لرسم الشكل مع مؤثر الإضاءة حيث light هو رقم 0-255 يمثل مقدار الإضاءة بدل blit ولتطبيق أكثر من مؤثر مثلا رسم mypic نصف شفافة في مكان وربع شفافة في مكان آخر

	COLOR_MAP color_map1,color_map2;
	create_trans_table(color_map1,pal1,128,128,128,NULL);
	create_trans_table(color_map1,pal1,64,64,64,NULL);
	.
	.
	color_map=&color_map1;
	draw_trans_sprite(screen,mypic,x1,y1);
	color_map=&color_map2;
	draw_trans_sprite(screen,mypic,x2,y2);
	.
	.

8.8.7 فضاء بثلاث أبعاد

تحتوي مكتبة allegro على أكثر من طريقة لرسم الصور ثلاثية الأبعاد الأولى وهي استعمال مكتبة AllegroGL الإضافية بحيث تستعمل Allegro لكل شيء فتح النافذة والفأرة والتوقيت وكل شيء آخر ومكتبة OpenGL للرسم ثلاثي الأبعاد وهذه الطريقة لست مهتما بها لأن OpenGL تقية عالية الجودة جدا ولاتناسب الطبيعة التفاعلية للألعاب والطريقة الثانية و الثالثة هي استخدام Allegro فقط دون أي اضافات وهنا ستكون مكتبتنا أكثر تواضعا من OpenGL إلا أنها تعطينا السرعة اللازمة للألعاب فحن لانريد وضع ضباب وظلال معقدة كل مانريده هو عمل رسومات ثلاثية الأبعاد تحتوي على إضاءة بسيطة ونسيج texture واحد و الظلال و الضباب ليس بالضرورة أن تكون حقيقية اذ يمكن أن تكون باستخدام تقنيات ثائية الأبعاد وخدع من هذا القبيل. الطريقة الثانية وهي Allegro بوظائف zbuffer وهي طريقة لإخفاء الأجسام التي تقع خلف أجسام أخرى حتى لو حصل بينهما تداخل ولن أناقش هذه الطريقة لأنها وعلى سرعتها أقل سرعة من الثالثة وهي اسستخدام وظائف scene التي تعتمد على تقية scan line وهي أسرع الطرق التي أعرفها وهي الطريقة التي أتحدث عنها

في الجزء الإستهلالي التحضيري لبرامج استدع ولمرة واحدة create_scene(max_edges,max_poly); حيث max_edges هي الحد الأعلى للنقاط التي تنوي رسمها max_poly هي الحد الأعلى للمضلعات التي تنوي رسمها وهذا يحجز الذاكرة الخاصة بتلك الحسابات لهذا نحجزها مرة احدة

والآن في الحلقة الأساسة لرسم المشهد كالعادة ترسم الخلفية ب blit ثم تستدعي clear_scene(buff); حيث buff هي ال bitmap التي تمثل الشاشة المخفية التي نرسم عليها، ثم لكل مضلع نريد رسمه نقوم بما يلي: نقله إلى عالم الكاميرا ذلك بتطبيق مصفوفة الكاميرا ويمكن توليد هذه المصفوفة ب get_camera_matrix(m,cX,cY,cZ,fX,fY,fZ,upX,upY,upZ,fov,aspect) حيث m مؤشر من نوع MATRIX والباقي أرقام، cX,cY,cZ موقع الكاميرا، fX,fY,fZ اتجاه النظر، upX,upY,upZ الإتجاه العامودي لأعلى عادة 0,0,1 fov زاوية الرؤية عادة 32-48 (255 تعني 360 درجة) ، aspect هي معامل تصحيح نسبة الطول إلى العرض ضعها احد، وتولد هذه المصفوفة مرة واحدة ثم يتم التعديل عليها فقط (انظر جدول العمليات على المصفوفة) ولنقل نقطة إلى عالم الكاميرا apply_matrix(m,x,y,z,&xx,∓yy,&zz); حيث xx و yy و zz هي الإحداثيات بعد تطبيق المصفوفة. ثم قص الأطراف الخارجة ب clip3d(type,minz,maxz,vc,vtx[ ],vout[ ],vtmp[ ],out) حيث type هي كما في الجدول أدناه و minZ و maxZ هي الحدود vc هي عدد الرؤوس في المضلع و vtx هي الرؤوس قبل vout بعد vtmp هي مؤقته للحسابات وكلهم من نوع V3D انظر أدناه عن تركيب V3D.ثم اسقاط النقاط مثلا ب perp_projection(x,y,z,&xx,&yy); ونكون قبل ذلك في الإجراءات الإستهلالية استدعينا set_projection_viewport(0,0,0,buff->w,buff->h); .نأتي الآن إلى رسم المضلعات باستدعاء scene_polygon3d(buff,type,txt,no_v,vtx[ ]); حيث txt هي النسيج إذا كنت لا تستعمل سيج دعه NULL no_v هي عدد رؤوس المضلع و vtx مؤشر إلى مصفوفة من V3D تحتوي على مواقع النقاط vtx[0]->x,vtx[0]->y,vtx[0]->z وموقع النسيج vtx[0]->u,vtx[0]->v ولون أو مقدار الإضاءة vtx[0]->c وهي في الحقيقة لا ترسم شيء وإنما تقوم بالحسابات فقط ثم نستدعي render_scene_polygon3d(); فترسم هذه الرسومات أما type فهي واحدة من التالية
POLYTYPES_FLAT تستخدم c من أول نقطة على أنها لون المضلع كاملا ولا ترسم النسيج
POLYTYPES_GCOL تستخدم c من كل نقطة بالتدريج لتلوين المضلع ولا ترسم النسيج في طور 256 لون
POLYTYPES_GRGB تستخدم c من كل نقطة بالتدريج لتلوين المضلع ولا ترسم النسيج في طور الألوان الحقيقية
POLYTYPES_ATEX ترسم النسيج بطريقة سريعة
POLYTYPES_PTEX ترسم النسيج مع معامل تصحيح العمق لصورة أفضل
POLYTYPES_ATEX_MASK ترسم النسيج بطريقة سريعة مع تفعيل قناع الشفافية
POLYTYPES_ATEX_LIT ترسم النسيج بطريقة سريعة مع استخدام c على أنها مقدار الضوء ويجب أن تكون قد أعددت color_map في ال 256 لون أو blenderfunc في طور الألوان الحقيقية
POLYTYPES_ATEX_MASK_LIT كما في سابقتها اضافة لتفعيل قناع الشفافية
POLYTYPES_ATEX_TRANS ترسم النسيج بطريقة سريعة مع تفعيل جدول الشفافية (أن تكون نصف شفافة مثلا)
POLYTYPES_ATEX_MASK_TRANS كما في سابقتها اضافة لتفعيل قناع الشفافية
ولدينا نفس آخر 6 مع تبديل PTEX مكان ATEX. ثم رسم الرسوم ثنائية الأبعاد الإضافية مثلا ب blit وأخيرا نقل كل ما رسمناه إلى الشاشة ب blit(buff, screen, 0, 0, 0,0, buff->w, buff->h);

العمليات على المصفوفات هي
get_translation_matrix(m,x,y,z) المصفوفة التي تعمل إزاحة بمقدار x,y,z
get_scaling_matrix(m,x,y,z) المصفوفة التي تعمل تحجيم (تكبير/تصغير) بمقدار x,y,z
get_x_rotate_matrix(m,r) المصفوفة التي تعمل تدير حول محور x بمقدار r (r من 0-255 تعني 0-360 درجة)
get_y_rotate_matrix(m,r) المصفوفة التي تعمل تدير حول محور y بمقدار r
get_z_rotate_matrix(m,r) المصفوفة التي تعمل تدير حول محور z بمقدار r
get_rotation_matrix(m,rx,ry,rz) المصفوفة التي تعمل تدير حول المحور بمقدار rx,ry,rz على الترتيب
get_vector_rotation_matrix(m,vx,vy,vz,r) المصفوفة التي تعمل تدير حول المتجه vx,vy,vz بمقدار r
يمكنك استبدال q مكان get لتطبق الخيار على المصفوفة m مثلا qtranslate_matrix(m,x,y,z) فإن المصفوفة الناتجة تقوم بما كانت تقوم به m إضافة إلى الإزاحة ويمكنك ضرب مصفوفتين باستعمال matrix_mul(m1,m2,m) حيث سيضرب m1 في m2 ويكون الجواب في m


<< السابق كتاب لينكس الشامل التالي >>