【问题标题】:Pygame - Return collision locationPygame - 返回碰撞位置
【发布时间】:2021-02-21 21:54:07
【问题描述】:

如何获得两个精灵之间碰撞的确切位置?

如果有多个像素重叠,可能会得到一个像素位置列表。 我想在那个时候生成粒子,并且也需要它来实现其他功能。

伪代码:

obj1.rect..x += obj1.velocity
collision = collide(obj1, obj2):
if collision:
    ?
    return collision_location

我的代码

def _bullet_collision(self):
        for bullet in self.bullets:
            hits = pygame.sprite.spritecollide(bullet, self.aliens, False, pygame.sprite.collide_mask)
            if hits:
                hit_str = 11
                for alien in hits:
                    x, y = alien.x, alien.y
                    spawn_pos = (x, y)
                    self._hit_enemy(alien, x, y, hit_str)
                bullet.bullet_hit(spawn_pos, hit_str)

【问题讨论】:

  • 请发布您的代码。
  • 在把问题发到这里之前先谷歌一下,第一页有几十个资源
  • 天哪,你们很友好。我查看了 google、youtube 和 stackoverflow,并试图掌握这些文档,但我能找到的只是碰撞检测。为什么这个问题需要发布代码?它可能只是一个功能,我无法正确处理。说真的,你有没有仔细看看你的谷歌搜索结果
  • @RandomDavis ^this
  • @Rabbid76 - 如果我很多人提出不同意见 - 这个问题是关于碰撞的交叉区域,而不是如何碰撞。我不同意这是重复的。我也搜索了这个交叉区域的例子,但没有找到适合 Python/PyGame 的东西。

标签: python pygame


【解决方案1】:

根据答案:https://stackoverflow.com/a/57023183/1730895

计算矩形的交点相当容易:

def rectIntersection( rect1, rect2 ):
    """ Given two pygame.Rect intersecting rectangles, return the overlap rect """
    left  = max( rect1.left,  rect2.left )
    width = min( rect1.right, rect2.right ) - left
    top   = max( rect1.top,   rect2.top )
    height= min( rect1.bottom, rect2.bottom ) - top
    return pygame.Rect( left, top, width, height )

所以首先使用pygame.rect.colliderect() (doco) 来确定是否真的有任何重叠。显然,这会给您一个重叠的区域,因此要回答您的问题,它可能是该矩形区域内的每个像素。但也许您可以将质心用作“发生点”。

import pygame

# Window size
WINDOW_WIDTH    = 400
WINDOW_HEIGHT   = 400
WINDOW_SURFACE  = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE
WINDOW_MAXFPS   = 60

# Colours
DARK_BLUE = (  3,   5,  54)
RED       = (255,   0,   0)
YELLOW    = (200, 200,  20)
GREEN     = ( 20, 200,  20)


def rectIntersection( rect1, rect2 ):
    """ Given two pygame.Rect intersecting rectangles, calculate the rectangle of intersection """
    left  = max( rect1.left,  rect2.left )
    width = min( rect1.right, rect2.right ) - left
    top   = max( rect1.top,   rect2.top )
    height= min( rect1.bottom, rect2.bottom ) - top

    return pygame.Rect( left, top, width, height )


### Initialisation
pygame.init()
pygame.mixer.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), WINDOW_SURFACE )
pygame.display.set_caption("Rect-Rect Intersection")

central_rect = pygame.Rect( 175, 175, 50, 50 )
player_rect  = pygame.Rect(   0,   0, 30, 30 )

### Main Loop
clock = pygame.time.Clock()
done = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.MOUSEMOTION ):  # move the player's rectangle with the mouse
            mouse_pos = pygame.mouse.get_pos()
            player_rect.center = mouse_pos      

    # Update the window
    window.fill( DARK_BLUE )
    pygame.draw.rect( window, RED,    central_rect, 1 )     # centre rect
    pygame.draw.rect( window, YELLOW, player_rect,  1 )     # player's mouse rect

    # IFF the rectangles overlap, paint the overlap
    if ( player_rect.colliderect( central_rect ) ):
        overlap_rect = rectIntersection( player_rect, central_rect )
        pygame.draw.rect( window, GREEN, overlap_rect )

    pygame.display.flip()

    # Clamp FPS
    clock.tick_busy_loop( WINDOW_MAXFPS )

pygame.quit()

如果需要像素完美的碰撞,请使用Surface.subsurface() 和重叠矩形的坐标在两个精灵的位图掩码上。这为您提供了两个位掩码(掩码 A 和掩码 B),您知道它们以某种方式重叠。

我想不出一种快速的方法来找到这两个子部分之间重叠的准确像素。然而,遍历每个掩码像素非常容易,找到都“打开”的掩码 A 和掩码 B 对。显然这一步需要将屏幕坐标转换为精灵坐标,但这只是精灵当前屏幕xy的减法。

您真正想要的是位图交点的“边缘”,但这是另一个问题。

【讨论】:

  • 感谢您的回答。我会转过头来玩代码:) 也非常感谢您实际回答我的问题。看着我得到的 cmets,我有点觉得我不是在说英语(现在是重复的标志 ^^)
  • @Woww - 谢谢你的拥抱!人们非常会发布问题,然后期望得到一个经过全面设计、调试和注释的答案。一旦你看到其中的一些,当问题开始看起来像“给我密码!”时,你就会变得有点敏感。要求。这就是为什么人们有时会对纯文字问题有点刻薄。我,我只是来找乐子的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-28
  • 1970-01-01
  • 2015-02-22
相关资源
最近更新 更多