Menu
CoddyTech

دالة واحدة لكل حالة

جزء من قسم قواعد اللعبة في رحلة Pygame على Coddy. الدرس 5 من 29.

كانت الحلقة تجمع بين ثلاث شاشات، وكانت كل حالة جديدة ستضيف طبقة أخرى من if داخل الرسم والتحديث. أما الملف المبدئي فيمنح كل حالة دالتها الخاصة، وتختار الحلقة إحداها:

if state == "menu":
    draw_menu()
elif state == "play":
    play_frame()
else:
    draw_over()

تحرّك play_frame() العناصر، وتتحقق من الاصطدام، وترسم. أما draw_menu() وdraw_over() فترسمان فقط. تعرض شاشة انتهاء اللعبة اللعبةَ مجمّدةً أسفل رسالتها، لذا تستخدم كلتاهما الدالة المشتركة draw_game() لرسم اللاعب والصخرة والنتيجة.

الدالة التي تغيّر الحالة أو النتيجة تحتاج إلى تضمينهما بعد global:

def play_frame():
    global score, state

تحريك player.x لا يحتاج إلى global: فهو يغيّر كائن Rect، ولا يعيّن كائنًا جديدًا.

بهذا التصميم، تتكوّن الحالة الجديدة من دالة واحدة وعبارة elif واحدة. أضف شاشة إيقاف مؤقت بهذه الطريقة.

challenge icon

التحدي

متوسط
  1. أضف حالة "paused": يؤدي الضغط على P أثناء اللعب إلى الإيقاف المؤقت، ويؤدي الضغط على P مرة أخرى إلى العودة إلى اللعب.
  2. اكتب draw_paused(): تعرض اللعبة المتوقفة مؤقتًا، مع ظهور Paused في المنتصف عند (240, 160).
  3. استدعِها من الحلقة عندما تكون الحالة "paused"، مع إضافة elif أخرى.

جرّب بنفسك

import random
import pygame

pygame.init()
screen = pygame.display.set_mode((480, 360))
pygame.display.set_caption("Meteor Dodge")
clock = pygame.time.Clock()
font = pygame.font.Font(None, 32)
WHITE = (240, 240, 240)


def reset():
    global player, rock, score
    player = pygame.Rect(220, 300, 40, 40)
    rock = pygame.Rect(random.randint(0, 456), -24, 24, 24)
    score = 0


def draw_menu():
    screen.fill((30, 30, 46))
    title = font.render("Meteor Dodge", True, WHITE)
    screen.blit(title, title.get_rect(center=(240, 140)))
    hint = font.render("Press Enter to play", True, WHITE)
    screen.blit(hint, hint.get_rect(center=(240, 200)))


def draw_game():
    screen.fill((30, 30, 46))
    pygame.draw.rect(screen, (255, 196, 0), player)
    pygame.draw.rect(screen, (235, 80, 80), rock)
    score_text = font.render(f"Score: {score}", True, WHITE)
    screen.blit(score_text, (10, 10))


def play_frame():
    global score, state
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        player.x -= 6
    if keys[pygame.K_RIGHT]:
        player.x += 6
    player.clamp_ip(screen.get_rect())

    rock.y += 4
    if rock.top > 360:
        rock.y = -24
        rock.x = random.randint(0, 456)
        score += 1
    if rock.colliderect(player):
        state = "over"
    draw_game()


def draw_over():
    draw_game()
    message = font.render("Game over", True, WHITE)
    screen.blit(message, message.get_rect(center=(240, 160)))
    hint = font.render("Press R to play again", True, WHITE)
    screen.blit(hint, hint.get_rect(center=(240, 200)))


reset()
state = "menu"

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RETURN and state == "menu":
                state = "play"
            elif event.key == pygame.K_r and state == "over":
                reset()
                state = "play"

    if state == "menu":
        draw_menu()
    elif state == "play":
        play_frame()
    else:
        draw_over()
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس قواعد اللعبة

تدرّب بنفسك: Playground لـ Pygame