How to check collision of mouse with sprites in pygame?

我们两清 提交于 2021-02-10 12:12:32

问题


I replaced my mouse with a crosshair and I have some targets on the screen. When you shoot a target, it's supposed to disappear from the screen. How can I check if the CENTER of my crosshair (My actual mouse) is in collision with one of the sprites? The following code doesn't precisely check if the center of my crosshair is on one of the targets, so even if you shoot with the empty area in the crosshair it would count, and I don't want that.

import pygame
from random import randrange

class Crosshair(pygame.sprite.Sprite):
    def __init__(self, image):
        super().__init__()
        self.image = image
        self.rect = self.image.get_rect()
    def update(self):
        self.rect.center = pygame.mouse.get_pos()
    def shoot(self):
        pygame.sprite.spritecollide(self, target_group, True)

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

def set_background(background):
    (b_width, b_height) = background.get_size()
    for x in range(0, screen_width, b_width):
        for y in range(0, screen_height, b_height):
            screen.blit(background, (x, y))


#General setup
pygame.init()
fps = 60
clock = pygame.time.Clock()

#Background picture
background = pygame.image.load('Art/bg.png')

#Hide mouse
pygame.mouse.set_visible(False)

#Game Screen
screen_width = 1024
screen_height = 576
screen = pygame.display.set_mode((screen_width, screen_height))


#Crosshair
crosshair_image = pygame.image.load('Art/crosshair.png')
crosshair = Crosshair(crosshair_image)
crosshair_group = pygame.sprite.Group()
crosshair_group.add(crosshair)

#Targets
targets = 10
target_image = pygame.image.load('Art/target.png')
new_target_image = pygame.transform.rotozoom(target_image, 0, 0.5)
target_group = pygame.sprite.Group()
while len(target_group)<10:
    target = Target(new_target_image,
        randrange(0, screen_width),
        randrange(0, screen_height))
    if pygame.sprite.spritecollide(target, target_group, False):
        continue
    target_group.add(target)


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

    set_background(background)

    target_group.draw(screen)

    crosshair_group.update()
    crosshair_group.draw(screen)
    
    pygame.display.flip()
    clock.tick(fps)

pygame.quit()


回答1:


Since the targets are circular, the collision can b detected by calculating the distance from the mouse pointer to the center of the target.

Compute the square of the Euclidean distance (dx*dx + dy*dy) from the mouse cursor to the center of the target. Test that the square of the distance is less than the square of the radius:

Pass the mouse position to the Crosshair.shoot. Go through the targets and kill a target when a collision is detected:

class Crosshair(pygame.sprite.Sprite):
    # [...]
    
    def shoot(self, mouse_pos):
        for target in target_group:
            dx = target.rect.centerx - mouse_pos[0]
            dy = target.rect.centery - mouse_pos[1]
            dist_sq = dx*dx + dy*dy
            radius = target.image.get_width() / 2
            if dist_sq < radius*radius:
                target.kill()
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            crosshair.shoot(event.pos)            # <--- pass event.pos

    # [...]

An more elegant solution, however, is to use pygame.sprite.collide_circle(). This function can be passed to pygame.sprite.spritecollide() as a callback argument.
For this solution the pygame.sprite.Sprite objects must have an attribute radius:

class Crosshair(pygame.sprite.Sprite):
    def __init__(self, image):
        super().__init__()
        self.image = image
        self.rect = self.image.get_rect()
        self.radius = 1

    def update(self):
        self.rect.center = pygame.mouse.get_pos()
    
    def shoot(self, mouse_pos):
        self.rect.center = mouse_pos
        pygame.sprite.spritecollide(self, target_group, True, pygame.sprite.collide_circle)
class Target(pygame.sprite.Sprite):
    def __init__(self, image, x, y):
        super().__init__()
        self.image = image
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)
        self.radius = self.rect.width // 2


来源:https://stackoverflow.com/questions/65863252/how-to-check-collision-of-mouse-with-sprites-in-pygame

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!