Как мне обнаружить коллизию в 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
Объект предлагает различные методы для обнаружения коллизий между объектами. Даже столкновение между прямоугольным и круглым объектом, таким как ракетка и мяч, может быть обнаружено по столкновению между двумя прямоугольными объектами, ракеткой и ограничивающим ее прямоугольником мяча.
Несколько примеров:
Проверьте, находится ли точка внутри прямоугольника
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
repl.it/@Rabbid76/PyGame-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:
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")
Надеюсь, у вас это сработает!!!