سرعة تتزايد تدريجيًا
جزء من قسم قواعد اللعبة في رحلة Pygame على Coddy. الدرس 15 من 29.
تصبح اللعبة مملة إذا لم تتغير مطلقًا، واللعبة التي تبدأ بصعوبة تفقد اللاعبين الجدد. ابدأ بسهولة واجعلها أصعب كلما طال صمود اللاعب.
يحدد الوقت المنقضي منذ بدء اللعبة السرعة. يتذكر reset() وقت البدء، وتحسب كل لقطة السرعة انطلاقًا منه:
seconds = (pygame.time.get_ticks() - start_time) // 1000
speed = 3 + seconds // 5تزداد قيمة seconds // 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()
جميع دروس قواعد اللعبة
تدرّب بنفسك: Playground لـ Pygame