اختيارات موزونة
جزء من قسم قواعد اللعبة في رحلة Pygame على Coddy. الدرس 18 من 29.
تكون اللعبة أكثر تشويقًا عندما لا يكون كل ما يسقط متماثلًا. هنا، نصف الأشياء الساقطة صخور صغيرة، وبعضها صخور كبيرة، والقليل منها جواهر تساوي 5 نقاط. تختار random.choice كل عنصر بالقدر نفسه من التكرار. تأخذ random.choices الوسيط weights، الذي يحدد عدد مرات ظهور كل عنصر:
def pick_kind():
return random.choices(["small", "big", "gem"], weights=[5, 3, 2])[0]مجموع الأوزان 5 و3 و2 هو 10، لذا من كل 10 أشياء ساقطة، يكون نحو 5 منها صغيرة و3 كبيرة و2 جواهر. الأوزان نسب، وليست نسبًا مئوية: [50, 30, 20] تعني الشيء نفسه.
يمكن لـrandom.choices الاختيار عدة مرات دفعة واحدة، لذلك تُرجع دائمًا قائمة، حتى عند إجراء اختيار واحد. يأخذ [0] العنصر منها.
بعد ذلك، يصبح كل نوع Rect مختلفًا. توضع الجواهر في قائمة خاصة بها، gems، لأن لمس إحداها خبر سار. يتحرك البرنامج المبدئي ويرسم الجواهر ويلتقطها بالفعل؛ لكن لا شيء يُسقط جوهرة بعد.
التحدي
متوسط- اكتب
pick_kind(): فهي تُعيد"small"أو"big"أو"gem"بأوزان 5 و3 و2. - عند
SPAWN، أسقط العنصر الذي تختاره: صخرة صغيرة بحجم 24 في 24، أو صخرة كبيرة بحجم 40 في 40 (x من 0 إلى 440، وy -40)، أو جوهرة بحجم 20 في 20 (x من 0 إلى 460، وy -20)، وأضِفها إلىgems.
جرّب بنفسك
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, gems, score, lives
player = pygame.Rect(220, 300, 40, 40)
rocks = []
gems = []
score = 0
lives = 3
pygame.time.set_timer(POINT, 1000)
pygame.time.set_timer(SPAWN, 500)
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)
for gem in gems:
pygame.draw.rect(screen, (90, 220, 120), gem)
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, gems, 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())
kept = []
for rock in rocks:
rock.y += 3
if rock.colliderect(player):
lives -= 1
elif rock.top <= 360:
kept.append(rock)
rocks = kept
kept = []
for gem in gems:
gem.y += 3
if gem.colliderect(player):
score += 5
elif gem.top <= 360:
kept.append(gem)
gems = 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))
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