【问题标题】:Sprite collide with object function?精灵与对象函数碰撞?
【发布时间】:2014-12-31 06:45:05
【问题描述】:

我是否可以创建一个函数,如果 Sprite(火箭)与 astroid 物体发生碰撞,它会显示一条消息?

class Rocket(pygame.sprite.Sprite):

    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.rect=self.image.get_rect()
        self.image=Rocket.image
        self.firecountdown = 0

    def setup(self):
        self.rect.x=700
        self.rect.y=random.randint(20,380)

    def updateposition(self):
        self.rect.x=self.rect.x-1
        time.sleep(0.005)

        if self.rect.x == 0 :
            self.rect.x = 700 + random.randint(0, 100)
            self.rect.y=random.randint(20,380)


asteroids=[]

asteroidsize=[]

for i in range(25):

        x=random.randrange(700,10000)

        y=random.randrange(0,400)

        asteroids.append([x,y])

        asteroids[i]=Asteroid()

for i in range(25):

        asteroidsize.append(random.randint(6,15))


while True:

        for i in range(len(asteroids)):


        pygame.draw.circle(screen,GREY,asteroids[i],asteroidsize[i])


        asteroids[i][0]-=2



        if asteroids[i][0]<0:

            y=random.randrange(0,400)

            asteroids[i][1]=y

            x=random.randrange(700,720)

            asteroids[i][0]=x

【问题讨论】:

  • 是的,有可能。
  • 抱歉,我应该措辞更好 - 你能告诉/告诉我如何做到这一点吗?
  • 不,这既不是代码编写也不是教程服务。我建议你从pygame's documentation开始。

标签: python pygame sprite collision


【解决方案1】:

您可以在 Rocket 类上编写一个函数来检查碰撞。由于小行星是圆形,因此您需要检查圆形上离精灵矩形中心最近的点是否在矩形范围内:

def check_asteroid_collision( self, asteroid, size ) :
    # Create a vector based on the distance between the two points
    distx   = self.rect.centerx - asteroid[0];
    disty   = self.rect.centery - asteroid[1];
    # Get magnitude (sqrt of x^2 + y^2)
    distmag = ((distx * distx) + (disty * disty)) ** 0.5;

    # Get the closest point on the circle:
    # Circle center + normalized vector * radius
    clsx    = asteroid[0] + distx / distmag * size;
    clsy    = asteroid[1] + disty / distmag * size;

    # Check if it's within our rect
    if self.rect.collidepoint( clsx, clsy ) :
        # We're colliding!! Do whatever
        print( "Oh no!" );

然后在你的游戏循环中,你可以通过调用这个来检查碰撞:

while True:
    for i in range(len(asteroids)):
        ...
        # Collision checking
        myrocket.check_asteroid_collision( asteroids[i], asteroidsize[i] );

请记住,这个过程有点昂贵,它会检查每颗小行星是否发生碰撞。如果有大量小行星,它会运行缓慢。

【讨论】:

    【解决方案2】:

    虽然我没有编写 python 代码,但我可以给你一个简单的例子来说明如何完成这样的事情。

    1. 让你的所有游戏对象都继承自一个通用的游戏物品类,这样你就知道所有物品都有一个位置和一个碰撞半径。

      class: int positionX int positionY int radius

    2. 然后将所有物品保存在游戏对象的全局列表中。

    3. 遍历你的游戏列表,看看是否有任何两个项目发生冲突

      foreach object1 in gameObjectsList: foreach object2 in gameObjectsList: if(object1 != object2) if(math.sqrt(object1.positionX - object2.positionX)**2 + (object1.positionY - object2.positionY)**2) <= object1.radius + object2.radius. //Things are colliding

    4. 随着游戏的进行,请确保在每个对象中保持位置变量的更新。

    这基本上意味着你有你的游戏对象列表,然后你循环遍历每个游戏帧并检查它们中的任何一个是否相互接触。

    或者就纯数学而言,使用距离公式(link)得到两个项目之间的距离,然后检查它们的组合半径是否大于这个距离。如果是,他们正在触摸。

    【讨论】:

    • pygame.sprites实际为你实现碰撞检测,并提供位置等
    • 好吧,假设它有一个物理模拟,或者一个多边形解释器,它正在做一些接近这个的事情,尽管可能有些优化。 :)
    • @jonrsharpe 不幸的是,pygame.sprite 仅支持在其他pygame.sprites 之间进行 rect 到 rect 或 circle 到 circle 的碰撞检测。如果你想在 sprite 和 non-sprite 之间,或者在 rects 和 circles 之间进行碰撞检测,你需要编写自己的函数。
    【解决方案3】:

    是的,得分是可能的。我假设你知道精灵碰撞功能:pygame.sprite.spritecollide()。如果您不这样做,请查看 PyGame Docs。或谷歌它。但这里是你如何做到的。第一的。在pygame,init() 行之后的代码开头添加这些代码行:

    variable = 0
    variable_font = pygame.font.Font(None, 50)
    variable_surf = variable_font.render(str(variable), 1, (0, 0, 0))
    variable_pos = [10, 10]
    

    显然,variable 可以是字符串,只需删除第 3 行中的 str()。第 1 行是不言自明的 - 它是您将在屏幕上看到的值(只是 = 符号后面的内容和/或括号)。第 2 行决定了您希望消息使用的字体和大小。如果您选择None and 50,则意味着您希望消息采用普通字体和 50 号大小。第三行 呈现或粘贴,屏幕上的消息包含字符串/数字的变量的名称,数字1(我不知道为什么),以及您的消息的颜色。如果变量包含一个数字,请在其周围放置一个str()。最后一行将是消息的位置。但是您需要先对其进行 blit。要防止消息永远出现在屏幕上,请创建一个变量:

    crashed = 0
    

    然后创建您的实例和组:

    ship = Rocket(None)
    asteroids = pygame.sprite.Group() #This is recommended, try making a class for the asteroids
    

    最后是你的碰撞代码:

    if pygame.sprite.spritecollide(Rocket, asteroids, True):
        crashed = 1
    

    您可以使用 crashed 变量控制您的 blit:

    if crashed == 0:
        screen.blit(ship.image, ship.rect)
    elif crashed == 1:
        screen.blit(ship.image, ship.rect)
        screen.blit(variable_surf, variable_pos)
    

    当您的船崩溃时(碰撞代码中的crashed = 1),最后一个 blit 行将在屏幕上列出的位置 (variable_pos) 上显示您的消息。您可以使用一些代码使crashed 回到0。记得做pygame.display.flip() 否则会发生奇怪的事情。希望这个回答对你有帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-14
      • 2018-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-18
      相关资源
      最近更新 更多