Zones de collision circulaires
Fait partie de la section Sprites et images du Journey Pygame de Coddy. Leçon 24 sur 36.
Un test de pixels est exact, mais ce qui est exact ne semble pas toujours juste. Une pointe qui effleure l’extrémité d’une aile compte comme un impact. À la place, de nombreux jeux testent une forme plus petite et plus simple, une zone de collision, et ignorent les frôlements.
Pour les objets ronds, testez des cercles. Attribuez un radius à chaque sprite, et pygame.sprite.collide_circle considère qu’il y a un impact lorsque la distance entre les centres est inférieure à la somme des deux rayons :
self.radius = 24 # dans Player.__init__
self.radius = 22 # dans Ball.__init__
hits = pygame.sprite.spritecollide(player, balls, False, pygame.sprite.collide_circle)Ici, cela représente 24 + 22 = 46 pixels entre les centres. Les cercles sont plus petits que les images, leurs bords peuvent donc s’effleurer sans provoquer d’impact. Un test par cercle est également peu coûteux : une seule distance, aucun pixel.
Sans radius, collide_circle utilise un cercle autour du Rect entier, plus grand que le Rect lui-même. Pour un sprite de forme rectangulaire, un Rect plus petit fait le même travail : self.rect.inflate(-16, -16) est un Rect 16 pixels moins large et moins haut, avec le même centre.
Défi
Moyen- Donne à
Playerself.radius = 24et àBallself.radius = 22. - Teste avec
pygame.sprite.collide_circleau lieu decollide_mask.
Essayez vous-même
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()
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Sprites et images
1Charger des images
Charger une imageLa placer avec un rectangleDéplacer l’imageRépéter un arrière-planPixels transparents2Tourner, retourner, redimensionner
Faire pivoter autour du centreRegarder dans la direction du volRedimensionner une imagePivoter à partir de l’original5Collisions au pixel près
Les rectangles semblent injustesMasquesSprites au pixel prèsZones de collision circulaires3Les classes pour les objets du jeu
Votre première classeLes méthodesSelf est l’objetUne liste d’objetsDes objets avec des imagesUne sous-classe6Animation à partir de feuilles de sprites
Découper une feuille de spritesUn compteur de framesAnimer avec le tempsUne explosion à déclenchement uniqueEntraînez-vous par vous-même : Playground Pygame