Вопрос-Ответ

How do I detect collision in pygame?

Как мне обнаружить коллизию в pygame?

Я составил список маркеров и список спрайтов, используя классы ниже. Как мне определить, сталкивается ли маркер со спрайтом, а затем удалить этот спрайт и маркер?

#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))
Переведено автоматически
Ответ 1

В PyGame обнаружение коллизий выполняется с помощью pygame.Rect объектов. Rect Объект предлагает различные методы для обнаружения коллизий между объектами. Даже столкновение между прямоугольным и круглым объектом, таким как ракетка и мяч, может быть обнаружено по столкновению между двумя прямоугольными объектами, ракеткой и ограничивающим ее прямоугольником мяча.

Несколько примеров:


  • pygame.Rect.collidepoint:



    Проверьте, находится ли точка внутри прямоугольника



    repl.it/@Rabbid76/PyGame-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()


  • pygame.Rect.colliderect



    Проверьте, перекрываются ли два прямоугольника



    Смотрите также Как обнаружить коллизию между двумя прямоугольными объектами или изображениями в pygame


    repl.it/@Rabbid76/PyGame-colliderect


    colliderect


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


Furthermore, pygame.Rect.collidelist and pygame.Rect.collidelistall can be used for the collision test between a rectangle and a list of rectangles. pygame.Rect.collidedict and pygame.Rect.collidedictall can be used for the collision test between a rectangle and a dictionary of rectangles.

The collision of pygame.sprite.Sprite and pygame.sprite.Group objects, can be detected by pygame.sprite.spritecollide(), pygame.sprite.groupcollide() or pygame.sprite.spritecollideany(). When using these methods, the collision detection algorithm can be specified by the collided argument:


The collided argument is a callback function used to calculate if two sprites are colliding.


Possible collided callables are collide_rect, collide_rect_ratio, collide_circle, collide_circle_ratio, collide_mask

Some examples:


  • pygame.sprite.spritecollide()


    repl.it/@Rabbid76/PyGame-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

Смотрите также Коллизия и пересечение


  • pygame.sprite.spritecollide() / collide_circle


    repl.it/@Rabbid76/PyGame-spritecollidecollidecircle



    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(80, 80)
    sprite1.radius = 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)
    sprite2.radius = 40

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



Что все это значит для вашего кода?

pygame.Surface.get_rect.get_rect() возвращает прямоугольник размером с объект Surface, который всегда начинается с (0, 0), поскольку объект Surface не имеет позиции. Положение прямоугольника может быть указано с помощью ключевого аргумента. Например, центр прямоугольника может быть указан с помощью ключевого аргумента center. Эти аргументы ключевого слова применяются к атрибутам pygame.Rect перед его возвратом (см. pygame.Rect Список аргументов ключевого слова).
Смотрите *Почему мой тест на коллизию всегда возвращает "true" и почему положение прямоугольника изображения всегда неправильное (0, 0)?

Вам вообще не нужны x и y атрибуты Sprite и Bullet. Вместо этого используйте позицию 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.Rect.colliderect() для обнаружения коллизий между экземплярами Sprite и Bullet.

Смотрите Как обнаружить коллизии между двумя прямоугольными объектами или изображениями в pygame:

my_sprite = Sprite(sx, sy, name)
my_bullet = Bullet(by, by)
while True:
# [...]

if my_sprite.rect.colliderect(my_bullet.rect):
printe("hit")
Ответ 2

Насколько я понимаю pygame, вам просто нужно проверить, перекрываются ли два прямоугольника, используя colliderect метод. Один из способов сделать это - иметь в вашем 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()
Ответ 3

Существует очень простой метод для того, что вы пытаетесь сделать, используя встроенные методы.

вот пример.

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()
Ответ 4

Создайте группу для маркеров, а затем добавьте маркеры в группу.

Что бы я сделал, так это это: В классе для игрока:

def collideWithBullet(self):
if pygame.sprite.spritecollideany(self, 'groupName'):
print("CollideWithBullet!!")
return True

И где-то в основном цикле:

def run(self):
if self.player.collideWithBullet():
print("Game Over")

Надеюсь, у вас это сработает!!!

python pygame