如何在pygame中检查鼠标与精灵的碰撞? [英] How to check collision of mouse with sprites in pygame?

查看:169
本文介绍了如何在pygame中检查鼠标与精灵的碰撞?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用十字准线替换了我的鼠标,并且屏幕上有一些目标.当你射击一个目标时,它应该会从屏幕上消失.如何检查我的十字准线(我的实际鼠标)的 CENTER 是否与其中一个精灵发生碰撞?下面的代码并没有精确地检查我的十字准线的中心是否在一个目标上,所以即使你用十字准线中的空白区域射击它也会计数,我不想要那样.

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()

推荐答案

由于目标是圆形的,所以可以通过计算鼠标指针到目标中心的距离来检测碰撞.

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

计算 欧几里德距离的平方 (dx*dx + dy*dy) 从鼠标光标到目标的中心.测试距离的平方小于半径的平方:

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:

将鼠标位置传递给Crosshair.shoot.通过目标和kill 检测到碰撞时的目标:

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

    # [...]


然而,更优雅的解决方案是使用 <代码>pygame.sprite.collide_circle().这个函数可以传递给 pygame.sprite.spritecollide() 作为回调参数.
对于此解决方案,pygame.sprite.Sprite对象必须有一个属性 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

这篇关于如何在pygame中检查鼠标与精灵的碰撞?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆