首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Pygame,同一组中两个对象之间的碰撞

Pygame,同一组中两个对象之间的碰撞
EN

Stack Overflow用户
提问于 2018-06-07 00:53:49
回答 3查看 1.4K关注 0票数 3

所以,我正在尝试创建一个外星人从3个特定的地方产卵的游戏。每个外星人都会随机地在3个外星人中的一个中产卵,但总会有至少一个外星人在另一个外星人的上面产卵。我想删除那个外星人然后在另一个产卵点随机繁殖他。如果它是空的,他会留下来,如果不是,这个过程就会重复。问题是,我找不到一种方法来检测同一组中两个对象的碰撞。

我刚开始学习pygame,所以1)我的问题可能很愚蠢2)我的产卵方式可能非常低效

下面是Alien类:

代码语言:javascript
复制
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

这是我检测冲突的部分(这部分不起作用)

代码语言:javascript
复制
aliens_col = pygame.sprite.groupcollide(aliens, aliens, True, False)

for i in aliens_col:
    alien = Alien()
    aliens.add(alien)
    all_sprites.add(aliens)
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-06-07 03:01:25

下面是边界框测试的一个实现。

代码语言:javascript
复制
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))
票数 0
EN

Stack Overflow用户

发布于 2018-06-07 04:58:30

我仍然不能完全确定您想要实现什么,但我认为这个示例将对您有所帮助。

当一个精灵离开屏幕时,我调用reset_pos方法,在这个方法中,我迭代三个产卵点,将位置设置为一个接一个的产卵,然后使用另一个for循环来迭代精灵,以检查其中一个是否发生冲突。

如果一个精灵发生碰撞,我会继续下一个产卵点。

如果没有sprite冲突,我就从方法中返回。

如果没有空闲的产卵,我会移除精灵(但你可以做其他的事情)。

代码语言:javascript
复制
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()
票数 0
EN

Stack Overflow用户

发布于 2021-03-07 15:24:02

当在groupcollide的两个组参数中使用相同的组时,它总是认为它在group_a中检查的精灵与group_b中的同一个精灵发生冲突。这会导致groupcollide总是返回一个冲突。

为了解决这个问题,我在pygame的sprite.py中创建了一个新函数,它忽略单个冲突,只返回冲突>= 2。我唯一的更改是添加了:

代码语言:javascript
复制
if len(collision) >=2:

然后是以下行所需的选项卡。

下面粘贴了我添加到sprite.py的代码,但是def intra_groupcollide的标签太远了:

代码语言:javascript
复制
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?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50725706

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档