Menu
CoddyTech

آمن بعد الاصطدام

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

قف تحت صخرة في هذه النسخة. لم تعد الصخرة تقفز إلى الأعلى عند اصطدامها، بل تسقط عبر اللاعب وتلمسه لعدة إطارات متتالية. كل إطار من هذه الإطارات يخصم حياة، لذا تنهي صخرة واحدة اللعبة.

تمنح ألعاب كثيرة فترة أمان قصيرة بعد الإصابة. لمعرفة المدة التي انقضت، استفسر من الساعة. تمثل pygame.time.get_ticks() عدد المللي ثانية منذ pygame.init(). تذكّر لحظة الإصابة واطرحها:

now = pygame.time.get_ticks()
if rock.colliderect(player) and now - hit_time > 1000:
    hit_time = now
    lives -= 1

ابدأ قيمة hit_time عند -2000 في reset()، لكي تُحتسب الإصابة الأولى دائمًا.

أظهر فترة الأمان بالوميض. تكون قيمة get_ticks() // 100 % 2 هي 0 لعُشر ثانية، ثم 1، ثم 0 مجددًا؛ لذا فإن رسم اللاعب عندما تكون القيمة 0 فقط يجعله يومض:

safe = pygame.time.get_ticks() - hit_time < 1000
if not safe or pygame.time.get_ticks() // 100 % 2 == 0:
    pygame.draw.rect(screen, (255, 196, 0), player)
challenge icon

التحدي

متوسط
  1. في reset()، اضبط hit_time = -2000 (وأضِفه إلى سطر global).
  2. لا تؤدي الإصابة إلى خسارة حياة إلا بعد مرور أكثر من 1000 ms منذ hit_time؛ ثم اضبط hit_time على الوقت الحالي.
  3. لمدة 1000 ms بعد الإصابة، ارسم اللاعب فقط عندما يكون pygame.time.get_ticks() // 100 % 2 == 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)


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


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

    rock.y += 4
    if rock.top > 360:
        rock.y = -24
        rock.x = random.randint(0, 456)
        score += 1
    if rock.colliderect(player):
        lives -= 1
        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 == 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()

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

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