如何在 pygame 中检测碰撞?
- 2024-11-19 08:39:00
- admin 原创
- 11
问题描述:
我使用下面的类创建了一个子弹列表和一个精灵列表。如何检测子弹是否与精灵发生碰撞,然后删除该精灵和子弹?
#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
:
测试某个点是否位于矩形内
![IT科技](https://i.sstatic.net/5jD0C.png) 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 中检测两个矩形物体或图像之间的碰撞
![IT科技](https://i.sstatic.net/5jD0C.png) 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
一些例子:
pygame.sprite.spritecollide()
![IT科技](https://i.sstatic.net/5jD0C.png) 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
![IT科技](https://i.sstatic.net/5jD0C.png) 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对象大小相同的矩形,由于Surface对象没有位置,因此该矩形始终从 (0, 0) 开始。矩形的位置可以通过关键字参数指定。例如,可以使用关键字参数指定矩形的中心。这些关键字参数在返回之前center
应用于的属性(请参阅关键字参数列表)。
请参阅 *为什么我的碰撞测试总是返回“true”,为什么图像矩形的位置总是错误的 (0, 0)?pygame.Rect
`pygame.Rect`
您根本不需要and的x
和属性。请改用属性的位置:y
`SpriteBullet
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()
实例之间的碰撞。
请参阅如何在 pygame 中检测两个矩形物体或图像之间的碰撞:Sprite
Bullet
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")
希望这对你有用!
解决方案 5:
在 Sprite 类中,尝试使用以下代码在 Sprite 类中添加一个self.mask
属性
self.mask = pygame.mask.from_surface(self.image)
和一个函数:collide_mask
def collide_mask(self, mask):
collided = False
mask_outline = mask.outline()
self.mask_outline = self.mask.outline()
for point in range(len(mask_outline)):
mask_outline[point] = list(mask_outline[point])
mask_outline[point][0] += bullet.x
mask_outline[point][1] += bullet.y
for point in range(len(self.mask_outline)):
self.mask_outline[point] = list(mask_outline[point])
self.mask_outline[point][0] += self.x
self.mask_outline[point][1] += self.y
for point in mask_outline:
for self_mask_point in self.mask_outline:
if point = self_mask_point:
collided = True
return collided
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件