所以,我正在尝试创建一个外星人从3个特定的地方产卵的游戏。每个外星人都会随机地在3个外星人中的一个中产卵,但总会有至少一个外星人在另一个外星人的上面产卵。我想删除那个外星人然后在另一个产卵点随机繁殖他。如果它是空的,他会留下来,如果不是,这个过程就会重复。问题是,我找不到一种方法来检测同一组中两个对象的碰撞。
我刚开始学习pygame,所以1)我的问题可能很愚蠢2)我的产卵方式可能非常低效
下面是Alien类:
class Alien(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((80,60))
self.image.fill(GREY)
self.rect = self.image.get_rect()
spawn_point1 = x1,y1 = -30, 70
spawn_point2 = x2,y2 = -30, 150
spawn_point3 = x3,y3 = -30, 230
random_spawn = random.choice([spawn_point1,spawn_point2,spawn_point3])
self.rect.center = random_spawn
self.speedx = 10
def update(self):
spawn_point1 = x1,y1 = -30, 70
spawn_point2 = x2,y2 = -30, 150
spawn_point3 = x3,y3 = -30, 230
self.speedx = 10
random_spawn = random.choice([spawn_point1,spawn_point2,spawn_point3])
self.rect.x += self.speedx
if self.rect.x > WIDTH + 20:
self.rect.center = random_spawn
这是我检测冲突的部分(这部分不起作用)
aliens_col = pygame.sprite.groupcollide(aliens, aliens, True, False)
for i in aliens_col:
alien = Alien()
aliens.add(alien)
all_sprites.add(aliens)
发布于 2018-06-07 03:01:25
下面是边界框测试的一个实现。
import random
class Rectangle:
def __init__(self, height, width, x, y):
self.height = height
self.width = width
self.x = x
self.y = y
def collided_with_another_rectangle(self, rect):
""" Assumes rectangles are same size or that this rectangle is smaller than the other rectangle"""
if self.x > (rect.x + rect.width):
# Is to the right of the other rectangle
return False
elif (self.x + self.width) < rect.x:
# is to the left of the other rectangle
return False
elif (self.y + self.height) < rect.y:
# is above the other rectangle
return False
elif self.y > (rect.y + rect.height):
# is below the other rectangle
return False
else:
return True
collision_count = 0
for i in range(0, 1000):
# Here I pick random locations on a 1000X1000 screen for the first rectangle
x1 = random.randint(0, 1000)
y1 = random.randint(0, 1000)
# Here I pick random locations on a 1000X1000 screen for the second rectangle
rect1 = Rectangle(100, 100, x1, y1)
x2 = random.randint(0, 1000)
y2 = random.randint(0, 1000)
rect2 = Rectangle(100, 100, x2, y2)
"""
I use the collided with another rectangle function to test if the first rectangle is above,below,
to the right or to the left of the other rectangle. If neither of these are true then the rectangles
have collided.
"""
if rect1.collided_with_another_rectangle(rect2):
collision_count += 1
print("Rect1 X and Y:" + str(x1) + " " + str(y1))
print("Rect2 X and Y:" + str(x2) + " " + str(y2))
print("collided")
print("Collision Count:" + str(collision_count))
发布于 2018-06-07 04:58:30
我仍然不能完全确定您想要实现什么,但我认为这个示例将对您有所帮助。
当一个精灵离开屏幕时,我调用reset_pos
方法,在这个方法中,我迭代三个产卵点,将位置设置为一个接一个的产卵,然后使用另一个for循环来迭代精灵,以检查其中一个是否发生冲突。
如果一个精灵发生碰撞,我会继续下一个产卵点。
如果没有sprite冲突,我就从方法中返回。
如果没有空闲的产卵,我会移除精灵(但你可以做其他的事情)。
import random
import pygame
from pygame.math import Vector2
pygame.init()
WIDTH, HEIGHT = 640, 480
class Alien(pygame.sprite.Sprite):
def __init__(self, aliens):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((80, 60))
self.image.fill((120, random.randrange(255), random.randrange(255)))
self.rect = self.image.get_rect()
self.spawn_points = [(-30, 70), (-30, 150), (-30, 230)]
self.aliens = aliens
self.reset_pos()
self.speedx = 10
def update(self):
self.rect.x += self.speedx
if self.rect.x > WIDTH + 20:
self.reset_pos()
def reset_pos(self):
random.shuffle(self.spawn_points) # Shuffle the spawns.
for spawn in self.spawn_points:
# Set the position to one of the spawns.
self.rect.center = spawn
# Check if this sprite collides with another one.
for sprite in self.aliens:
if sprite is self: # Skip self.
continue
if self.rect.colliderect(sprite.rect):
break # Break out of the loop if the spawn is occupied.
else: # The else means no 'break' occurred in the for loop above,
# so the spawn must be free.
return # Break out of the method if the spawn is free.
# I just remove the sprite if no spawn is free. You can do something else here.
self.kill()
def main():
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
aliens = pygame.sprite.Group()
for _ in range(3):
# I pass the aliens group to the sprite because we need to
# iterate over it to see if a sprite collides.
alien = Alien(aliens)
aliens.add(alien)
all_sprites = pygame.sprite.Group(aliens)
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
al = Alien(aliens)
all_sprites.add(al)
aliens.add(al)
all_sprites.update()
screen.fill((30, 30, 30))
all_sprites.draw(screen)
pygame.display.flip()
clock.tick(30)
if __name__ == '__main__':
main()
pygame.quit()
发布于 2021-03-07 15:24:02
当在groupcollide的两个组参数中使用相同的组时,它总是认为它在group_a中检查的精灵与group_b中的同一个精灵发生冲突。这会导致groupcollide总是返回一个冲突。
为了解决这个问题,我在pygame的sprite.py中创建了一个新函数,它忽略单个冲突,只返回冲突>= 2。我唯一的更改是添加了:
if len(collision) >=2:
然后是以下行所需的选项卡。
下面粘贴了我添加到sprite.py的代码,但是def intra_groupcollide的标签太远了:
def intra_groupcollide(groupa, groupb, dokilla, dokillb, collided=None):
"""detect collision between a group and itself.
This is modified from groupcollide but excludes collisions <=1
pygame.sprite.groupcollide(groupa, groupb, dokilla, dokillb):
return dict
"""
crashed = {}
# pull the collision function in as a local variable outside
# the loop as this makes the loop run faster
sprite_collide_func = spritecollide
if dokilla:
for group_a_sprite in groupa.sprites():
collision = sprite_collide_func(group_a_sprite, groupb,
dokillb, collided)
if collision:
if len(collision) >=2:
crashed[group_a_sprite] = collision
group_a_sprite.kill()
else:
for group_a_sprite in groupa:
collision = sprite_collide_func(group_a_sprite, groupb,
dokillb, collided)
if collision:
if len(collision) >=2:
crashed[group_a_sprite] = collision
#print(crashed)
return crashed
然后在我自己的python程序中,我简单地用intra_groupcollide替换了groupcollide。我将两个kill参数都设置为“false”,因为在我的用法中,我会将它们彼此弹开。我还没有在它们设置为“true”的情况下测试这段代码。
通过以下回答,我在我的文件系统中找到了sprite.py:Where are the python modules stored?
https://stackoverflow.com/questions/50725706
复制相似问题