مضى على الشبكة و يوم من العطاء.

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

MinaMina is verified member.

{ | مشرف قسم لغات البرمجة | }
.:: طاقم المشرفين ::.
.:: كاتب تقني ::.

السمعة:

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

بعد أن قمنا بتعلم أساسيات الرسم يتبقى لنا التحريك (Animation)
  • تحريك الكرة
بما أننا ذكرنا سابقًا أن للكرة أحداثيات بالنسبة للمعلمين (x,y) فهي حتما تمتلك سرعة بالنسبة للمحور X وسرعة بالنسبة للمحور Y
ومن أجل تحريكها يجب تحديث سرعتها بالنسبة لكِلا المعلمين
C++:
#include <iostream>
#include<raylib.h>

// بما أن للكرة خصائص فسنحتاج لانشاء كلاس
class Ball {
public:
    float x, y;
    int speed_x, speed_y;
    int radius;
    void Draw() {//<----- نفس دالة الرسم التي استعملناها سابقا
        DrawCircle(x,y, radius, WHITE);//xوy احداثيات الرسم للكرة
    }

    void Move() {//<--- اضفنا هذه الدالة من اجل تحديث سرعة الكرة
        x += speed_x;//<--  Xسنقوم في كل مرة باضافة عدد معين من البكسلات بالنسبة للمحور
        y+= speed_y;//<--  Yنفس الامر بالنسبة للمحور
    }
};
Ball ball;//<--انشاء الكرة
int main()
{
    const int screen_width = 1270;
    const int screen_height = 550;
    InitWindow(screen_width, screen_height, "Sh3ll Game");
    SetTargetFPS(65);
    ball.x = screen_width / 2;// اعطاء القيم المناسبة للكرة التي قمنا باختيارها في المرة السابقة
    ball.y= screen_height / 2;
    ball.radius = 20;
    ball.speed_x = 5;
    ball.speed_y = 5;

    while (!WindowShouldClose()) {
        BeginDrawing();
        ball.Move();//نحدث
        DrawLine(screen_width / 2, 0, screen_width / 2, screen_height, WHITE);
        ball.Draw();//ثم نرسم
  
        DrawRectangle(10, screen_height / 2- 60, 35, 120, WHITE);
        DrawRectangle(screen_width-45, screen_height / 2 - 60, 35, 120, WHITE);
 
        EndDrawing();
 
    }
    CloseWindow();
    return 0;
}

النتيجة:



نلاحظ أن الكرة تتحرك لكن تترك خلفها أثر الموقع السابق, السبب في ذلك يعود إلى أن تنفيذ الحلقة يكون تنفيذ تسلسلي في كل مرة تقوم بتنفيذ الكود بشكل متتالي أمر بعد أمر بالترتيب المكتوب ولا تقوم بمحو ما سبقه مما قامت بتفيذه.

إذًا نحتاج في كل مرة قبل أن نبدأ برسم المواقع الجديدة وأن نمحو ما قمنا برسمه سابقًا

C++:
 ClearBackground(BLACK);//<-- تاخذ هذه الدالة اللون الذي تقوم بالمحو به نختار الاسود

النتيجة:
قد قمت بتبطيئ السرعة كي استطيع أن القطها لكم لأنها سريعة.




ملاحظة: إن الكرة تتحرك إلى خارج إطار النافذة وبذلك يجب علينا تحديد تحركها !

الشرط سيكون عند ملامسة الكرة لإحدى حواف الشاشة يجب عليها تغيير مسارها

demo12.PNG

إذا ارتطمت الكرة بالشاشة يجب عليها تغيير مسارها( عكس اتجاهها)
C++:
    void Move() {
        x += speed_x;
        y+= speed_y;
        if (y + radius >= GetScreenHeight() || y-radius<=0) {//نتاكد من الارتطام اسفل واعلى الشاشة
           speed_y *= -1;// تغير الاتجاه بعكس المسار

        }
        if (x + radius >= GetScreenWidth()|| x - radius <= 0) {//نفس الامر بالنسبة لجانبي الشاشة
            speed_x *= -1;
        }
    }
};

النتيجة :



بالنسبة للمجاذيف:
  • مجذاف اللاعب:
بما أنه هو كذلك له خصائص كالحركة فسنقومم أولًا بإنشاء كلاس له ولكن حركته متعلقة فقط بالمحور Y , إذًا سنهمل حركته بالنسبة للمحور X
كذلك , حركة اللاعب متعلقة بالضغط على القفلين UP أو DOWN إذًا سيكون هذا شرطنا .
C++:
class Paddle {
public:
    float x, y,width, height;//<---   كنا قد حددناها سابقا XY  بالنسبة لاحداثيات الرسم
    int speed;
    void Draw() {
        DrawRectangle(x, y, width, height, WHITE);
    }
     void Move() {
     if (IsKeyDown(KEY_UP)) {//<-----    اذا ضغط الاعب على القفل ,↑ يجب ان نحرك المجذاف للاعلى بالتالي قيمته في المحور ستنقص
         y -= speed;
     }
     if (IsKeyDown(KEY_DOWN)) { //اذا ضغط اللاعب على القفل ↓يجب ان نحركه نح الاسفل بالتالي ستزيد قيمته بالنسبة للمحور
         y += speed;
     }
 }

};

[SIZE=5]لا ننسى ان نراقب الحواف اثناء التحريك[/SIZE]
[CODE=cpp]protected:
    void Movement_limit() {
        if (y <= 0) {//نراقب اذا ارتطمت بالحافة العلوية
            y = 0;// نرجعها للبداية
        }

        if (y + height >= GetScreenHeight()) {//كذلك الامر بالنسبة للحافة السفلية
            y = GetScreenHeight() - height;
        }
    }

النتيجة :



  • تحريك مجذاف CPU:
بما أننا حددنا مسبقًا كلاس المجذاف؛ يمككننا فقط وراثة هذا الكلاس بالنسبة للمجذاف الخاص بال CPU؛ لكن مع إضافة الدالة التي تسمح بتحريك المجذاف بشكل أوتوماتيكي
كيف يجب أن يعمل هذا المجذاف أولًا :
ببساطة سنعتمد على هذه الخوارزمية
demo13.PNG

إذًا نحن في كل لحظة بحاجة لمعرفة قيمة y للكرة كي نستطيع تحريك المجذاف على أساسه .

C++:
class CPU_paddle :public Paddle{//<--- عرفنا الكلاس على انها ترث
public:
    void Move(int ball_y) {//بماننا بحاجة لمعرفة احداقية الكرة في كل لحظة اذن سنستقبها كعامل من الدالة الاساسية
        if (y + height / 2 > ball_y) {//الجزء المشروح في الرسم السابق
            y -= speed;
        }
        else {
            y += speed;
        }
        Movement_limit();//  ننادي على الدالة فقط للتاكد من ارتطام الحواف
    }

};

النتيجة :



  • يبقى لنا فقط تحديد الإرتطام مع المجذاف
C++:
CheckCollisionCircleRec(Vector2 center,float raduis,Rectangle rec);
    // للدائرة x,yهذه الدلة تتحق من ارتطام الدائرة بالمستطيل تاخذ ال عامل هما
    // العامل الثاني تاخذ نصف قطر الدائرة
    //العامل الاخير تاخذ خصائص المستطيل
    CheckCollisionCircleRec(Vector2 {ball.x,ball.y},ball.radius,Rectangle{player.x,player.y,player.width,player.height});
في حال تحقق الارتطام سواء بالنسبة لمجذاف اللاعب او مجذافCPU نقوم بعكس الاتجاه تماما كما فعلنا في السابق
C++:
 if (CheckCollisionCircleRec(Vector2{ ball.x,ball.y }, ball.radius, Rectangle{ player.x,player.y,player.width,player.height })) {
     ball.speed_x *= -1;
}

 if (CheckCollisionCircleRec(Vector2{ ball.x,ball.y }, ball.radius, Rectangle{cpu.x,cpu.y,cpu.width,cpu.height })) {
     ball.speed_x *= -1;
 }



  • بالنسبة لتسجيل النقاط (Scoring)
C++:
//سنقوم بنتعريف متغييرن
int scorePlayer=0,scoreCpu=0;//في البداية رصيد كلا اللاعبين0
// متى ياخذ  اللعب نقطة اذا تحقق شرط الارتطام مع  جانبي الحائط الذي كتبناه سابقا اذن
 if (x + radius >= GetScreenWidth()|| x - radius <= 0) {
     speed_x *= -1;
 }
//--->سنقوم بفصل الشرط المركب الى شرطين
if (x + radius >= GetScreenWidth()) {
 
    scoreCpu++;
}
    if( x - radius <= 0) {
 
    scorePlayer++;
}
///////////////////////////////////
DrawText(char text, int posX, int posY, int fontsize, color);//<----  الدالة المسؤولة عن العرض على الشاشة

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

C++:
//Ballننشئ هذه الدالة داخل كلاس
//ونقوم باستعمالها في كل مرة تترطم الكرة في احدى الجانبين
void Return_Ball() {
    x = GetScreenWidth() / 2;
    y = GetScreenHeight() / 2;
    int orientation[2] = { -1,1 };//ناخذ اتجاهين فقط
    speed_x *= orientation[GetRandomValue(0, 1)];// هذه الدالة تقوم باختيار قيمة عشوائية من احدى قيم الجدول يا اما 1 يا اما -1
    speed_y *= orientation[GetRandomValue(0, 1)];
}

النتيجة :



وهكذا قمنا بالمرور على كامل النقاط تقريبًا يتبقى لنا فقط التصميم وعداد الوقت.

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

int scorePlayer = 0, scoreCpu = 0;
class Ball {
public:
    float x, y;
    int speed_x, speed_y;
    int radius;
    void Draw() {
        DrawCircle(x,y, radius, WHITE);
    }

    void Move() {
        x += speed_x;
        y+= speed_y;
        if (y + radius >= GetScreenHeight() || y-radius<=0) {
           speed_y *= -1;

        }
        if (x + radius >= GetScreenWidth()) {
        
            scoreCpu++;
            Return_Ball();
        }
            if( x - radius <= 0) {
        
            scorePlayer++;
            Return_Ball();
        }
    }
    void Return_Ball() {
        x = GetScreenWidth() / 2;
        y = GetScreenHeight() / 2;
        int orientation[2] = { -1,1 };
        speed_x *= orientation[GetRandomValue(0, 1)];
        speed_y *= orientation[GetRandomValue(0, 1)];
    }
};

class Paddle {
protected:
    void Movement_limit() {
        if (y <= 0) {
            y = 0;
        }

        if (y + height >= GetScreenHeight()) {
            y = GetScreenHeight() - height;
        }
    }
public:
    float x, y,width, height;
    int speed;
    void Draw() {
        DrawRectangle(x, y, width, height, WHITE);
    }
    void Move() {
        if (IsKeyDown(KEY_UP)) {
            y -= speed;
        }
        if (IsKeyDown(KEY_DOWN)) {
            y += speed;
        }
        Movement_limit();
    }
 
};
class CPU_paddle :public Paddle{
public:
    void Move(int ball_y) {
        if (y + height / 2 > ball_y) {
            y -= speed;
        }
        else {
            y += speed;
        }
        Movement_limit();
    }

};

Ball ball;
Paddle player;
CPU_paddle cpu;
int main()
{
    const int screen_width = 1270;
    const int screen_height = 550;
    InitWindow(screen_width, screen_height, "Sh3ll Game");
    SetTargetFPS(65);
    ball.x = screen_width / 2;
    ball.y= screen_height / 2;
    ball.radius = 20;
    ball.speed_x = 5;
    ball.speed_y = 5;
    player.width = 35;
    player.height = 120;
    player.x = screen_width - player.width - 10;
    player.y = screen_height / 2 - player.height / 2;
    player.speed = 7;
    cpu.width = 35;
    cpu.height = 120;
    cpu.x = 10;
    cpu.y = screen_height / 2 - cpu.height / 2;
    cpu.speed = 6;

    while (!WindowShouldClose()) {
        BeginDrawing();
        ball.Move();
        player.Move();
        ClearBackground(BLACK);
        if (CheckCollisionCircleRec(Vector2{ ball.x,ball.y }, ball.radius, Rectangle{ player.x,player.y,player.width,player.height })) {
            ball.speed_x *= -1;
        }

        if (CheckCollisionCircleRec(Vector2{ ball.x,ball.y }, ball.radius, Rectangle{ cpu.x,cpu.y,cpu.width,cpu.height })) {
            ball.speed_x *= -1;
        }
        DrawLine(screen_width / 2, 0, screen_width / 2, screen_height, WHITE);
        ball.Draw();
        cpu.Draw();
        player.Draw();
        cpu.Move(ball.y);
        DrawText(TextFormat("%i",scoreCpu), screen_width / 4 - 20, 20, 80, WHITE);
        DrawText(TextFormat("%i", scorePlayer), 3*screen_width / 4 - 20, 20, 80, WHITE);

        EndDrawing();
  
    }
    CloseWindow();
    return 0;
}

دمتم بخير 🦋
 
الله يعطيكم ألف عافية 💪
ما شاء الله استمر و ننتظر الجزء الثالث
 
  • Love
التفاعلات: Mina
بسم الله الرحمن الرحيم


بعد ان قمنا بتعلم اساسيات الرسم يتبقى لنا التحريك (Animation)
  • تحريك الكرة :​
بما اننا ذكرنا سابقا ان للكرة احداثيات بالنسبة للمعلمين (x,y) فهي حتما تمتلك سرعة بالنسبة للمحور X وسرعة بالنسبة للمحور Y
ومن اجل تحريكها يجب تحديث سرعتها بالنسبة لكِلا المعلمين

C++:
#include <iostream>
#include<raylib.h>
// بمان للكرة خصائص فسنحتاج لانشاء كلاس
class Ball {
public:
    float x, y;
    int speed_x, speed_y;
    int radius;
    void Draw() {//<----- نفس دالة الرسم التي استعملناها سابقا
        DrawCircle(x,y, radius, WHITE);//xوy احداثيات الرسم للكرة
    }

    void Move() {//<--- اضفنا هذه الدالة من اجل تحديث سرعة الكرة
        x += speed_x;//<--  Xسنقوم في كل مرة باضافة عدد معين من البكسلات بالنسبة للمحور
        y+= speed_y;//<--  Yنفس الامر بالنسبة للمحور
    }
};
Ball ball;//<--انشاء الكرة
int main()
{
    const int screen_width = 1270;
    const int screen_height = 550;
    InitWindow(screen_width, screen_height, "Sh3ll Game");
    SetTargetFPS(65);
    ball.x = screen_width / 2;// اعطاء القيم المناسبة للكرة التي قمنا باختيارها في المرة السابقة
    ball.y= screen_height / 2;
    ball.radius = 20;
    ball.speed_x = 5;
    ball.speed_y = 5;

    while (!WindowShouldClose()) {
        BeginDrawing();
        ball.Move();//نحدث
        DrawLine(screen_width / 2, 0, screen_width / 2, screen_height, WHITE);
        ball.Draw();//ثم نرسم
   
        DrawRectangle(10, screen_height / 2- 60, 35, 120, WHITE);
        DrawRectangle(screen_width-45, screen_height / 2 - 60, 35, 120, WHITE);
 
        EndDrawing();
 
    }
    CloseWindow();
    return 0;
}
النتيجة:



مشاهدة المرفق 9594



نلاحظ ان الكرة تتحرك لكن تترك خلفها اثر الموقع السابق


السبب في ذلك يعود ان تنفيذ الحلقة يكون تنفيذ تسلسلي في كل مرة تقوم بتنفيذ الكود بشكل متتالي امر بعد امر بالترتيب المكتوب ولا تقوم بمحو ماسبقه مما قامت بتفيذه


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


C++:
 ClearBackground(BLACK);//<-- تاخذ هذه الدالة اللون الذي تقوم بالمحو به نختار الاسود
النتيجة:


(قد قمت بتبطيئ السرعة كي استطيع ان القطها لكم لانها سريعة)
مشاهدة المرفق 9595



ملاحظة 2: ان الكرة تتحرك الى خارج اطار النافذة وبذلك يجب علينا تحديد تحركها !

الشرط سيكون عند ملامسة الكرة لاحدى حواف الشاشة يجب عليها تغيير مسارها
مشاهدة المرفق 9596

اذا ارتطمت الكرة بالشاشة يجب عليها تغيير مسارها( عكس اتجاهها)
C++:
    void Move() {
        x += speed_x;
        y+= speed_y;
        if (y + radius >= GetScreenHeight() || y-radius<=0) {//نتاكد من الارتطام اسفل واعلى الشاشة
           speed_y *= -1;// تغير الاتجاه بعكس المسار

        }
        if (x + radius >= GetScreenWidth()|| x - radius <= 0) {//نفس الامر بالنسبة لجانبي الشاشة
            speed_x *= -1;
        }
    }
};
النتيجة :



مشاهدة المرفق 9597


بالنسبة للمجاذيف :
مجذاف اللاعب :
بمانه هو كذلك له خصائص كاحركة فسنقومم اولا بانشاء كلاس له ولكن حركته متعلقة فقط بالمحور Y اذن سنهمل حركته بالنسبة للمحور X
كذلك حركة اللاعب متعلقة بالضغط على القفلين UP او DOWN اذن سيكون هذا شرطنا

C++:
class Paddle {
public:
    float x, y,width, height;//<---   كنا قد حددناها سابقا XY  بالنسبة لاحداثيات الرسم
    int speed;
    void Draw() {
        DrawRectangle(x, y, width, height, WHITE);
    }
     void Move() {
     if (IsKeyDown(KEY_UP)) {//<-----    اذا ضغط الاعب على القفل ,↑ يجب ان نحرك المجذاف للاعلى بالتالي قيمته في المحور ستنقص
         y -= speed;
     }
     if (IsKeyDown(KEY_DOWN)) { //اذا ضغط اللاعب على القفل ↓يجب ان نحركه نح الاسفل بالتالي ستزيد قيمته بالنسبة للمحور
         y += speed;
     }
 }

};

[SIZE=5]لا ننسى ان نراقب الحواف اثناء التحريك[/SIZE]
[CODE=cpp]protected:
    void Movement_limit() {
        if (y <= 0) {//نراقب اذا ارتطمت بالحافة العلوية
            y = 0;// نرجعها للبداية
        }

        if (y + height >= GetScreenHeight()) {//كذلك الامر بالنسبة للحافة السفلية
            y = GetScreenHeight() - height;
        }
    }
النتيجة :



مشاهدة المرفق 9600


تحريك مجذاف CPU:
بماننا حددنا مسبقا كلاس المجذاف يمككننا فقط وراثة هذا الكلاس بالنسبة للمجذاف الخاص بال CPU
لكن مع اضافة الدالة التي تسمح بتحريك المجذاف بشكل اوتوماتيكي
كيف يجب ان يعمل هذا المجذاف اولا :
ببساطة سنعتمد على هذه الخوارزمية

مشاهدة المرفق 9601

اذن نحن في كل لحظة بحاجة لمعرفة قيمة y للكرة كي نستطيع تحريك المجذاف على اساسه
C++:
class CPU_paddle :public Paddle{//<--- عرفنا الكلاس على انها ترث
public:
    void Move(int ball_y) {//بماننا بحاجة لمعرفة احداقية الكرة في كل لحظة اذن سنستقبها كعامل من الدالة الاساسية
        if (y + height / 2 > ball_y) {//الجزء المشروح في الرسم السابق
            y -= speed;
        }
        else {
            y += speed;
        }
        Movement_limit();//  ننادي على الدالة فقط للتاكد من ارتطام الحواف
    }

};
النتيجة :


مشاهدة المرفق 9603


يبقى لنا فقط تحديد الارتطام مع المجذاف
C++:
CheckCollisionCircleRec(Vector2 center,float raduis,Rectangle rec);
    // للدائرة x,yهذه الدلة تتحق من ارتطام الدائرة بالمستطيل تاخذ ال عامل هما
    // العامل الثاني تاخذ نصف قطر الدائرة
    //العامل الاخير تاخذ خصائص المستطيل
    CheckCollisionCircleRec(Vector2 {ball.x,ball.y},ball.radius,Rectangle{player.x,player.y,player.width,player.height});
في حال تحقق الارتطام سواء بالنسبة لمجذاف اللاعب او مجذافCPU نقوم بعكس الاتجاه تماما كما فعلنا في السابق
C++:
 if (CheckCollisionCircleRec(Vector2{ ball.x,ball.y }, ball.radius, Rectangle{ player.x,player.y,player.width,player.height })) {
     ball.speed_x *= -1;
}

 if (CheckCollisionCircleRec(Vector2{ ball.x,ball.y }, ball.radius, Rectangle{cpu.x,cpu.y,cpu.width,cpu.height })) {
     ball.speed_x *= -1;
 }


مشاهدة المرفق 9606


بالنسبة لتسجيل النقاط (Scoring)
C++:
//سنقوم بنتعريف متغييرن
int scorePlayer=0,scoreCpu=0;//في البداية رصيد كلا اللاعبين0
// متى ياخذ  اللعب نقطة اذا تحقق شرط الارتطام مع  جانبي الحائط الذي كتبناه سابقا اذن
 if (x + radius >= GetScreenWidth()|| x - radius <= 0) {
     speed_x *= -1;
 }
//--->سنقوم بفصل الشرط المركب الى شرطين
if (x + radius >= GetScreenWidth()) {
 
    scoreCpu++;
}
    if( x - radius <= 0) {
 
    scorePlayer++;
}
///////////////////////////////////
DrawText(char text, int posX, int posY, int fontsize, color);//<----  الدالة المسؤولة عن العرض على الشاشة
كذلك نحن بحاجة لارجاع الكرة الى منتصف الملعب في كل مرة تترطم باحدى الجانبين سيكون اختيار اتجاه الكرة عشوائي
C++:
//Ballننشئ هذه الدالة داخل كلاس
//ونقوم باستعمالها في كل مرة تترطم الكرة في احدى الجانبين
void Return_Ball() {
    x = GetScreenWidth() / 2;
    y = GetScreenHeight() / 2;
    int orientation[2] = { -1,1 };//ناخذ اتجاهين فقط
    speed_x *= orientation[GetRandomValue(0, 1)];// هذه الدالة تقوم باختيار قيمة عشوائية من احدى قيم الجدول يا اما 1 يا اما -1
    speed_y *= orientation[GetRandomValue(0, 1)];
}
النتيجة :


مشاهدة المرفق 9607


وهكذا قمنا بالمرور على كامل النقاط تقريبا يتبقى لنا فقط التصميم وعداد الوقت

تلخيص الكود:

C++:
#include <iostream>
#include<raylib.h>

int scorePlayer = 0, scoreCpu = 0;
class Ball {
public:
    float x, y;
    int speed_x, speed_y;
    int radius;
    void Draw() {
        DrawCircle(x,y, radius, WHITE);
    }

    void Move() {
        x += speed_x;
        y+= speed_y;
        if (y + radius >= GetScreenHeight() || y-radius<=0) {
           speed_y *= -1;

        }
        if (x + radius >= GetScreenWidth()) {
         
            scoreCpu++;
            Return_Ball();
        }
            if( x - radius <= 0) {
         
            scorePlayer++;
            Return_Ball();
        }
    }
    void Return_Ball() {
        x = GetScreenWidth() / 2;
        y = GetScreenHeight() / 2;
        int orientation[2] = { -1,1 };
        speed_x *= orientation[GetRandomValue(0, 1)];
        speed_y *= orientation[GetRandomValue(0, 1)];
    }
};

class Paddle {
protected:
    void Movement_limit() {
        if (y <= 0) {
            y = 0;
        }

        if (y + height >= GetScreenHeight()) {
            y = GetScreenHeight() - height;
        }
    }
public:
    float x, y,width, height;
    int speed;
    void Draw() {
        DrawRectangle(x, y, width, height, WHITE);
    }
    void Move() {
        if (IsKeyDown(KEY_UP)) {
            y -= speed;
        }
        if (IsKeyDown(KEY_DOWN)) {
            y += speed;
        }
        Movement_limit();
    }
 
};
class CPU_paddle :public Paddle{
public:
    void Move(int ball_y) {
        if (y + height / 2 > ball_y) {
            y -= speed;
        }
        else {
            y += speed;
        }
        Movement_limit();
    }

};

Ball ball;
Paddle player;
CPU_paddle cpu;
int main()
{
    const int screen_width = 1270;
    const int screen_height = 550;
    InitWindow(screen_width, screen_height, "Sh3ll Game");
    SetTargetFPS(65);
    ball.x = screen_width / 2;
    ball.y= screen_height / 2;
    ball.radius = 20;
    ball.speed_x = 5;
    ball.speed_y = 5;
    player.width = 35;
    player.height = 120;
    player.x = screen_width - player.width - 10;
    player.y = screen_height / 2 - player.height / 2;
    player.speed = 7;
    cpu.width = 35;
    cpu.height = 120;
    cpu.x = 10;
    cpu.y = screen_height / 2 - cpu.height / 2;
    cpu.speed = 6;

    while (!WindowShouldClose()) {
        BeginDrawing();
        ball.Move();
        player.Move();
        ClearBackground(BLACK);
        if (CheckCollisionCircleRec(Vector2{ ball.x,ball.y }, ball.radius, Rectangle{ player.x,player.y,player.width,player.height })) {
            ball.speed_x *= -1;
        }

        if (CheckCollisionCircleRec(Vector2{ ball.x,ball.y }, ball.radius, Rectangle{ cpu.x,cpu.y,cpu.width,cpu.height })) {
            ball.speed_x *= -1;
        }
        DrawLine(screen_width / 2, 0, screen_width / 2, screen_height, WHITE);
        ball.Draw();
        cpu.Draw();
        player.Draw();
        cpu.Move(ball.y);
        DrawText(TextFormat("%i",scoreCpu), screen_width / 4 - 20, 20, 80, WHITE);
        DrawText(TextFormat("%i", scorePlayer), 3*screen_width / 4 - 20, 20, 80, WHITE);

        EndDrawing();
   
    }
    CloseWindow();
    return 0;
}


دمتم بخير 🦋

بارك الله فيك يا مكينا على هذا العمل الجبار، استمري 🔥
 
  • Love
التفاعلات: Mina

آخر المشاركات

فانوس

رمضان
عودة
أعلى