mzeid Admin
مزاجي :
بلدي : الهواية :
المشاركات : 1168 نقاط : 2147489225 السٌّمعَة : 0 الإنتساب : 15/08/2009 الموقع : www.mzeid.hooxs.com
| موضوع: درس في صناعة الألعاب : استخدام الجتا / الجا(Cos/Sin) 8/2/2011, 10:20 am | |
| السلام عليكم ^^
(الدرس كتبته في منتدى ثاني ونقلته هنا ^_^)
أدري إني كسلان في كتابة الدروس >_>" بس سامحوني الدرس عشان صديق اسمه كلاود عندي في المسن ^^ ..طلب مني أشرح كونسبت الـCos/Sin (جتا/جا) وعلاقتهم بصناعة الالعاب ..لما شفت الدرس بيطول قلته بكتب موضوع عشان يكون موجود للي يبي يتعلم ^^.. الموضوع ببسطه بكونسبت أخف بإذن الله عشان يكون واضح للجميع وما يحتاج عصر دماغ XD هذا الكونسبت من استنتاجي لصناعة الالعاب بس n_n يعني يا ريت محد يروح يحطه في ورقة الاختبار في الثانوية / الجامعة ويفشلنا ! .. أخلي مسئوليتي من الحين XD أعتذر مقدماً عن كمية الفلسفة في الموضوع التالي ^_^ رجاءاً تناول حبتين بنادول و اثنين ريفو عشان ما يجيك صداع xD أولاً نبدأ بإيش ممكن تفيدنا الجتا/الجا (Cos/Sin) في صناعة الالعاب الموضوع متعلق بشكل بحتي بالزوايا/ الدوائر / المنحنيات ، وبرياضات الألعاب المعقدة(مع إنها من جد مب معقدة لما تفهمها) درس اليوم بيكون بتركيز مخصوص على التحريك في إتجاه زاوية معينة ، إتقان هذا الأمر بيتيح أفكار جديدة للمبرمج يقدر يطبقها بإذن الله.. الدرس بسيط وسهل ، وأتمنى يبين كيف الموضوع سهل ومب معقد مثل ما البعض معتقد ^^ مع العلم الـCos/Sin لها استخدامات أخرى ، وهذي أبسط استخداماتها ندخل في الدرس xP تقدرون تشرحون لي الشكل التالي؟ هاه؟ مين يعرف ؟ لا الشكل ما يشير لحمامة xD هذي زاوية (ما توقعتوا هاه XD ) ندخل في الجد ^^ الزاوية تتكون من ضلعين و"فتحة" بينهم لاحظوا الضلع الثابت (الأسود) والضلع الآخر المتحرك ( اللي لونته باللون الاحمر xP بتعرفون ليه الحين) تخيلوا الحين النقطة البنفسجية في الصورة "نقطة تلاقي الضلعين" هي كائن ما ، تصوروا لو نقدر نخليها تتحرك تجاه النقطة الزرقاء في الصورة "نقطة على الضلع المتحرك" ، هذا اللي بإذن الله بنحاول نعمله اليوم وهذا بيفيدنا في إننا نحرك هذي الشخصية على حسب زاويتها ^^ بالمناسبة ، الضلع الثابت عادة يرسم بس عشان يحدد مقدار فتحة الزاوية أحس إن شرحي معقد الأمور X"D على أي حال نكمل ناتج جتا الزاوية في الصورة هو احداثي (س/X ) النقطة الزرقاء ، وناتج جا الزاوية في الصورة هو احداثي (ص/Y ) النقطة الزرقاء في الصورة ، بإعتبار إن احداثي النقطة البنفسجية هو (0 ، 0) وبإعتبار إن المسافة بين النقطة الزرقاء هي 1 بكسل فهمتوا شئ؟ XD أنا نفسي مب فاهم اللي أكتبه عشان نوضح أكثر ، شوفوا الصورة التالية : هذا يشرح الجتا/جا بالطريقة التقليدية ^^ .. تخيلوا النقطة البنفسجية في إحداثي (0،0) يعني مكان نقطة الأصل في دائرة طول نصف قطرها 1 ، وهنا النقطة البنفسجية هي مركزها بالمناسبة ، هذا معناه إن المسافة بين مركز الدائرة ( النقطة البنفسجية) و أي نقطة على الدائرة ( أي نقطة زرقاء) هو 1 لكن هذا مب معناه إن لازم أي من الاحداثيين يكون 1 ، بس البعد بين المركز وأي نقطة على الدائرة = 1 هنا ^^ لو قلنا جتا(Cos) الزاوية بيطلع احداثي X للنقطة الزرقاء اللي بيتلاقى فيها الضلع المتحرك مع الدائرة ولو قلنا جا (Sin ) الزاوية بيطلع احداثي Y للنقطة الزرقاء اللي بيتلاقى فيها الضلع المتحرك مع الدائرة يعني بإختصار ^^ بيكون إحداثي أي نقطة تقع "على" الدائرة هو (جتا الزاوية ، جا الزاوية ) طيب نفترض الزاوية 90 ، يعني الخط طالع من المركز مباشرة على فوق xP .. من دون ما تستخدمون الآلة الحاسبة ، تقدرون تقولون كم جتا 90 وجا 90 في هاي الحالة (النقطة الزرقاء) ؟ ^^ ببساطة بما إننا تحركنا لفوق ومب يمين ولا يسار بتكون جتا( 90 ) = 0 ،، جا ( 90 ) = 1 بما إنه خط طالع لفوق مباشرة ! ..يعني تحركنا 1 على الإحداثي الصادي (Y ) وما تحركنا شئ على الإحداثي السيني (X ) طيب لو 0 ؟ ^^ بنكون تحركنا لليمين وما تحركنا شئ على إحداثي Y يعني جتا(0) = 1 و جا (0) =0 طيب لو زاوية 45 ؟ XD هذي بإذن الله (0.707 ، 0.707) ..بس طبعاً إحنا مالنا دخل =P بنسيب اللعبة تحسب الزوايا ! في شئ نقدر نستنتجه ^^ .. دام الدائرة نصف قطرها =1 ..فهذا معناه إن الجا/الجتا بين الـ-1 والـ1 ! يعني مستحيل دائرة نصف قطرها 1 وموجودة في نقطة الأصل وتكون نقطة تقاطع الضلع المتحرك معاها 2 مثلاً XD طيب كيف بنقدر نستفيد من هذا؟ ^^ نرجع مرة ثانية لصورة الحمامة..أقصد الزاوية xD على اعتبار إن النقطة الزرقاء هنا تبعد عن النقطة البنفسجية 1 .. كيف نقدر نخلي النقطة البنفسجية تتحرك نحوها؟ ببساطة نفس فكرة الدائرة اللي فوق ^^ الاحداثي السيني للنقطة الزرقاء = الاحداثي السيني للنقطة البنفسجية + جتا(الزاوية) الاحداثي الصادي للنقطة الزرقاء = الاحداثي الصادي للنقطة البنفسجية + جا(الزاوية) في البرمجة بيصير الامر كالتالي ^^ : (على إعتبار إن blueX , blueY احداثيات النقطة الزرقاء.. و purpleX , purpleY إحداثيات النقطة البنفسجية ... و angle الزاوية بين النقطتين)
كود:
blueX = purpleX+cos(angle);
blueY = purpleY + sin(angle);
ممتاز جداً ! >ن< الحين نقدر نحرك النقطة على حسب زاويتها ^_^ !! طيب بس ما تلاحظون إن السرعة بتكون بطيئة >_>" كيف نقدر نعدلها؟ ببساطة ^^ .. بنقوم بضرب الجتا/الجا في السرعة اللي نبيها ^__^ لو نبي ضعف السرعة(2) بنقوم بضربها في 2 ..لو نبي 3 بنقوم بضربها في 3 وهكذا.. مثال : كود: Speed = 5;
blueX = purpleX+cos(angle)*Speed;
blueY=purpleY+sing(angle)*Speed; ببساطة بيتم مضاعفة المسافة ^^ مثال أكثر استخداماً / تنظيماً للتحرك على حسب الزاوية : (في هذا المثال dX هي المسافة التي سيتم اضافتها على الاحداثي السيني ، و dY هي المسافة التي سيتم اضافتها على الاحداثي الصادي ) كود:
dX = cos(angle)*Speed;
dY= sin(angle)*Speed;
x=x+dX;
y=y+dY;
أتمنى يكون كل شئ واضح الحين ^_^ ! بكتب مثال بسيط في النهاية XD ..بالأليغرو لإني بحط الدرس في مكان ثاني بعد ^^ .. بس أتمنى برنس أو أي أحد يقرأ الدرس ويفهمه يعمل مثال بالجيم ميكر بعد عشان يكون واضح لمستخدمي الجيم ميكر ^_^ -- اعمل مشروع جديد ، وبعدها اعمل ملف هيدر جديد ..سميه اللي تبي xD بسميه gameBullet.h ، بما إن اللي ناوي أسويه قريب جداً من اللي يستخدموه في ألعاب الشوتر ^-^ ببساطة بنحط فيه كلاس ، سميه اللي تبي xP بسميه gameBullet بعد عشان يكون على اسم الملف ^^ بس براحتك ! كود: #include <allegro.h>
class gameBullet
{
public:
fixed x , y;
fixed angle;
gameBullet(fixed newX,fixed newY,fixed newAngle);
void update();
};
الكلاس بيخزن معلومات عن احداثيات كل رصاصة ^^ وزاوية تحركها ، ايضاً بيحتوي كونستركتور (يتم استدعاؤه حينما يتم الإعلان عن الكائن) وفنكشن بسيطة بنسميها update بتتكفل بتحديث الرصاصة ^^ وإضافة الموقع الجديد عليها المهم ، لاحظوا هنا إننا استخدمنا نوع fixed ! نوع غريب للمتغيرات صح؟ متعودين عادة نستخدم انتيغر / فلوت (أعداد صحيحة / أعداد نسبية) .. السبب الرئيسي إن في الواقع في احداثيات على الشاشة مثلاً 2.5 ما لها معنى حقيقة xD رغم إن محركات ثانية تسمح بيها وتقرب لأقرب عدد صحيح لما تطلب منها الرسم في موقع غير صحيح ^^ ..لإن لما يكون عندنا شاشة مثلاً بعرض 850 بكسل ..فمعناها عندنا 850 بكسل صحيحة ومن المستحيل الرسم بينها لأنها أصغر وحدة ! فهنا نوع fixed جاء مع الاليغرو عشان يهتم بالموضوع ^_^ .. بالإضافة لبعض الدوال الثانية للتحويل ! نرجع لملف الـmain.cpp (لو ما غيرت اسمه xP ) فيه الكود المبدأي للأليغرو مثل وضع الـcolor depth و فتح الشاشة ، الخ المهم لا تنسى تضيف فوق جملة إنكلود لملف الهيدر ^^
كود:
#include "gameBullet.h"
كود: انزل تحت ، بنعرف الكونستركتور اللي كتبنا الـprototype حقه في ملف الهيدر ^^ بيتم استدعائه في بداية تكوين الأوبجكت كود:
gameBullet::gameBullet(fixed newX, fixed newY , fixed newAngle)
{
x = newX;
y = newY;
angle = newAngle;
} ببساطة يتيح لك إنك تدخل القيم ، وبيقوم بمساواة القيم داخل الاوبجكت بالقيم اللي أدخلتها ^^ بعدها عرف فنكشن الـupdate اللي كتبنا البروتوتايب حقها في الهيدر بعد ^_^
كود:
void gameBullet::update()
{
x += fcos(angle);
y += fsin(angle);
}
ببساطة بيزود على الاحداثيات الحالية الجتا والجا للزاوية ^^ لاحظ إننا استخدمنا fcos و fsin ، الدالتين بيتم استخدامهم مع نوع fixed ^^ وبيقوموا بإرجاع قيمة من نوع fixed كود: #include <vector>
using namespace std;
vector<gameBullet*> bullets;
اطلع فوق مرة ثانية XD قوم بعمل إنكلود لهيدر الفيكتور اللي ما يعرف ايش هو الفيكتور ^^ فهو جزء من الـSTL ، ببساطة هو array او لائحة تقدر تضيف ليها كائنات من النوع اللي تختاره ^_^ وهذا بيسهل علينا كثير تطبيق نفس الشئ على عدد من الكائنات بوقت واحد ! شئ ثاني ، مثل معظم مكتبات الـSTL لازم تستخدم using namespace std وفي السطر الثالث بنعمل فيكتور من نوع الكلاس اللي عملناه ..ونسمي الفيكتور بإسم bullets كود: BITMAP* buffer;
وقوم بعمل بوينتر عشان بفر الشاشة ^^ ( بنقوم برسم كل شئ على هذا البفر ، بعدين في النهاية بنقوم برسم البفر على الشاشة ، وهذا أفضل للجرافكس كارد) إنزل تحت في بداية الـمين ^^ .. وضيف هذا السطر : كود:
buffer = create_bitmap(screen->w , screen->h);
ببساطة بنقوم بشغل مساحة البفر بصورة فارغة ^_^ .. عرضها عرض الشاشة وطولها طول الشاشة
كود:
for (int i=0; i != 10 ;i++)
{
bullets.push_back(new gameBullet(itofix(screen->w/2) , itofix(screen->h/2) ,itofix( i*30)));
}
بدأنا اللعب XDD بنستخدم جملة for عشان نكرر الكود 10 مرات ^_^ .. ببساطة بيقوم بإضافة 10 كائنات للفيكتور (بما إن شرط الخروج إن العداد I يساوي 10 xP ) كل مرة في وسط الشاشة ^^ (العرض مقسوم على 2 ، والطول مقسوم على 2) .. وهنا دالة ثانية itofix لتحويل الرقم الناتج لـfixed ^^ بالنسبة للقيمة الثالثة (الزاوية ) بتساوي قيمة العداد (0 إلى 10 ) * 30 .. عشان نتأكد إن الزاوية كبيرة بس ^^ وتكبر أكثر مع كل أوبجكت ^^ اعثر على :
كود:
while (!key[KEY_ESC])
{
}
وضع بداخلها ^^ :
كود:
for ( int i =0; i < bullets.size() ; i++ )
{
bullets[i]->update();
textout_ex(buffer, font, "@",fixtoi( bullets[i]->x), fixtoi(bullets[i]->y)
, makecol(255, 0, 0), -1);
}
ببساطة سنمر داخل كل عنصر في الفيكتور ونقوم باستدعاء فنكشن update ومن ثم سنقوم برسم حرف "@" مكانه XD يعني بدل السبرايت ^^ >>بما إن المثال ما فيه سبرايت كود: draw_sprite(screen,buffer,0,0); clear(buffer); قم برسم البفر على الشاشة ثم محوه للتجهيز للرسم عليه مجدداً ^^ وأول ما تعمل كومبايل بإذن الله بتشوف هذي النتيجة ^^ :
10 علامات "@" يتحركوا على شكل دائرة XD هذا ملف exe مع السورس ^^ http://www.mediafire.com/?omkyuj3wm5jdjnw وبهكذا ينتهي درسنا اللي مدري وش أبي منه ه1 الواجب في محرككم المفضل اعملوا شخصية لما تضغط سهم أيمن أو أيسر تدور ولما تضغط للأمام أو للوراء تتحرك في إتجاه الزاوية أو عكسه ^_^ | |
|