قائمة لعدّاء السماء
جزء من قسم قواعد اللعبة في رحلة Pygame على Coddy. الدرس 29 من 30.
تستمد Sky Runner قواعدها من هذا القسم، بدءًا بقائمة. تحتاج اللعبة الجديدة إلى إعادة كل شيء إلى حالته عند البداية، لذا ضع ذلك في reset(): عدّاء جديد، ومجموعة فارغة، والسرعة والنتيجة، وإعادة تشغيل المؤقتين كليهما.
يؤدي مفتاح المسافة الآن وظيفتين، واحدة لكل حالة:
if state == "play":
runner.jump()
elif state == "menu":
reset()
state = "play"تحتاج القائمة إلى سطرين في الوسط، وستحتاج شاشة انتهاء اللعبة إلى ثلاثة أسطر، لذا ترسم دالة صغيرة سطرًا واحدًا في المنتصف عند x 320:
def show(text, text_font, y):
picture = text_font.render(text, True, INK)
screen.blit(picture, picture.get_rect(center=(320, y)))تنتمي النتيجة إلى اللعبة، لذا لا تعرضها إلا بعد بدء اللعبة، وليس في القائمة.
التحدي
متوسطأضف قائمة إلى Sky Runner.
- اكتب
reset()للعدّاء والمجموعة وspeedوscoreوالمؤقّتين؛ واستدعِها قبل الحلقة واضبطstate = "menu". - في القائمة، استخدم
show()لعرضSky Runnerبخطbig_fontوعبارةPress Space to start؛ واعرض النتيجة خارج القائمة فقط. - عند الضغط على مفتاح المسافة في القائمة، استدعِ
reset()واضبطstate = "play".
اضغط «العب»: يبدأ الضغط على مفتاح المسافة جولة. ثم اضغط «تحقق».
جرّب بنفسك
import random
import pygame
pygame.init()
screen = pygame.display.set_mode((640, 320))
pygame.display.set_caption("Sky Runner")
clock = pygame.time.Clock()
font = pygame.font.Font("assets/fonts/pixel.ttf", 32)
SKY = (140, 200, 240)
GROUND = (90, 160, 80)
GROUND_Y = 260
GRAVITY = 1
SPAWN = pygame.USEREVENT + 1
POINT = pygame.USEREVENT + 2
class Runner(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.frames = [
pygame.image.load("assets/images/player.png").convert_alpha(),
pygame.image.load("assets/images/player_walk.png").convert_alpha(),
]
self.image = self.frames[0]
self.step = 0
self.rect = self.image.get_rect(midbottom=(100, GROUND_Y))
self.vy = 0
def jump(self):
if self.rect.bottom == GROUND_Y:
self.vy = -16
def update(self):
self.vy += GRAVITY
self.rect.y += self.vy
if self.rect.bottom >= GROUND_Y:
self.rect.bottom = GROUND_Y
self.vy = 0
if self.rect.bottom == GROUND_Y:
self.step += 1
self.image = self.frames[self.step // 8 % 2]
else:
self.image = self.frames[1]
class Obstacle(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = random.choice(obstacle_images)
self.rect = self.image.get_rect(midbottom=(664, GROUND_Y))
def update(self):
self.rect.x -= speed
if self.rect.right < 0:
self.kill()
obstacle_images = [
pygame.image.load("assets/images/spike_ball.png").convert_alpha(),
pygame.image.load("assets/images/blob.png").convert_alpha(),
]
runner = Runner()
obstacles = pygame.sprite.Group()
speed = 6
pygame.time.set_timer(SPAWN, 1500)
pygame.time.set_timer(POINT, 100)
score = 0
state = "play"
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN and event.key in (pygame.K_SPACE, pygame.K_UP):
if state == "play":
runner.jump()
if event.type == SPAWN and state == "play":
obstacles.add(Obstacle())
pygame.time.set_timer(SPAWN, random.randint(1000, 2000))
if event.type == POINT and state == "play":
score += 1
if state == "play":
speed = min(14, 6 + score // 100)
runner.update()
obstacles.update()
if pygame.sprite.spritecollideany(runner, obstacles, pygame.sprite.collide_mask):
state = "over"
screen.fill(SKY)
pygame.draw.rect(screen, GROUND, (0, GROUND_Y, 640, 60))
screen.blit(runner.image, runner.rect)
obstacles.draw(screen)
score_text = font.render(f"{score:05}", True, (40, 50, 80))
screen.blit(score_text, score_text.get_rect(topright=(630, 10)))
if state == "over":
message = font.render("Game over", True, (40, 50, 80))
screen.blit(message, message.get_rect(center=(320, 140)))
pygame.display.flip()
clock.tick(60)
pygame.quit()
جميع دروس قواعد اللعبة
6عدّاء السماء
العدّاءالقفزتدرّب بنفسك: Playground لـ Pygame