Menu
CoddyTech

عادي أم صعب

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

دع اللاعب يختار مدى صعوبة اللعبة قبل أن تبدأ. تعرض القائمة خيارين، وتختار الأسهم أحدهما:

elif event.key == pygame.K_LEFT and state == "menu":
    difficulty = "normal"
elif event.key == pygame.K_RIGHT and state == "menu":
    difficulty = "hard"

تحرّك الأسهم نفسها اللاعب أثناء اللعب. يضمن اختبار state == "menu" الفصل بين الاستخدامين.

تُبرز القائمة الخيار المحدد، ليرى اللاعب ما الذي سيبدأ عند الضغط على Enter:

if difficulty == "normal":
    normal, hard = "> Normal <", "Hard"
else:
    normal, hard = "Normal", "> Hard <"

ثم تستخدم اللعبة difficulty حيث تُحدَّد الأرقام. في المستوى الصعب، تبدأ الصخور بسرعة 6 بكسلات في الإطار بدلًا من 3:

if difficulty == "normal":
    speed = 3 + seconds // 5
else:
    speed = 6 + seconds // 5

عيّن difficulty = "normal" مرة واحدة قبل الحلقة، وليس في reset()، حتى يحتفظ المفتاح R بالخيار.

challenge icon

التحدي

متوسط
  1. قبل الحلقة، عيّن difficulty = "normal".
  2. في القائمة، يعيّن مفتاح السهم الأيسر القيمة إلى "normal" ومفتاح السهم الأيمن إلى "hard".
  3. تعرض القائمة الخيارين في المنتصف عند (160, 260) و(320, 260): > Normal < وHard، أو Normal و> Hard <.
  4. تبدأ الصخور بسرعة 3 بكسلات لكل إطار على المستوى العادي و6 على المستوى الصعب، وتزداد السرعة بمقدار 1 كل خمس ثوانٍ.

جرّب بنفسك

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, start_time
    player = pygame.Rect(220, 300, 40, 40)
    rocks = []
    score = 0
    lives = 3
    start_time = pygame.time.get_ticks()
    pygame.time.set_timer(POINT, 1000)
    pygame.time.set_timer(SPAWN, 1000)


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
    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())

    seconds = (pygame.time.get_ticks() - start_time) // 1000
    speed = 3 + seconds // 5
    kept = []
    for rock in rocks:
        rock.y += speed
        if rock.colliderect(player):
            lives -= 1
        elif rock.top <= 360:
            kept.append(rock)
    rocks = kept
    if lives <= 0:
        state = "over"
    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)))


reset()
state = "menu"

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))
            seconds = (pygame.time.get_ticks() - start_time) // 1000
            interval = max(400, 1000 - seconds * 60)
            pygame.time.set_timer(SPAWN, interval)
        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