当前位置: 首页 > 知识库问答 >
问题:

如何在pygame中检测冲突?

堵鸿光
2023-03-14

我使用下面的类制作了一个项目符号列表和一个精灵列表。如何检测子弹是否与子画面发生碰撞,然后删除该精灵和子弹?

#Define the sprite class
class Sprite:

    def __init__(self,x,y, name):
        self.x=x

        self.y=y

        self.image = pygame.image.load(name)

        self.rect = self.image.get_rect()

    def render(self):
        window.blit(self.image, (self.x,self.y))


# Define the bullet class to create bullets          
class Bullet:

    def __init__(self,x,y):
        self.x = x + 23
        self.y = y
        self.bullet = pygame.image.load("user_bullet.BMP")
        self.rect = self.bullet.get_rect()

    def render(self):
        window.blit(self.bullet, (self.x, self.y))

共有3个答案

贝杜吟
2023-03-14

有一个非常简单的方法可以让您尝试使用内置方法来做什么。

这是一个例子。

import pygame
import sys

class Sprite(pygame.sprite.Sprite):
    def __init__(self, pos):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface([20, 20])
        self.image.fill((255, 0, 0))
        self.rect = self.image.get_rect()

        self.rect.center = pos

def main():
    pygame.init()
    clock = pygame.time.Clock()
    fps = 50
    bg = [255, 255, 255]
    size =[200, 200]


    screen = pygame.display.set_mode(size)

    player = Sprite([40, 50])
    player.move = [pygame.K_LEFT, pygame.K_RIGHT, pygame.K_UP, pygame.K_DOWN]
    player.vx = 5
    player.vy = 5


    wall = Sprite([100, 60])

    wall_group = pygame.sprite.Group()
    wall_group.add(wall)

    player_group = pygame.sprite.Group()
    player_group.add(player)

    # I added loop for a better exit from the game
    loop = 1
    while loop:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                loop = 0

        key = pygame.key.get_pressed()

        for i in range(2):
            if key[player.move[i]]:
                player.rect.x += player.vx * [-1, 1][i]

        for i in range(2):
            if key[player.move[2:4][i]]:
                player.rect.y += player.vy * [-1, 1][i]

        screen.fill(bg)

        # first parameter takes a single sprite
        # second parameter takes sprite groups
        # third parameter is a do kill command if true
        # all group objects colliding with the first parameter object will be
        # destroyed. The first parameter could be bullets and the second one
        # targets although the bullet is not destroyed but can be done with
        # simple trick bellow
        hit = pygame.sprite.spritecollide(player, wall_group, True)

        if hit:
            # if collision is detected call a function in your case destroy
            # bullet
            player.image.fill((255, 255, 255))

        player_group.draw(screen)
        wall_group.draw(screen)

        pygame.display.update()
        clock.tick(fps)

    pygame.quit()
    # sys.exit


if __name__ == '__main__':
    main()
汝弘深
2023-03-14

根据我对pygame的了解,您只需要使用碰撞方法检查两个矩形是否重叠即可。一种方法是在 Bullet 类中使用一个检查冲突的方法:

def is_collided_with(self, sprite):
    return self.rect.colliderect(sprite.rect)

然后你可以这样称呼它:

sprite = Sprite(10, 10, 'my_sprite')
bullet = Bullet(20, 10)
if bullet.is_collided_with(sprite):
    print('collision!')
    bullet.kill()
    sprite.kill()
宦博超
2023-03-14

在PyGame中,冲突检测是使用pygame.Rect对象完成的。Rect对象提供了检测对象之间碰撞的各种方法。即使是矩形和圆形对象(如球拍和球)之间的碰撞也可以通过两个矩形对象(球拍和球的边界矩形)之间的碰撞来检测。

一些例子:

> pygame。Rect.collidepoint:

测试一个点是否在一个矩形内

import pygame

pygame.init()
window = pygame.display.set_mode((250, 250))
rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(100, 100)

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

    point = pygame.mouse.get_pos()
    collide = rect.collidepoint(point)
    color = (255, 0, 0) if collide else (255, 255, 255)

    window.fill(0)
    pygame.draw.rect(window, color, rect)
    pygame.display.flip()

pygame.quit()
exit()

< code>pygame。Rect.colliderect

测试两个矩形是否重叠

另请参见如何在pygame中检测两个矩形对象或图像之间的碰撞

import pygame

pygame.init()
window = pygame.display.set_mode((250, 250))
rect1 = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75)
rect2 = pygame.Rect(0, 0, 75, 75)

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

    rect2.center = pygame.mouse.get_pos()
    collide = rect1.colliderect(rect2)
    color = (255, 0, 0) if collide else (255, 255, 255)

    window.fill(0)
    pygame.draw.rect(window, color, rect1)
    pygame.draw.rect(window, (0, 255, 0), rect2, 6, 1)
    pygame.display.flip()

pygame.quit()
exit()

此外,< code>pygame。Rect.collidelist和< code>pygame。Rect.collidelistall可用于矩形和矩形列表之间的碰撞测试。< code>pygame。Rect.collidedict和< code>pygame。rect . collideditall 可用于矩形和矩形字典之间的碰撞测试。

pygame.sprite的冲突。精灵pygame.Sprite。pygame.sprite可以检测组对象。spritecollide()pygame.sprite。组碰撞()或pygame.sprite.spritecollideany()。使用这些方法时,碰撞检测算法可以由collected参数指定:

碰撞参数是一个回调函数,用于计算两个精灵是否碰撞。

可能的碰撞可调用项包括collect_rect collece_circle_ratio、 collect_mask

一些例子:

>

  • pygame.sprite.spritecollide()

    import pygame
    
    pygame.init()
    window = pygame.display.set_mode((250, 250))
    
    sprite1 = pygame.sprite.Sprite()
    sprite1.image = pygame.Surface((75, 75))
    sprite1.image.fill((255, 0, 0))
    sprite1.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75)
    sprite2 = pygame.sprite.Sprite()
    sprite2.image = pygame.Surface((75, 75))
    sprite2.image.fill((0, 255, 0))
    sprite2.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75)
    
    all_group = pygame.sprite.Group([sprite2, sprite1])
    test_group = pygame.sprite.Group(sprite2)
    
    run = True
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
    
        sprite1.rect.center = pygame.mouse.get_pos()
        collide = pygame.sprite.spritecollide(sprite1, test_group, False)
    
        window.fill(0)
        all_group.draw(window)
        for s in collide:
            pygame.draw.rect(window, (255, 255, 255), s.rect, 5, 1)
        pygame.display.flip()
    
    pygame.quit()
    exit()
    

    对于与蒙版的碰撞,请参阅如何制作碰撞蒙版?或Pygame蒙版碰撞

    另请参见碰撞和交叉

    > < Li > < p > < code > py game . sprite . sprite collide()/< code > collide _ circle

    import pygame
    
    pygame.init()
    window = pygame.display.set_mode((250, 250))
    
    sprite1 = pygame.sprite.Sprite()
    sprite1.image = pygame.Surface((80, 80), pygame.SRCALPHA)
    pygame.draw.circle(sprite1.image, (255, 0, 0), (40, 40), 40)
    sprite1.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(40, 40)
    sprite2 = pygame.sprite.Sprite()
    sprite2.image = pygame.Surface((80, 89), pygame.SRCALPHA)
    pygame.draw.circle(sprite2.image, (0, 255, 0), (40, 40), 40)
    sprite2.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(80, 80)
    
    all_group = pygame.sprite.Group([sprite2, sprite1])
    test_group = pygame.sprite.Group(sprite2)
    
    run = True
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
    
        sprite1.rect.center = pygame.mouse.get_pos()
        collide = pygame.sprite.spritecollide(sprite1, test_group, False, pygame.sprite.collide_circle)
    
        window.fill(0)
        all_group.draw(window)
        for s in collide:
            pygame.draw.circle(window, (255, 255, 255), s.rect.center, s.rect.width // 2, 5)
        pygame.display.flip()
    
    pygame.quit()
    exit()
    

    这对您的代码意味着什么?

    皮游戏。Surface.get_rect.get_rect() 返回一个具有表面对象大小的矩形,该矩形始终从 (0, 0) 开始,因为表面对象没有位置。矩形的位置可以通过关键字参数指定。例如,可以使用关键字参数中心指定矩形的中心。这些关键字参数应用于 pygame 的属性。在返回之前进行更正(请参阅 pygame。关键字参数列表的矩形)。
    请参阅 *为什么我的碰撞测试总是返回“true”,为什么图像矩形的位置总是错误 (0, 0)?

    您根本不需要SpriteBulletx和y属性。使用rect属性的位置:

    #Define the sprite class
    class Sprite:
        def __init__(self, x, y, name):
            self.image = pygame.image.load(name)
            self.rect = self.image.get_rect(topleft = (x, y))
    
        def render(self):
            window.blit(self.image, self.rect)
    
    # Define the bullet class to create bullets          
    class Bullet:
        def __init__(self, x, y):
            self.bullet = pygame.image.load("user_bullet.BMP")
            self.rect = self.bullet.get_rect(topleft = (x + 23, y))
    
        def render(self):
            window.blit(self.bullet, self.rect)
    

    使用皮游戏。用于检测精灵实例和子弹实例之间的碰撞。
    请参阅如何在pygame中检测两个矩形物体或图像之间的碰撞:

    my_sprite = Sprite(sx, sy, name)
    my_bullet = Bullet(by, by)
    
    while True:
        # [...]
    
        if my_sprite.rect.colliderect(my_bullet.rect):
            printe("hit")
    

  •  类似资料:
    • 我是pygame的新手,我做了一个屏幕边框检测,但它不起作用 并检查它是否接触到边缘 但如果我们使用它就会坏掉/播放器就会卡住 整个代码是

    • 我们可以在unity3d中检测网格碰撞吗?我想在碰撞时显示一些纹理,目前我正在使用箱形碰撞体,这就是为什么它的表面/边缘与对象体网格不匹配的原因,即使我在网格表面上获得命中点,我也不知道如何在网格上的特定位置将纹理放在网格上, 在unity3d中,是否有任何特定于相同类型要求的内置组件或解决方法? 正如我们在图片中看到的,在游戏对象内检测到了碰撞,因为框碰撞器位于目标对象网格内。注意:这里我用虚拟

    • 问题内容: 我知道我可以检查是否有鼠标左键 但是如何检查他们是否双击了?还有什么方法可以检查用户是否向前或向后移动了滚轮? 问题答案: 我从未使用过-但是: 检测双击: 猜测一下,而不是立即处理每次单击,而是施加50ms的延迟,然后查看您在该时间是否收到另一个单击事件。用户可能不会注意到50ms的延迟。 区分上/下滚轮: 请参阅此文档页面上的注释。显然,定义了五个按钮-左,中,右,上滚轮和下滚轮。

    • 所以我试图用Python和Pyplay创建一个益智平台游戏,但是我遇到了一点麻烦。当我为主要角色使用单点图像,而不是矩形图像时,如何制作碰撞检测器?我知道直角图像有左、右、顶部和底部像素功能(这对冲突检测非常有用),但是对于单片图像有这样的功能吗?或者我只需要为x和y坐标创建一个变量图像的宽度/高度?我试过用那个 但是catImg一直在通过窗户的尽头。我做错了什么?提前谢谢。

    • 我写了下面的JavaFX程序,其中两个矩形节点正在转换转换: 如何对“平移转换”中的两个矩形节点实施冲突检测?

    • 我正在尝试检查StackPane中节点的冲突检测。下面是我的代码: 在这里,如果我使用AnchorPane,碰撞检测就会工作。但在StackPane的情况下,我无法做到这一点。我猜这是因为堆栈窗格的坐标系统(如果我错了,请纠正我)。 所以请帮我实现上述两个矩形的碰撞检测。另外,如果我想更改节点的坐标,请提供一些建议(如果您知道),以便在StackPane内的节点上实现此类冲突检测。