Menu
CoddyTech

حمّله عند البدء

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

تم حفظ الرقم القياسي؛ والآن اقرأه مجددًا عند بدء اللعبة. يحوّل int(file.read()) نص الملف إلى رقم. في المرة الأولى لا يكون هناك ملف، ويوقف open البرنامج مع FileNotFoundError.

يلتقط try وexcept هذا الخطأ وينفّذان شيئًا آخر بدلًا من ذلك:

def load_best():
    try:
        with open("highscore.txt") as file:
            return int(file.read())
    except FileNotFoundError:
        return 0


best = load_best()

ينفّذ Python كتلة try. إذا أثار open الخطأ FileNotFoundError، ينتقل إلى كتلة except ويُرجع 0. أما أي خطأ آخر، فيظل يوقف البرنامج، وهذا ما تريده: فهو خطأ حقيقي في البرنامج.

يفتح open("highscore.txt") الملف للقراءة عند عدم تحديد وضع.

على جهاز كمبيوتر، أغلق اللعبة وشغّلها مجددًا، وسيظهر أفضل رقم من المرة السابقة على شاشة انتهاء اللعبة الأولى. وفي المتصفح، يحدث الأمر نفسه في كل مرة تضغط فيها على «العب»، إلى أن يُعاد تحميل الصفحة.

challenge icon

التحدي

متوسط
  1. اكتب load_best(): تُعيد الرقم الموجود في highscore.txt، أو 0 إذا لم يكن هذا الملف موجودًا.
  2. عيّن best = load_best() بدلًا من best = 0.

جرّب بنفسك

import random
import pygame

pygame.init()
screen = pygame.display.set_mode((480, 360))
pygame.display.set_caption("Meteor Dodge")
clock = pygame.time.Clock()
heart = pygame.image.load("assets/images/heart.png").convert_alpha()
heart_empty = pygame.image.load("assets/images/heart_empty.png").convert_alpha()
font = pygame.font.Font("assets/fonts/pixel.ttf", 24)
big_font = pygame.font.Font("assets/fonts/pixel.ttf", 48)
WHITE = (240, 240, 240)
PLATE = (60, 60, 90)
POINT = pygame.USEREVENT + 1
SPAWN = pygame.USEREVENT + 2


def reset():
    global player, rocks, score, lives
    player = pygame.Rect(220, 300, 40, 40)
    rocks = []
    score = 0
    lives = 3
    pygame.time.set_timer(POINT, 1000)
    pygame.time.set_timer(SPAWN, 800)


def draw_menu():
    screen.fill((30, 30, 46))
    title = big_font.render("Meteor Dodge", True, WHITE)
    title_rect = title.get_rect(center=(240, 140))
    pygame.draw.rect(screen, PLATE, title_rect.inflate(24, 12))
    screen.blit(title, title_rect)
    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)
    for rock in rocks:
        pygame.draw.rect(screen, (235, 80, 80), rock)
    score_text = font.render(f"{score:05}", True, WHITE)
    score_rect = score_text.get_rect(topright=(470, 10))
    pygame.draw.rect(screen, PLATE, score_rect.inflate(12, 8))
    screen.blit(score_text, score_rect)
    for i in range(3):
        if i < lives:
            screen.blit(heart, (10 + i * 40, 10))
        else:
            screen.blit(heart_empty, (10 + i * 40, 10))


def play_frame():
    global rocks, lives, state, best
    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())

    kept = []
    for rock in rocks:
        rock.y += 3
        if rock.colliderect(player):
            lives -= 1
        elif rock.top <= 360:
            kept.append(rock)
    rocks = kept
    if lives <= 0:
        state = "over"
        best = max(best, score)
        with open("highscore.txt", "w") as file:
            file.write(str(best))
    draw_game()


def draw_over():
    draw_game()
    message = big_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)))
    best_text = font.render(f"Best: {best}", True, WHITE)
    screen.blit(best_text, best_text.get_rect(center=(240, 240)))


reset()
state = "menu"
best = 0

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == POINT and state == "play":
            score += 1
        if event.type == SPAWN and state == "play":
            rocks.append(pygame.Rect(random.randint(0, 456), -24, 24, 24))
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RETURN and state == "menu":
                reset()
                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()

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

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