我使用下面的类制作了子弹列表和精灵列表。如何检测子弹是否与精灵碰撞,然后删除该精灵和子弹?
#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))
答案 0 :(得分:6)
根据我对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()
此外,您的课程通常应延长object
,因此请将class Sprite:
替换为class Sprite(object):
等。
答案 1 :(得分: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)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False
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()
答案 2 :(得分:2)
在PyGame中,可以使用pygame.Rect
对象来完成基本的碰撞检测。 Rect
对象提供了多种检测对象之间冲突的方法。请注意,甚至在 Pong 游戏中,矩形对象与圆形对象(例如球拍和球)的碰撞也可以通过两个矩形对象(球拍的球拍和边界矩形)之间的碰撞来大致检测到球。
一些例子:
测试点是否在矩形内
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()
测试两个矩形是否重叠
另请参阅How to detect collisions between two rectangular objects or images in 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()
此外,pygame.Rect.collidelist
和pygame.Rect.collidelistall
可用于矩形和矩形列表之间的碰撞测试。 pygame.Rect.collidedict
和pygame.Rect.collidedictall
可用于矩形和矩形字典之间的碰撞碰撞测试。
pygame.sprite.Sprite
,pygame.sprite.Group
或pygame.sprite.spritecollide()
可以检测到pygame.sprite.groupcollide()
和pygame.sprite.spritecollideany()
对象的碰撞。使用这些方法时,可以通过collided
参数指定冲突检测算法:
collided参数是一个回调函数,用于计算两个精灵是否发生碰撞。
可能的collided
可调用对象是collide_rect
,collide_rect_ratio
,collide_circle
,collide_circle_ratio
,collide_mask
一些例子:
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()
有关与面具的碰撞,请参见How can I made a collision mask?或Pygame mask collision
另请参阅Collision and Intersection
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(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()
这对您的代码意味着什么?
pygame.Surface.get_rect.get_rect()
返回一个具有 Surface 对象大小的矩形,该矩形始终以(0,0)开始,因为 Surface 对象没有位置。矩形的位置可以通过关键字参数指定。例如,可以使用关键字参数center
指定矩形的中心。这些关键字参数在返回之前将应用于pygame.Rect
的属性(有关关键字参数的完整列表,请参见pygame.Rect
)。
参见* Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?
您根本不需要x
和y
的{{1}}和Sprite
属性。请改用Bullet
属性的位置:
rect
使用pygame.Rect.colliderect()
检测#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)
和Sprite
实例之间的冲突。
参见How to detect collisions between two rectangular objects or images in pygame:
Bullet
my_sprite = Sprite(sx, sy, name)
my_bullet = Bullet(by, by)
答案 3 :(得分:0)
为项目符号创建一个组,然后将项目符号添加到该组中。
我要做的是: 在播放器类中:
def collideWithBullet(self):
if pygame.sprite.spritecollideany(self, 'groupName'):
print("CollideWithBullet!!")
return True
在主循环中的某处:
def run(self):
if self.player.collideWithBullet():
print("Game Over")
希望对您有用!