Menu
CoddyTech

مناطق التصادم الدائرية

جزء من قسم الكائنات والصور في رحلة Pygame على Coddy. الدرس 24 من 36.

اختبار البكسلات دقيق، لكن الدقة ليست دائمًا ما يبدو منصفًا. يُحتسب احتكاك شوكة بطرف جناح إصابةً. تختبر ألعاب كثيرة بدلًا من ذلك شكلًا أصغر وأبسط، يُسمى صندوق الإصابة، وتتجاهل الحالات التي يفصل فيها القليل عن الإصابة.

للأشكال الدائرية، اختبر الدوائر. أعطِ كل كائن متحرك radius، وتعتبر pygame.sprite.collide_circle التصادم إصابةً عندما تكون المسافة بين المركزين أقل من مجموع نصفي القطرين:

self.radius = 24  # في Player.__init__
self.radius = 22  # في Ball.__init__

hits = pygame.sprite.spritecollide(player, balls, False, pygame.sprite.collide_circle)

هنا، تكون المسافة بين المركزين 24 + 22 = 46 بكسلًا. الدائرتان أصغر من الصورتين، لذا قد تتلامس الحواف تمامًا من دون أن تُحتسب إصابة. واختبار الدائرة سريع أيضًا: مسافة واحدة، ومن دون فحص البكسلات.

من دون radius، تستخدم collide_circle دائرةً تحيط بـ Rect كاملًا، فتكون أكبر من Rect نفسه. وبالنسبة إلى كائن متحرك مربع الشكل، تؤدي Rect أصغر الغرض نفسه: self.rect.inflate(-16, -16) هي Rect أقل عرضًا وارتفاعًا بمقدار 16 بكسلًا، مع الحفاظ على المركز نفسه.

challenge icon

التحدي

متوسط
  1. أعطِ Player self.radius = 24 وBall self.radius = 22.
  2. اختبر باستخدام pygame.sprite.collide_circle بدلًا من collide_mask.

جرّب بنفسك

import pygame

pygame.init()
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("Spike Field")
clock = pygame.time.Clock()

ship_image = pygame.image.load("assets/images/ship.png").convert_alpha()
ball_image = pygame.image.load("assets/images/spike_ball.png").convert_alpha()
font = pygame.font.Font(None, 40)


class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = ship_image
        self.rect = self.image.get_rect(topleft=(420, 320))
        self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            self.rect.x -= 4
        if keys[pygame.K_RIGHT]:
            self.rect.x += 4
        if keys[pygame.K_UP]:
            self.rect.y -= 4
        if keys[pygame.K_DOWN]:
            self.rect.y += 4


class Ball(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = ball_image
        self.rect = self.image.get_rect(center=(x, y))
        self.mask = pygame.mask.from_surface(self.image)


player = Player()
balls = pygame.sprite.Group(Ball(160, 240), Ball(320, 240), Ball(480, 240))

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    player.update()
    hits = pygame.sprite.spritecollide(player, balls, False, pygame.sprite.collide_mask)

    screen.fill((20, 22, 40))
    balls.draw(screen)
    screen.blit(player.image, player.rect)
    if hits:
        text = font.render("Hit!", True, (240, 240, 240))
        screen.blit(text, (10, 10))
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس الكائنات والصور

تدرّب بنفسك: Playground لـ Pygame