מהירות שעולה בהדרגה
חלק מהיחידה חוקי המשחק במסלול ה-Pygame של Coddy. שיעור 15 מתוך 29.
משחק שלא משתנה אף פעם נעשה משעמם, ומשחק שמתחיל קשה מאבד שחקנים חדשים. התחילו בעדינות והקשו ככל שהשחקן מחזיק מעמד זמן רב יותר.
הזמן שעבר מאז תחילת המשחק קובע את המהירות. reset() זוכרת מתי המשחק התחיל, ובכל פריים מחושבת המהירות על סמך הזמן הזה:
seconds = (pygame.time.get_ticks() - start_time) // 1000
speed = 3 + seconds // 5seconds // 5 גדל ב-1 בכל חמש שניות, כך שסלעים נופלים בתחילה 3 פיקסלים בפריים, 4 אחרי חמש שניות, ו-5 אחרי עשר. צעדים שלמים שומרים על מהירות שהיא מספר שלם, וזה נחוץ ל-Rect: הוא שומר פיקסלים שלמים, ולכן rock.y += 3.5 יאבד את החצי.
Enter ו-R קוראים שתיהן ל-reset(), כך שהשעון מתחיל מחדש בכל משחק, בלי קשר למשך הזמן שבו התפריט הוצג.
אתגר
בינוני- בתוך
reset(), הגדר אתstart_timeל-pygame.time.get_ticks(). - בתוך
play_frame(), חשב כמהsecondsחלפו מאזstart_time, ואתspeed = 3 + seconds // 5. - הזז כל סלע כלפי מטה ב-
speedבמקום ב-3.
נסו בעצמכם
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
player = pygame.Rect(220, 300, 40, 40)
rocks = []
score = 0
lives = 3
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())
kept = []
for rock in rocks:
rock.y += 3
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 אונליין