Menu
CoddyTech

حدث مؤقّت

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

تُكافئ النقطة الواحدة عن كل صخرة تسقط من أمامك الانتظار. لكن احتساب نقطة عن كل ثانية تصمد فيها أكثر إنصافًا. يمكن لـ pygame إرسال حدث خاص بلعبتك كل ثانية.

أنواع الأحداث هي أرقام. pygame.USEREVENT هو أول رقم يتركه pygame متاحًا لك، لذا سمِّ نوع الحدث الخاص بك انطلاقًا منه:

POINT = pygame.USEREVENT + 1
...
pygame.time.set_timer(POINT, 1000)

منذ ذلك الحين، يصل حدث POINT كل 1000 ms مع الأحداث الأخرى، وتعالجه كما تعالج ضغطة مفتاح:

if event.type == POINT and state == "play":
    score += 1

يظل المؤقّت يعمل في القائمة وعلى شاشة انتهاء اللعبة، لذا تحقّق من الحالة. يؤدي استدعاء set_timer مرة أخرى إلى إعادة تشغيله، ولهذا يوضع في reset(): تنتظر كل لعبة جديدة ثانية كاملة قبل الحصول على أول نقطة.

challenge icon

التحدي

متوسط
  1. أضف POINT = pygame.USEREVENT + 1 بعد الألوان.
  2. في reset()، ابدأ مؤقّتًا يرسل POINT كل 1000 مللي ثانية.
  3. عند وقوع حدث POINT أثناء اللعب، أضف 1 إلى النقاط.
  4. لم تعد الصخور التي تسقط إلى أسفل تمنح نقاطًا.

جرّب بنفسك

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, hit_time
    player = pygame.Rect(220, 300, 40, 40)
    rock = pygame.Rect(random.randint(0, 456), -24, 24, 24)
    score = 0
    lives = 3
    hit_time = -2000


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))
    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)
    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, hit_time
    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
    now = pygame.time.get_ticks()
    if rock.colliderect(player) and now - hit_time > 1000:
        hit_time = now
        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()
quiz iconاختبر نفسك

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

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

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