Tirages pondérés
Fait partie de la section Règles du jeu du Journey Pygame de Coddy. Leçon 18 sur 29.
Un jeu est plus intéressant lorsque tout ce qui tombe n’est pas identique. Ici, la moitié des objets qui tombent sont de petites pierres, certains sont de grosses pierres et quelques-uns sont des gemmes valant 5 points. random.choice choisit chaque élément aussi souvent que les autres. random.choices prend des weights, qui indiquent la fréquence d’apparition de chacun :
def pick_kind():
return random.choices(["small", "big", "gem"], weights=[5, 3, 2])[0]Les poids 5, 3 et 2 totalisent 10, donc, sur 10 objets qui tombent, environ 5 sont de petites pierres, 3 de grosses pierres et 2 des gemmes. Les poids sont des proportions, pas des pourcentages : [50, 30, 20] signifie la même chose.
random.choices peut faire plusieurs choix à la fois, donc il renvoie toujours une liste, même pour un seul choix. [0] en extrait l’élément.
Chaque type devient ensuite un Rect différent. Les gemmes sont placées dans leur propre liste, gems, car en toucher une est une bonne nouvelle. Le code de départ sait déjà déplacer, dessiner et attraper les gemmes ; aucune n’est encore lâchée.
Défi
Moyen- Écrivez
pick_kind(): elle renvoie"small","big"ou"gem"avec des poids de 5, 3 et 2. - À l’événement
SPAWN, faites tomber ce qu’il sélectionne : un petit rocher de 24 sur 24, un gros rocher de 40 sur 40 (x de 0 à 440, y -40), ou une gemme de 20 sur 20 (x de 0 à 460, y -20), ajoutée àgems.
Essayez vous-même
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()
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Règles du jeu
Entraînez-vous par vous-même : Playground Pygame