pygame/sprites: 暴徒碰撞
pygame/sprites: mob collision
您好,我最近开始接触 pygame 库并制作一些小项目。我正在制作一个非常简单的游戏,你作为玩家必须躲避敌人。但是,我想在它们相互碰撞时删除它们。我想到了下面的代码,但是,它只删除了一个小怪。生物在 all_sprites 和 mob_sprites 中。我对精灵和 pygame 很陌生,所以这里可能有一个愚蠢的错误,希望有人能帮助我。
# check mob collision
for mob in mobs:
temp_sprites.add(mob)
mobs.remove(mob)
collision = pg.sprite.groupcollide(temp_sprites, mobs, True, True)
for col in collision:
# score is just for the game
score += col.size
else:
mobs.add(mob)
all_sprites.add(mob)
temp_sprites.remove(mob)
如果你想销毁一个精灵,调用pygame.sprite.Sprite.kill()
:
就足够了
mob.kill()
kill
从包含它的所有组中删除 Sprite。
如果你想检测一个精灵是否与循环中的任何其他精灵发生碰撞,那么我建议使用 2 个嵌套循环和 pygame.sprite.collide_rect()
:
例如:
for mob1 in mobs:
for mob2 in mobs:
if mob1 != mob2 and pg.sprite.collide_rect(mob1, mob2):
mob1.kill()
mob2.kill()
# score is just for the game
score += col.size
你的第一个问题是你使用了一个for...else
循环; else
部分将被执行,如果你不 break
for 循环以防发生碰撞,从而重新添加精灵。
你的代码的第二个问题是,虽然 groupcollide
会正确地从它们的组中删除精灵,但它们将被重新添加,因为它们仍然存储在你用 [=18 迭代的列表中=] 循环(遍历精灵组每次都会创建一个新列表)。
所以你可以用这样的方法修复你的代码:
for mob in mobs.sprites():
if not mob.groups():
# mob was already removed by a previous iteration of this loop
continue
temp_sprites.add(mob)
mobs.remove(mob)
collision = pygame.sprite.groupcollide(temp_sprites, mobs, True, True)
for col in collision:
# score is just for the game
score += col.size
break
else:
mobs.add(mob)
all_sprites.add(mob)
temp_sprites.remove(mob)
但我建议改为在精灵的 update
方法中处理碰撞。
def update(self):
# whatever
if pygame.sprite.spritecollide(self, self.mobs, True, collide_rect_not_self):
self.kill()
其中 self.mobs
是对 mobs
组的引用,collide_rect_not_self
是对 pygame.sprite.collide_rect
:
的简单包装
def collide_rect_not_self(a, b):
if a != b:
return pygame.sprite.collide_rect(a, b)
这是一个完整的例子:
import random
import pygame
def collide_rect_not_self(a, b):
if a != b:
return pygame.sprite.collide_rect(a, b)
class Actor(pygame.sprite.Sprite):
def __init__(self, pos, mobs, static, *grps):
super().__init__(mobs, *grps)
self.image = pygame.Surface((40, 40))
self.rect = self.image.get_rect(center=pos)
self.pos = pygame.Vector2(*pos)
self.vel = pygame.Vector2(random.randint(0, 10), random.randint(0, 10)) if not static else pygame.Vector2(0, 0)
self.mobs = mobs
def update(self):
self.pos += self.vel
if not pygame.display.get_surface().get_rect().contains(self.rect):
self.vel *= -1
self.rect.clamp_ip(pygame.display.get_surface().get_rect())
self.pos = self.rect.center
self.rect.center = self.pos
if pygame.sprite.spritecollide(self, self.mobs, True, collide_rect_not_self):
self.kill()
def main():
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((800, 600))
mobs = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
while True:
for event in pygame.event.get():
pos = pygame.mouse.get_pos()
if event.type == pygame.QUIT:
return
if event.type == pygame.MOUSEBUTTONDOWN:
Actor(event.pos, mobs, event.button == 1, all_sprites)
screen.fill((255, 255, 255))
all_sprites.update()
all_sprites.draw(screen)
clock.tick(30)
pygame.display.flip()
main()
使用鼠标左键放置静态矩形,使用其他鼠标按钮放置移动矩形。
您好,我最近开始接触 pygame 库并制作一些小项目。我正在制作一个非常简单的游戏,你作为玩家必须躲避敌人。但是,我想在它们相互碰撞时删除它们。我想到了下面的代码,但是,它只删除了一个小怪。生物在 all_sprites 和 mob_sprites 中。我对精灵和 pygame 很陌生,所以这里可能有一个愚蠢的错误,希望有人能帮助我。
# check mob collision
for mob in mobs:
temp_sprites.add(mob)
mobs.remove(mob)
collision = pg.sprite.groupcollide(temp_sprites, mobs, True, True)
for col in collision:
# score is just for the game
score += col.size
else:
mobs.add(mob)
all_sprites.add(mob)
temp_sprites.remove(mob)
如果你想销毁一个精灵,调用pygame.sprite.Sprite.kill()
:
mob.kill()
kill
从包含它的所有组中删除 Sprite。
如果你想检测一个精灵是否与循环中的任何其他精灵发生碰撞,那么我建议使用 2 个嵌套循环和 pygame.sprite.collide_rect()
:
例如:
for mob1 in mobs:
for mob2 in mobs:
if mob1 != mob2 and pg.sprite.collide_rect(mob1, mob2):
mob1.kill()
mob2.kill()
# score is just for the game
score += col.size
你的第一个问题是你使用了一个for...else
循环; else
部分将被执行,如果你不 break
for 循环以防发生碰撞,从而重新添加精灵。
你的代码的第二个问题是,虽然 groupcollide
会正确地从它们的组中删除精灵,但它们将被重新添加,因为它们仍然存储在你用 [=18 迭代的列表中=] 循环(遍历精灵组每次都会创建一个新列表)。
所以你可以用这样的方法修复你的代码:
for mob in mobs.sprites():
if not mob.groups():
# mob was already removed by a previous iteration of this loop
continue
temp_sprites.add(mob)
mobs.remove(mob)
collision = pygame.sprite.groupcollide(temp_sprites, mobs, True, True)
for col in collision:
# score is just for the game
score += col.size
break
else:
mobs.add(mob)
all_sprites.add(mob)
temp_sprites.remove(mob)
但我建议改为在精灵的 update
方法中处理碰撞。
def update(self):
# whatever
if pygame.sprite.spritecollide(self, self.mobs, True, collide_rect_not_self):
self.kill()
其中 self.mobs
是对 mobs
组的引用,collide_rect_not_self
是对 pygame.sprite.collide_rect
:
def collide_rect_not_self(a, b):
if a != b:
return pygame.sprite.collide_rect(a, b)
这是一个完整的例子:
import random
import pygame
def collide_rect_not_self(a, b):
if a != b:
return pygame.sprite.collide_rect(a, b)
class Actor(pygame.sprite.Sprite):
def __init__(self, pos, mobs, static, *grps):
super().__init__(mobs, *grps)
self.image = pygame.Surface((40, 40))
self.rect = self.image.get_rect(center=pos)
self.pos = pygame.Vector2(*pos)
self.vel = pygame.Vector2(random.randint(0, 10), random.randint(0, 10)) if not static else pygame.Vector2(0, 0)
self.mobs = mobs
def update(self):
self.pos += self.vel
if not pygame.display.get_surface().get_rect().contains(self.rect):
self.vel *= -1
self.rect.clamp_ip(pygame.display.get_surface().get_rect())
self.pos = self.rect.center
self.rect.center = self.pos
if pygame.sprite.spritecollide(self, self.mobs, True, collide_rect_not_self):
self.kill()
def main():
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((800, 600))
mobs = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
while True:
for event in pygame.event.get():
pos = pygame.mouse.get_pos()
if event.type == pygame.QUIT:
return
if event.type == pygame.MOUSEBUTTONDOWN:
Actor(event.pos, mobs, event.button == 1, all_sprites)
screen.fill((255, 255, 255))
all_sprites.update()
all_sprites.draw(screen)
clock.tick(30)
pygame.display.flip()
main()
使用鼠标左键放置静态矩形,使用其他鼠标按钮放置移动矩形。