Минимальный разрыв
Часть раздела Правила игры путешествия по Pygame на Coddy. Урок 16 из 29.
Камни падают быстрее, но всё ещё появляются каждые 800 мс. Камни, которые появляются чаще, тоже усложняют игру. Начни с интервала в одну секунду и со временем сокращай его:
interval = 1000 - seconds * 60Через 10 секунд интервал составит 400 мс, а через 17 секунд станет меньше 0, и таймер с интервалом 0 или меньше остановится. Игре нужен нижний предел: минимальный интервал, ниже которого он никогда не опускается. max возвращает большее из чисел, поэтому не позволяет интервалу стать меньше первого числа:
interval = max(400, 1000 - seconds * 60)Таймер сохраняет интервал, с которым был запущен. Чтобы изменить его, запусти таймер снова: при каждом падении камня вычисляй новый интервал и вызывай set_timer с ним. Следующий камень появится через этот интервал.
if event.type == SPAWN and state == "play":
rocks.append(...)
seconds = (pygame.time.get_ticks() - start_time) // 1000
interval = max(400, 1000 - seconds * 60)
pygame.time.set_timer(SPAWN, interval)Задание
Средне- В
reset()запусти таймерSPAWNна 1000 мс. - Каждый раз, когда падает камень, установи
interval = max(400, 1000 - seconds * 60)и снова запусти с этим значением таймерSPAWN.
Попробуйте сами
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, 800)
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))
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()
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Правила игры
Потренируйтесь самостоятельно: Песочница Pygame