تطوير PongGame باستخدام C++ و مكتبة raylib 🎮 👾 | جزء1

  • بادئ الموضوع بادئ الموضوع Mina
  • تاريخ البدء تاريخ البدء

Mina

.:: عضو فعّال ::.
.:: كاتب تقني ::.

بسم الله الرحمن الرحيم

بعد أن قمنا بتهيئة بيئة العمل الخاص بنا سوف نبدا بتأسيس اللعبة , لكن قبل البدء ما الذي يجب عليك معرفته؟
  • أساسيات البرمجة بال ++C
  • OOPيمكنكم متابعة الدروس المقدمة في شبكة شل من طرف Sadell_Ali ستجدونها جد مفيدة وكافية



والسؤال المطروح هو كيف سنبدأ ؟ أو من أين؟
ستكون المنهجية المتبعة هي المفهوم الشائع في البرمجة Divide & conquer ويعتمد على تجزئة مشكلة معينة معقدة نسبيًا إلى مجموعة من الأجزاء أقل تعقيدًا وحل كل جزء على حدً, في الأخير سنكون قد قمنا بحل كل الأجزاء ثم نعيد جمعها معًا لتكون المشكلة الأساسية قد حُلت .

أولًا لنتعرف على بنية اللعبة :

أي لعبة لها قسمين :
  1. التعريفات : نعرف جميع Objects والمتغيرات الموجودين في اللعبة من كرة ,مجاذيف ..الخ
  2. Game loop : هي عمر وحلقة اللعبة وفيها سنقوم بتحديث مواقع Objects في كل مرة وسنقوم بتحريكها حركات متعاقبة تحدث بسرعة كبيرة فتبدو كانها حركة مستمرة.

ثانيًا الأجزاء والخطوات:
  1. إنشاء وتخصيص (Customize) نافذة وشاشة العرض
  2. إنشاء حلقة اللعبة Game loop (عمر اللعبة)
  3. الرسم
  4. تحريك الكرة وتحديد التصادمات ومراقبتها (animation)
  5. تحريك المجذاف الخاص بالمعالج CPU
  6. إضافة عداد + Timer



  • إنشاء وتخصيص (Customize) نافذة وشاشة العرض.

C++:
#include<iostream>
#include<raylib.h>
int main(){
    const int screen_width = 1270;
const int screen_height = 550;

    InitWindow(screen_width, screen_height, "Sh3ll Game");// دالة تستقبل ثلاث معاملات(عرض الشاشة,طول الشاشة,عنوان الشاشة) يمكنكم تعديل الابعاد حسب الحاجة
  CloseWindow();//في لحظة ما سنحتاج لغلق هذه النافذة بواسطة
 return 0;
}


  • Game loop (تُحَدث باستمرار)
يجب علينا مراقبة أي حدث في اللعبة, كـ تحديث أماكن جميع Objects ,رسم الأشكال في أماكنهم الجديدة وغيرها.
ملاحظة: مادامت اللعبة لم تتوقف يجب علينا رسم الأشكال في كل لحظة

متى تتوقف اللعبة ؟ عندما يغلق اللاعب النافذة, إذًا سيكون هذا شرطنا الحالي
C++:
#include<iostream>
#include<raylib.h>
int main(){
    const int screen_width = 1270;
const int screen_height = 550;
InitWindow(screen_width, screen_height, "Sh3ll Game");
    while (!WindowShouldClose() ) {//مادام االاعب لم يغلق النافذة سيستمر عمر اللعبة
    BeginDrawing();// بداية الرسم
    EndDrawing();// في لحظة ما نحتاج الى وقف الرسم بواسطة
    }
 
}

أمر آخر وهو أنه يجب علينا تحديد سرعة اللعبة حيث أن سرعة اللعبة ستكون ثابتة خلال اللعبة إذًا ستكون خارج while loop

C++:
#include<iostream>
#include<raylib.h>
int main(){
    const int screen_width = 1270;
const int screen_height = 550;
InitWindow(screen_width, screen_height, "Sh3ll Game");
SetTargetFPS(65);//< ---(سيتم تحديث الشاشة 65 مرة في الثانية ) سرعة اللعبة تكون بتحديد كم مرة في الثانية سيتم تحديث الشاشة وهذا ما سيتحكم بسلاسة اللعب بواسطة
    while (!WindowShouldClose() ) {
    BeginDrawing();
 EndDrawing();
}
    CloseWindow();
return 0;
}

ماذا لو لم نستعمل SetTargetFPS(65) في هذه الحالة؟ سيقوم كل حاسوب بتنفيذ اللعبة بأعلى سرعة ممكنة
إذًا ستختلف سرعة اللعبة من حاسوب لآخر حسب إمكانياته , لكن بتحديد السرعة سنضمن أن سرعة اللعبة ثابتة بالنسبة لجميع الحواسيب



  • الرسم: تتيح raylib رسم أشكال أساسية كالدائرة , مستطيل, خط ... إلخ , سنستعمل الدائرة بما أننا بحاجة لرسم الكرة
C++:
void DrawCircle(int center1,int center2,float radius,Color color)// تقوم هذه الدالة برسم دائرة
//    center1: Xتمثل احداثيات الرسم بالنسبة للمحور
//center2:Y تمثل احداثيات الرسم بالنسبة للمحور
//radius: نصف قطر الدائرة والذي يحدد حجمها
//Color: لون الدائرة
أولًا أُريد أن أرسم الكرة في المنتصف سيكون الرسم بالنسبة لاحداثيات X و y كما ذكرنا سابقًا , بداية الشاشة على الحافة تمثل (0,0) من ثم أبعاد الشاشة ستكون محددة من طرفكم , ولإيجاد المنتصف يكفي أن نقوم بعملية قسمة بسيطة.

demo.PNG
C++:
DrawCircle(screen_width / 2, screen_height / 2, 20, WHITE);
// اخترت RADIUS =20
// بالنسبة للالوان تكتب CAPITAL

النتيجة بعد تنفيذ الكود:
السرعة في هذه المرحلة بدون تأثير لأننا لم نقم بالـ Animation بعد


demo1.PNG

والآن فالنرسم المجاذيف: بما أن المجاديف تأخذ شكل مستطيل سنستعمل دالة الرسم الخاصة بالمستطيل

C++:
 DrawRectangle(int px,int py,int width,int height,Color clor);
//px=position x
//py = position y
سنقوم برسمه في المنتصف:
C++:
DrawRectangle(0,screen_height / 2,35,120,WHITE);

النتيجة :
demo2.PNG

ملاحظة: إنه لا يظهر في منتصف الشاشة والسبب أن المستطيل يُحَدد من الحافة العلوية له


demo2.PNG

فالحافة العلوية المحددة بالنقطة الحمراء هي أساسًا في المنتصف لكن هل نحن نريد المستطيل أن يتموضع في منتصف الشاشة ؟
في هذه الحالة يجب أن يكون منتصف المستطيل في منتصف الشاشة

demo2.PNG
هذه أحداثيات النقطة الصفراء:
كود:
exactposition=(screen_height / 2)+(Rectangle_height/2)

وبالتالي لإيجاد الأحداثيات المناسبة يجب أن تكون حافة المستطيل (النقطة الحمراء) متموضعة.
كود:
reddotpos=screen_height / 2-Rectangle_height/2;
كود:
 DrawRectangle(0, screen_height / 2- 60, 35, 120, WHITE);
 //rectangleheight=120
// 120/2=60;
demo3.PNG

لا أُريد للمجذاف أن يكون ملتصقًا تمامًا بالشاشة سأبعده بعض ملمترات:
كود:
 DrawRectangle(10, screen_height / 2- 60, 35, 120, WHITE);

demo4.PNG

والآن لننتقل للمجذاف الثاني : يجب أن يتموضع يمين الشاشة

demo6.PNG

كود:
DrawRectangle(screen_width-45, screen_height / 2 - 60, 35, 120, WHITE);

demo7.PNG

يتبقي لنا الشي الوحيد في الرسم وهو الفاصل ببساطة وبنفس الخطوات سيتموضع في وسط الشاشة إذًا :

demo11.PNG

C++:
 // DrawLine(int startpox,int startposy ,int endposx, int endposy, Color color)
DrawLine(screen_width / 2, 0, screen_width / 2, screen_height, WHITE);

demo10.PNG

وهكذا أتممنا الجزء الخاص بالرسم سنقوم في المرات المقبلة إن شاء الله بال Animation والتعديل عليه.

تلخيص الكود
C++:
#include <iostream>
#include<raylib.h>

int main()
{
    const int screen_width = 1270;
    const int screen_height = 550;
    InitWindow(screen_width, screen_height, "Sh3ll Game");
    SetTargetFPS(65);
    while (!WindowShouldClose()) {
        BeginDrawing();
        DrawLine(screen_width / 2, 0, screen_width / 2, screen_height, WHITE);
        DrawCircle(screen_width / 2, screen_height / 2, 20, WHITE);
        DrawRectangle(10, screen_height / 2- 60, 35, 120, WHITE);
        DrawRectangle(screen_width-45, screen_height / 2 - 60, 35, 120, WHITE);
  
        EndDrawing();
  
    }
    CloseWindow();
    return 0;
}
دمتم بخير 🦋
 

المرفقات

  • demo3.PNG
    demo3.PNG
    6 KB · المشاهدات: 25
  • demo5.PNG
    demo5.PNG
    10.2 KB · المشاهدات: 30
  • demo9.PNG
    demo9.PNG
    20.4 KB · المشاهدات: 26
  • firstpg.cpp
    firstpg.cpp
    663 بايت · المشاهدات: 40

بارك الله فيك وجزاك الله كل خير مينا
وننتظر الجزء الثاني​
 
  • Love
التفاعلات: Mina

  • Love
التفاعلات: STORM

بسم الله الرحمن الرحيم

بعد أن قمنا بتهيئة بيئة العمل الخاص بنا سوف نبدا بتأسيس اللعبة , لكن قبل البدء ما الذي يجب عليك معرفته؟
  • أساسيات البرمجة بال ++C
  • OOPيمكنكم متابعة الدروس المقدمة في شبكة شل من طرف Sadell_Ali ستجدونها جد مفيدة وكافية



والسؤال المطروح هو كيف سنبدأ ؟ أو من أين؟
ستكون المنهجية المتبعة هي المفهوم الشائع في البرمجة Divide & conquer ويعتمد على تجزئة مشكلة معينة معقدة نسبيًا إلى مجموعة من الأجزاء أقل تعقيدًا وحل كل جزء على حدً, في الأخير سنكون قد قمنا بحل كل الأجزاء ثم نعيد جمعها معًا لتكون المشكلة الأساسية قد حُلت .

أولًا لنتعرف على بنية اللعبة :

أي لعبة لها قسمين :
  1. التعريفات : نعرف جميع Objects والمتغيرات الموجودين في اللعبة من كرة ,مجاذيف ..الخ
  2. Game loop : هي عمر وحلقة اللعبة وفيها سنقوم بتحديث مواقع Objects في كل مرة وسنقوم بتحريكها حركات متعاقبة تحدث بسرعة كبيرة فتبدو كانها حركة مستمرة.

ثانيًا الأجزاء والخطوات:
  1. إنشاء وتخصيص (Customize) نافذة وشاشة العرض
  2. إنشاء حلقة اللعبة Game loop (عمر اللعبة)
  3. الرسم
  4. تحريك الكرة وتحديد التصادمات ومراقبتها (animation)
  5. تحريك المجذاف الخاص بالمعالج CPU
  6. إضافة عداد + Timer



  • إنشاء وتخصيص (Customize) نافذة وشاشة العرض.

C++:
#include<iostream>
#include<raylib.h>
int main(){
    const int screen_width = 1270;
const int screen_height = 550;

    InitWindow(screen_width, screen_height, "Sh3ll Game");// دالة تستقبل ثلاث معاملات(عرض الشاشة,طول الشاشة,عنوان الشاشة) يمكنكم تعديل الابعاد حسب الحاجة
  CloseWindow();//في لحظة ما سنحتاج لغلق هذه النافذة بواسطة
 return 0;
}


  • Game loop (تُحَدث باستمرار)
يجب علينا مراقبة أي حدث في اللعبة, كـ تحديث أماكن جميع Objects ,رسم الأشكال في أماكنهم الجديدة وغيرها.
ملاحظة: مادامت اللعبة لم تتوقف يجب علينا رسم الأشكال في كل لحظة

متى تتوقف اللعبة ؟ عندما يغلق اللاعب النافذة, إذًا سيكون هذا شرطنا الحالي
C++:
#include<iostream>
#include<raylib.h>
int main(){
    const int screen_width = 1270;
const int screen_height = 550;
InitWindow(screen_width, screen_height, "Sh3ll Game");
    while (!WindowShouldClose() ) {//مادام االاعب لم يغلق النافذة سيستمر عمر اللعبة
    BeginDrawing();// بداية الرسم
    EndDrawing();// في لحظة ما نحتاج الى وقف الرسم بواسطة
    }
 
}

أمر آخر وهو أنه يجب علينا تحديد سرعة اللعبة حيث أن سرعة اللعبة ستكون ثابتة خلال اللعبة إذًا ستكون خارج while loop

C++:
#include<iostream>
#include<raylib.h>
int main(){
    const int screen_width = 1270;
const int screen_height = 550;
InitWindow(screen_width, screen_height, "Sh3ll Game");
SetTargetFPS(65);//< ---(سيتم تحديث الشاشة 65 مرة في الثانية ) سرعة اللعبة تكون بتحديد كم مرة في الثانية سيتم تحديث الشاشة وهذا ما سيتحكم بسلاسة اللعب بواسطة
    while (!WindowShouldClose() ) {
    BeginDrawing();
 EndDrawing();
}
    CloseWindow();
return 0;
}

ماذا لو لم نستعمل SetTargetFPS(65) في هذه الحالة؟ سيقوم كل حاسوب بتنفيذ اللعبة بأعلى سرعة ممكنة
إذًا ستختلف سرعة اللعبة من حاسوب لآخر حسب إمكانياته , لكن بتحديد السرعة سنضمن أن سرعة اللعبة ثابتة بالنسبة لجميع الحواسيب



  • الرسم: تتيح raylib رسم أشكال أساسية كالدائرة , مستطيل, خط ... إلخ , سنستعمل الدائرة بما أننا بحاجة لرسم الكرة
C++:
void DrawCircle(int center1,int center2,float radius,Color color)// تقوم هذه الدالة برسم دائرة
//    center1: Xتمثل احداثيات الرسم بالنسبة للمحور
//center2:Y تمثل احداثيات الرسم بالنسبة للمحور
//radius: نصف قطر الدائرة والذي يحدد حجمها
//Color: لون الدائرة
أولًا أُريد أن أرسم الكرة في المنتصف سيكون الرسم بالنسبة لاحداثيات X و y كما ذكرنا سابقًا , بداية الشاشة على الحافة تمثل (0,0) من ثم أبعاد الشاشة ستكون محددة من طرفكم , ولإيجاد المنتصف يكفي أن نقوم بعملية قسمة بسيطة.

C++:
DrawCircle(screen_width / 2, screen_height / 2, 20, WHITE);
// اخترت RADIUS =20
// بالنسبة للالوان تكتب CAPITAL

النتيجة بعد تنفيذ الكود:
السرعة في هذه المرحلة بدون تأثير لأننا لم نقم بالـ Animation بعد



والآن فالنرسم المجاذيف: بما أن المجاديف تأخذ شكل مستطيل سنستعمل دالة الرسم الخاصة بالمستطيل

C++:
 DrawRectangle(int px,int py,int width,int height,Color clor);
//px=position x
//py = position y
سنقوم برسمه في المنتصف:
C++:
DrawRectangle(0,screen_height / 2,35,120,WHITE);

النتيجة :

ملاحظة: إنه لا يظهر في منتصف الشاشة والسبب أن المستطيل يُحَدد من الحافة العلوية له



فالحافة العلوية المحددة بالنقطة الحمراء هي أساسًا في المنتصف لكن هل نحن نريد المستطيل أن يتموضع في منتصف الشاشة ؟
في هذه الحالة يجب أن يكون منتصف المستطيل في منتصف الشاشة

هذه أحداثيات النقطة الصفراء:
كود:
exactposition=(screen_height / 2)+(Rectangle_height/2)

وبالتالي لإيجاد الأحداثيات المناسبة يجب أن تكون حافة المستطيل (النقطة الحمراء) متموضعة.
كود:
reddotpos=screen_height / 2-Rectangle_height/2;
كود:
 DrawRectangle(0, screen_height / 2- 60, 35, 120, WHITE);
 //rectangleheight=120
// 120/2=60;

لا أُريد للمجذاف أن يكون ملتصقًا تمامًا بالشاشة سأبعده بعض ملمترات:
كود:
 DrawRectangle(10, screen_height / 2- 60, 35, 120, WHITE);


والآن لننتقل للمجذاف الثاني : يجب أن يتموضع يمين الشاشة


كود:
DrawRectangle(screen_width-45, screen_height / 2 - 60, 35, 120, WHITE);


يتبقي لنا الشي الوحيد في الرسم وهو الفاصل ببساطة وبنفس الخطوات سيتموضع في وسط الشاشة إذًا :


C++:
 // DrawLine(int startpox,int startposy ,int endposx, int endposy, Color color)
DrawLine(screen_width / 2, 0, screen_width / 2, screen_height, WHITE);


وهكذا أتممنا الجزء الخاص بالرسم سنقوم في المرات المقبلة إن شاء الله بال Animation والتعديل عليه.

تلخيص الكود
C++:
#include <iostream>
#include<raylib.h>

int main()
{
    const int screen_width = 1270;
    const int screen_height = 550;
    InitWindow(screen_width, screen_height, "Sh3ll Game");
    SetTargetFPS(65);
    while (!WindowShouldClose()) {
        BeginDrawing();
        DrawLine(screen_width / 2, 0, screen_width / 2, screen_height, WHITE);
        DrawCircle(screen_width / 2, screen_height / 2, 20, WHITE);
        DrawRectangle(10, screen_height / 2- 60, 35, 120, WHITE);
        DrawRectangle(screen_width-45, screen_height / 2 - 60, 35, 120, WHITE);
 
        EndDrawing();
 
    }
    CloseWindow();
    return 0;
}
دمتم بخير 🦋
شرح بسيط وجميل لكن لا ينصح باستخدام raylib.h بكل اختصار لعدة اسباب ابرزها انها تعتبر بسيطة ينصح قلبها بدراسة Computer Graphics وبعدها OpenGL
 
  • Love
التفاعلات: Mina

عودة
أعلى أسفل