درس في صناعة الألعاب : استخدام الجتا / الجا(Cos/Sin)

mody-san

] عضو شرير قداً [
تاماشي
0

السلام عليكم ^^



أدري إني كسلان في كتابة الدروس >_>" بس سامحوني



الدرس عشان صديق اسمه كلاود عندي في المسن ^^ ..طلب مني أشرح كونسبت الـ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 وهكذا..

مثال :


كود:
       [COLOR=Purple]
Speed = 5;

blueX = purpleX+cos(angle)*Speed;

blueY=purpleY+sing(angle)*Speed;
  [/COLOR]

ببساطة بيتم مضاعفة المسافة ^^







مثال أكثر استخداماً / تنظيماً للتحرك على حسب الزاوية :

(في هذا المثال dX هي المسافة التي سيتم اضافتها على الاحداثي السيني ، و dY هي المسافة التي سيتم اضافتها على الاحداثي الصادي )

كود:
    [COLOR=Purple]

dX = cos(angle)*Speed;

dY= sin(angle)*Speed;

x=x+dX;

y=y+dY;

[/COLOR]


أتمنى يكون كل شئ واضح الحين ^_^ !

بكتب مثال بسيط في النهاية XD ..بالأليغرو لإني بحط الدرس في مكان ثاني بعد ^^ .. بس أتمنى برنس أو أي أحد يقرأ الدرس ويفهمه يعمل مثال بالجيم ميكر بعد عشان يكون واضح لمستخدمي الجيم ميكر ^_^



--

اعمل مشروع جديد ، وبعدها اعمل ملف هيدر جديد ..سميه اللي تبي xD بسميه gameBullet.h ، بما إن اللي ناوي أسويه قريب جداً من اللي يستخدموه في ألعاب الشوتر ^-^

ببساطة بنحط فيه كلاس ، سميه اللي تبي xP بسميه gameBullet بعد عشان يكون على اسم الملف ^^ بس براحتك !




كود:
           [COLOR=Purple]
#include <allegro.h>

class gameBullet

{

  public:

   fixed  x , y;

   fixed  angle;

   gameBullet(fixed newX,fixed newY,fixed newAngle);

   void update();



};

[/COLOR]


الكلاس بيخزن معلومات عن احداثيات كل رصاصة ^^ وزاوية تحركها ، ايضاً بيحتوي كونستركتور (يتم استدعاؤه حينما يتم الإعلان عن الكائن) وفنكشن بسيطة بنسميها update بتتكفل بتحديث الرصاصة ^^ وإضافة الموقع الجديد عليها



المهم ، لاحظوا هنا إننا استخدمنا نوع fixed ! نوع غريب للمتغيرات صح؟ متعودين عادة نستخدم انتيغر / فلوت (أعداد صحيحة / أعداد نسبية) .. السبب الرئيسي إن في الواقع في احداثيات على الشاشة مثلاً 2.5 ما لها معنى حقيقة xD رغم إن محركات ثانية تسمح بيها وتقرب لأقرب عدد صحيح لما تطلب منها الرسم في موقع غير صحيح ^^ ..لإن لما يكون عندنا شاشة مثلاً بعرض 850 بكسل ..فمعناها عندنا 850 بكسل صحيحة ومن المستحيل الرسم بينها لأنها أصغر وحدة !



فهنا نوع fixed جاء مع الاليغرو عشان يهتم بالموضوع ^_^ .. بالإضافة لبعض الدوال الثانية للتحويل !





نرجع لملف الـmain.cpp (لو ما غيرت اسمه xP ) فيه الكود المبدأي للأليغرو مثل وضع الـcolor depth و فتح الشاشة ، الخ



المهم لا تنسى تضيف فوق جملة إنكلود لملف الهيدر ^^

كود:
#include "gameBullet.h"
كود:
    [COLOR=Purple]

[/COLOR]


انزل تحت ، بنعرف الكونستركتور اللي كتبنا الـprototype حقه في ملف الهيدر ^^ بيتم استدعائه في بداية تكوين الأوبجكت

كود:
    [COLOR=Purple]

gameBullet::gameBullet(fixed newX, fixed newY , fixed newAngle)

{

 x = newX;

 y = newY;

 angle = newAngle;                          

}
  [/COLOR]



ببساطة يتيح لك إنك تدخل القيم ، وبيقوم بمساواة القيم داخل الاوبجكت بالقيم اللي أدخلتها ^^



بعدها عرف فنكشن الـupdate اللي كتبنا البروتوتايب حقها في الهيدر بعد ^_^
كود:
void gameBullet::update()

{

 x += fcos(angle);

 y += fsin(angle);

}
ببساطة بيزود على الاحداثيات الحالية الجتا والجا للزاوية ^^



لاحظ إننا استخدمنا fcos و fsin ، الدالتين بيتم استخدامهم مع نوع fixed ^^ وبيقوموا بإرجاع قيمة من نوع fixed


كود:
       [COLOR=Purple]
#include <vector>

using namespace std;

vector<gameBullet*> bullets;

[/COLOR]


اطلع فوق مرة ثانية XD

قوم بعمل إنكلود لهيدر الفيكتور

اللي ما يعرف ايش هو الفيكتور ^^ فهو جزء من الـSTL ، ببساطة هو array او لائحة تقدر تضيف ليها كائنات من النوع اللي تختاره ^_^ وهذا بيسهل علينا كثير تطبيق نفس الشئ على عدد من الكائنات بوقت واحد !

شئ ثاني ، مثل معظم مكتبات الـSTL لازم تستخدم using namespace std

وفي السطر الثالث بنعمل فيكتور من نوع الكلاس اللي عملناه ..ونسمي الفيكتور بإسم bullets


كود:
       [COLOR=Purple]
BITMAP* buffer;

[/COLOR]


وقوم بعمل بوينتر عشان بفر الشاشة ^^ ( بنقوم برسم كل شئ على هذا البفر ، بعدين في النهاية بنقوم برسم البفر على الشاشة ، وهذا أفضل للجرافكس كارد)



إنزل تحت في بداية الـمين ^^ ..

وضيف هذا السطر :

كود:
    [COLOR=Purple]

buffer = create_bitmap(screen->w , screen->h);

[/COLOR]


ببساطة بنقوم بشغل مساحة البفر بصورة فارغة ^_^ .. عرضها عرض الشاشة وطولها طول الشاشة
كود:
            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 يعني بدل السبرايت ^^ >>بما إن المثال ما فيه سبرايت
كود:
[CENTER][COLOR=Purple]  draw_sprite(screen,buffer,0,0);
  
clear(buffer);
  
 [/COLOR][/CENTER]

قم برسم البفر على الشاشة ثم محوه للتجهيز للرسم عليه مجدداً ^^



وأول ما تعمل كومبايل بإذن الله بتشوف هذي النتيجة ^^ :







10 علامات "@" يتحركوا على شكل دائرة XD

هذا ملف exe مع السورس ^^

http://www.mediafire.com/?omkyuj3wm5jdjnw



وبهكذا ينتهي درسنا اللي مدري وش أبي منه ه1



الواجب

في محرككم المفضل اعملوا شخصية لما تضغط سهم أيمن أو أيسر تدور ولما تضغط للأمام أو للوراء تتحرك في إتجاه الزاوية أو عكسه ^_^



 

mody-san

] عضو شرير قداً [
تاماشي
0
مو هذا الدرس شرحته انا لك xd ?
اوكي لي عودة قريباً ...
يب يب ^_^ أنا فهمته زمان بفضل من الله ثم من اللي شرحته + دروس من الانترنت + المدرسة xD والحمد لله

بس الحمد لله فاهم الموضوع من زمان ^_^ وأذكر كنت سألتك عن كيفية تطبيقه على الثري دي مب التو دي قبل xD

لحظة ، لا تعمل أنت الأمثلة
برنس عمل الأمثلة بالجيم ميكر وحطها في منتدى المنت** من دون ما يشرح وقال بيرجع بعدين xD

فانتظره =P
 

Ajas

فانتومي
تاماشي
0
رغم إني ماقريت غير نص الكلام ><" >>>>>>>>>>>>>>>>>>>>>> كسولة

لكن تشكر على المجهود مودي ^^
 

ranka

محبة الرياح
تاماشي
0
اوه درس حلو ^.^ بستفيد منه
ان شاء الله
بس كنت اظن ان استخدام الانجل لحالها
يكفي فاذا كنت بتحركها لمثل اول رسمة
للزاوية الي رسمتاها نكتب الانجل 45
واذا كنا نبيها من زاوية من تحت نحط -45
مممم بغيت اسالك بالنسبة للسرعة انت ضربت في
جتا وجا لكن هذا بيخليه يتحرك لنقطة ابعد
هل ممكن نضيف ونكتب ان السبيد -السرعة- قيمتها مثلا 5
بيكون افضل
باقي الدرس ما قريته زين^^`` لما ادخل
من جهازي بكمل واشوفه
 

mody-san

] عضو شرير قداً [
تاماشي
0
هلا أختي ميمي ^^ !
يب ، على ما أتذكر في أكشن في الغيم ميكر في تحرك على حسب الزاوية ^^
لكن على ما أتذكر "مب واثق" مب موجودة في الـGML ^_^ ..
بالإضافة إن هذا مب الاستخدام الوحيد للجتا / الجا ^^ مثلاً الضرب في الجتا/الجا (الضرب في احدهم مع ثبات الأخر) ينتج عنه حركة تموجية ^^ ..هذا احتمال اكتب عنه درس أو احتمال لا XD
بس ببساطة بتستمرين في زيادة الزاوية كل ثانية ولو الموجة عمودية مثلاً تجمعين Sin الزاوية على احداثي Y بينما احداثي X بتضيفين عليه سرعة ثابتة XD

وفي اشياء ثانية ممكن تستخدمينها فيه مثل إنك تستخدمين مقلوبات الـجتا/الجا في إنك تكشفين عن الزاوية بين كائنين وتخلي واحد منهم يتحرك في هذي الزاوية (يعني تخليه يتحرك في اتجاه كائن آخر)
وهذا اعتقد بعد يوفره الجيم ميكر XD كان اسمها Move toward point على ما اتذكر؟

شوفي بعطيكي نصيحة ^__^ حتى لو وفرلك المحرك وسائل للطفو على الماء ، اخلعيها وتتعلمي السباحة ^^ عشان بيجي وقت عليكي ممكن تنتقلين لمحرك ثاني ، أو بإذن الله تنتقلين للثري دي ^__^
ووقتها بتجدي إن أمامك كثير تتعلميه عشان الأدوات الجاهزة اللي كان يوفرها المحرك السابق مب موجودة ، لما تقومي بالأشياء بشكل يدوي بتزداد خبرتك أكثر من الأدوات الجاهزة بإذن الله
وبيزداد فهمك لميكانيكيتها ^^ وبالتالي بتقدري تستخدميها أحسن ، وبيكون سهل عليكي تنتقلين من محرك لآخر من دون معاناة محاولة فهم أشياء جديدة كثيرة^_^

بالنسبة للسرعة وضربها في الجتا/الجا XD فلا
جربي بنفسك وشوفي =P
تذكري شئ ، في العمليات الحسابية في ترتيب للأولويات
حتى لو الجمع والطرح كان ترتيبهم في العملية قبل الضرب أو القسمة ، فعمليات الضرب والقسمة لازم تتم أولاً ^^
مثال ( اقرأيه من اليمين لليسار)
5+3×10 =؟
ممكن البعض يعمل عمليات الجمع أولاً ^^ .. 5+3 = 8 ، 8 × 10 = 80 .. بيطلع الناتج 80
لكن هذا غير صحيح ^^ لازم الضرب يتم أولاً
3×10 = 30
5+30 = 35
شفتي الفرق؟ xD

الحين نفترض الشخصية في موقع 20 على احداثي X .. والسرعة =5 ، ونبي نحركها في اتجاه زاوية 0 على الاحداثي السيني
الموقع الجديد = 20 + جتا(0) × 5
(بالمناسبة هذا مب قانون عشان تحفظيه XD لا تحفظي شئ في صناعة الألعاب !! افهميه بس ! )
بتكون العملية بالشكل التالي :
20 + جتا(0) × 5
= 20 + 1 ×5
=20 + 5
=25
بهذي الطريقة تحرك بسرعة 5 في اتجاه الزاوية 0 ^^

الموضوع مب معقد بالمناسبة XD ولا أحد ياخذه على إنه مثل دراسة الرياضيات في المدرسة !
هذي صناعة ألعاب *_* مفروض تكون أمتع من لعب الالعاب نفسها !! ^__^
تذكروا إننا ما نحرك مجرد نقطة على احداثي XP (باااه ممل !!) ..احنا نحرك شخصية أنمي خارقة تحاول تنقذ العالم مثلاً XD أو سمكة تبحث عن امها XD أو ماريو يحاول ينقذ الأميرة مثلاً D=

+آسف عشان ما رديت عليكي يا ميمي للحين بخصوص الرسالة الخاصة اللي ارسلتيها XD كنت مشغول xS
بحاول أرد بإذن الله ^_^
 

Prinsu-kun

عضو قدير
تاماشي
0
السلام عليكم ورحمة الله وبركاته

شكرا مودي سان, انا طبقت الملف من زمان وسوري تاخرت في الرفع تطبيقي لاني منشغل لفترة
المهم رفعت تطبيقي مع السورس وكذلك صيغة exe :) في المرفقات :022:

تطبيق المثال كان لجعل الكورة تدور في مسار ثابت دون أي أنحراف وبسرعة تزداد ويمكن ملاحظة
عن طريق رسم الكورة لمسارها :great:
تحياتي البرنسية



exe simple:
download
 

المرفقات

التعديل الأخير:

الأعضاء الذين قاموا بالقراءة (المجموع:0)

أعلى