القائمة الرئيسية

الصفحات

بايثون 20 عمل لعبة ping pong (باستخدام مكتبة turtle )

 

المحاضرة عشرون

عمل لعبة ping pong (باستخدام مكتبة turtle )



انشاء لعبة ping pong لاعبين مع تحكم من خلال keyboard حيث يمكن لكل لاعب التحكم بالعبة من خلال ازرار محددة من لوحة المفاتيح حيث سيتم مراجعة الأساسيات في المحاضرات السابقة كذلك سنتعلم محاور جديدة ومهمة من مكتبة turtle

لتبسيط الكود البرمجي سنقوم بتجزيئه وتوضيح كل جزء


أولا استدعاء المكاتبة

نقوم باستدعاء المكتبة وانشاء متغير يحمل القيمة المنطقية True يمثل حلة تشغيل اللعبة

import turtle

game_on=True

ثانيا انشاء لوحة الرسم

لأنشاء لوحة رسم نقوم بأنشاء كائن من الكلاس screen ثم نقوم بتعديل خواصه

حيث يمكن تغير قيم العنوان الرئيسي من خلال الخاصية title() ويمكن تغير زمن التأخير من خلال الخاصية tracer()

window = turtle.Screen()

window.title("Ping Pong ")

window.setup(width=800, height=600)

window.tracer(0) 

window.bgcolor(.1, .3, .1)

ثالثا انشاء الكرة

لأنشاء الكرة نقوم بأنشاء مؤشر جدد من خلال الكلاس Turtle() ونقوم بتغير خواصه

لتغير شكل أي مؤشر في turtle  نستخدم الخاصية shape()

لتغير حجم الوشر نستخدم الخاصية shapesiz()  

نستخدم اخر سطرين لتحريك الكرة

# ball

ball = turtle.Turtle()

ball.speed(0) 

ball.shape("circle")

ball.color("white")

ball.shapesize(stretch_len=1, stretch_wid=1)

ball.goto(x=0, y=0) 

ball.penup() 

ball_dx, ball_dy = 1, 1

ball_speed = .5

رابعا انشاء الخط الوسطي

# center line

center_line = turtle.Turtle()

center_line.speed(0)

center_line.shape("square")

center_line.color("white")

center_line.shapesize(stretch_len=.1, stretch_wid=25)

center_line.penup()

center_line.goto(0, 0)

خامسا اشاء الاعب الأول

# player1

player1 = turtle.Turtle()

player1.speed(0)

player1.shape("square")

player1.shapesize(stretch_len=1, stretch_wid=5)

player1.color("blue")

player1.penup()

player1.goto(x=-350, y=0)

سادسا انشاء الاعب الثاني

# player2

player2 = turtle.Turtle()

player2.speed(0)

player2.shape("square")

player2.shapesize(stretch_len=1, stretch_wid=5)

player2.color("red")

player2.penup()

player2.goto(x=350, y=0)

سابعا انشاء النص

انشاء نص لأظهار النتيجة

# score text

score = turtle.Turtle()

score.speed(0)

score.color("white")

score.penup()

score.goto(x=0, y=260)

score.write("Player1: 0 Player2: 0", align="center",

            font=("Courier", 14, "normal"))

score.hideturtle() 

p1_score, p2_score = 0, 0

ثامنا التحريك

لغرض تحريك الاعبين نقوم بأنشاء دالتين لكل لاعب حيث نقوم بالإضافة الى الموقع الحالي للاعب او الطرح منه لغرض التحريك للأعلى او الأسفل كذلك ننشئ دلة close لغرض اغلاق اللعبة بدون أخطاء وسيتم توضيح هذه النقطة بشكل مفصل في الفقرات القادمة ان شاء الله تعالى

# Players Movement ====================

players_speed = 20

 

 

def p1_move_up():

    player1.sety(player1.ycor() + players_speed)

 

 

def p1_move_down():

    player1.sety(player1.ycor() - players_speed)

 

 

def p2_move_up():

    player2.sety(player2.ycor() + players_speed)

 

 

def p2_move_down():

    player2.sety(player2.ycor() - players_speed)

def close():

    global game_on

    game_on=False

تاسعا التحكم

يمكن استقبال ادخال المستخدم في مكتبة turtle من خلال احدى خصائص لوحة الرسم وهي listen()

# Get users inputs (Key Bindings)

window.listen()

window.onkeypress(p1_move_up, "w") 

window.onkeypress(p1_move_down, "s")

window.onkeypress(p2_move_up, "Up")

window.onkeypress(p2_move_down, "Down")

window.onkeypress(close, "e")

عاشرا الحلقة التكرارية الرئيسية

نقوم بأنشاء الحلقة التكرارية الرئسية للبرنامج

نقوم بتحريك الكرة من خلال إضافة المتغيرات التي انشأناها في الفقرة ثالثا الى موقع الكرة الحالي

while game_on:

    window.update()

 

    # ball movement

    ball.setx(ball.xcor() + (ball_dx * ball_speed))

    ball.sety(ball.ycor() + (ball_dy * ball_speed))

أحدى عشر التصادم

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

# ball & borders collisions

    if(ball.ycor() > 290):  

        ball.sety(290)

        ball_dy *= -1 

 

    if(ball.ycor() < -290):  

        ball.sety(-290)

        ball_dy *= -1 

 

    # ball & players collisions =====================

    # collision with player 1

    if ball.xcor() < -340 and ball.xcor() > -350 and ball.ycor() > (player1.ycor()-60) and ball.ycor() < (player1.ycor()+60):

        ball.setx(-340)

        ball_dx *= -1

 

    # collision with player 2

    if ball.xcor() > 340 and ball.xcor() < 350 and ball.ycor() > (player2.ycor()-60) and ball.ycor() < (player2.ycor()+60):

        ball.setx(340)

        ball_dx *= -1

اثنى عشر احتساب الاهداف

داخل الحلقة التكرارية الرئيسية نقوم بتحديث النتيجة وتسجيل الأهداف بعد التحقق من حدوثها ثم نعيد الكرة الى المنتصف ونعكس اتجاهها بعد تسجيل هدف جديد

# score handling

    if(ball.xcor() > 390):

        ball.goto(0, 0)

        ball_dx *= -1  # invert X direction

        score.clear()

        p1_score += 1

        score.write(f"Player1: {p1_score} Player2: {p2_score}", align="center",

                    font=("Courier", 14, "normal"))

 

    if(ball.xcor() < -390):

        ball.goto(0, 0)

        ball_dx *= -1  # invert X direction

        score.clear()

        p2_score += 1

        score.write(f"Player1: {p1_score} Player2: {p2_score}", align="center",

                    font=("Courier", 14, "normal")(

ملاحظة للعب نستخدم الازرار

الاسم اسفل و اعلى للاعب الأول

الحرف w و s للاعب الثاني

يكون الكيبورد باللغة الإنكليزية والاحرف الصغيرة



 حل الأخطاء عند الاغلاق

والان عند اغلاق اللعبة من خلال زر الاغلاق سنلاحظ ظهور رسالة خطء بعنوان

_tkinter.TclError: invalid command name ".!canvas"

تظهر هذه الرسالة لسبب وهو عدم اغلاق الحلقة التكرارية بالشكل الصحيح حيث تبقى الحلقة التكرارية لانهائية وعند اغلاق البرنامج نجبر الحلقة على الاغلاق مما يسبب هذا الخطء

وهذا هو سبب انشاء المتغير game_on والدالة close حيث تعمل هذه الدالة على الاغلاق السليم

تحميل ملخص المحاضرة من هنا

 

تعليقات

التنقل السريع