Menu
CoddyTech

התנגשות

חלק מהיחידה חוקי המשחק במסלול ה-Pygame של Coddy. שיעור 27 מתוך 29.

מגע במכשול מסיים את הריצה. pygame.sprite.spritecollideany(sprite, group) מחזירה את הספרייט הראשון בקבוצה שנוגע בספרייט, או None.

כברירת מחדל, היא משווה מלבנים. בפינות התמונות יש אזורים שקופים, בעיקר בתמונה של הגוש, ולכן שני מלבנים יכולים לחפוף בלי ששום דבר ממה שרואים ייגע. ארגומנט שלישי בוחר בדיקה הוגנת יותר:

if pygame.sprite.spritecollideany(runner, obstacles, pygame.sprite.collide_mask):
    state = "over"

collide_mask משווה את הפיקסלים המצוירים בתמונות ומתעלמת מהפיקסלים השקופים. כך, התנגשות היא באמת התנגשות שהשחקן יכול לראות.

המצב פועל כמו ב-Meteor Dodge: עדכון, קפיצה והופעת מכשולים חדשים מתרחשים רק כשהמצב הוא "play", ומסך סיום המשחק מציג את המשחק הקפוא עם הודעה.

challenge icon

אתגר

בינוני
  1. הוסיפו גופן, assets/fonts/pixel.ttf בגודל 32, ואת state = "play".
  2. רק כשהמצב הוא "play": קפצו, הוסיפו מכשולים ועדכנו את הרץ ואת המכשולים.
  3. כשהרץ נוגע במכשול (collide_mask), הגדירו את המצב ל־"over".
  4. כשהמשחק מסתיים, הציגו את Game over בצבע (40, 50, 80) ובמרכז (320, 140).

נסו בעצמכם

import random
import pygame

pygame.init()
screen = pygame.display.set_mode((640, 320))
pygame.display.set_caption("Sky Runner")
clock = pygame.time.Clock()

SKY = (140, 200, 240)
GROUND = (90, 160, 80)
GROUND_Y = 260
GRAVITY = 1
SPAWN = pygame.USEREVENT + 1


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)

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):
            runner.jump()
        if event.type == SPAWN:
            obstacles.add(Obstacle())
            pygame.time.set_timer(SPAWN, random.randint(1000, 2000))

    runner.update()
    obstacles.update()

    screen.fill(SKY)
    pygame.draw.rect(screen, GROUND, (0, GROUND_Y, 640, 60))
    screen.blit(runner.image, runner.rect)
    obstacles.draw(screen)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

כל השיעורים ביחידה חוקי המשחק

תרגלו בעצמכם: Pygame אונליין