这是我第一次尝试使用遮罩碰撞,但找不到这种特定情况(多边形和精灵遮罩碰撞)的参考。
我希望精灵的能力,以检测其他精灵使用'视野'的方法。下面是我的Pygame应用程序的一个例子:
一堆蠕虫,显示其FOV以进行调试。在这种情况下,我希望他们看到小绿色。首先,我可以将FOV生成为多边形。我在pygame.display Surface(简称program.screen)上绘制它。然后,我检查精灵组中的每个‘目标‘,并检查多边形和目标之间的矩形碰撞-工作正常。所以所有的数学和计算都是正确的,但我不能得到下一位与面具面具碰撞工作。在我所附的代码中,print(“Detection”)语句永远不会被调用。
#Check if entity can detect its target given its fov
#
#@param entity: pygame.sprite.Sprite object performing the look() function
#@param fov: The angle and depth of view of 'entity', in the form of [angle (degrees), depth (pixels)]
#@param target: pygame.sprite.Sprite object the 'entity' is looking out for
#@param program: the main instance that runs and handles the entire application
def look(entity, fov, target, program):
r = fov[1] * np.cos(np.pi / 180 * fov[0])
coords_1 = (r * np.sin(entity.rot * np.pi / 180) + entity.x, r * np.cos(entity.rot * np.pi / 180) + entity.y)
coords_2 = (r * np.sin((entity.rot + 2*fov[0]) * np.pi / 180) + entity.x, r * np.cos((entity.rot + 2*fov[0]) * np.pi / 180) + entity.y)
poly_coords = ((entity.x, entity.y), coords_1, coords_2) # The coordinates of the fov
view = pygame.draw.polygon(program.screen, WHITE, poly_coords) # Draw the fov white for indication
pygame.display.update(view)
# Iterate over all sprites
for i in program.all_sprites:
if isinstance(i, target):
# Rough check for if this item is colliding with the fov polygon
if view.colliderect(i.rect):
# Exact check if this item is roughly colliding with the fov polygon
mask = pygame.mask.from_surface(i.image)
if pygame.mask.from_surface(program.screen).overlap(mask, (0, 0)):
# For now, colour the polygon red as indication
signal = pygame.draw.polygon(program.screen, RED, [(entity.x, entity.y), coords_1, coords_2])
print("Detection")
pygame.display.update(signal)
当我使用
if pygame.sprite.collide_mask(mask, pygame.mask.from_surface(program.screen)):
检查面具时我会得到一个
AttributeError: 'pygame.mask.Mask' object has no attribute 'rect'
我还尝试在不同的表面上绘制多边形,结果与第一个代码相同(未检测到):
def look(entity, fov, target, program):
r = fov[1] * np.cos(np.pi / 180 * fov[0])
coords_1 = (r * np.sin(entity.rot * np.pi / 180) + entity.x, r * np.cos(entity.rot * np.pi / 180) + entity.y)
coords_2 = (r * np.sin((entity.rot + 2*fov[0]) * np.pi / 180) + entity.x, r * np.cos((entity.rot + 2*fov[0]) * np.pi / 180) + entity.y)
poly_coords = ((entity.x, entity.y), coords_1, coords_2) # The coordinates of the fov
view_layer = pygame.Surface((500, 500)) # some random size big enough to hold the fov
#view_layer.fill(BLUE)
view = pygame.draw.polygon(view_layer, WHITE, poly_coords) # Draw the fov white for indication
pygame.display.update(view)
program.screen.blit(view_layer, (min(poly_coords[0]), max(poly_coords[1])))
pygame.display.update(view)
# Iterate over all sprites
for i in program.all_sprites:
if isinstance(i, target):
# Rough check for if this item is colliding with the fov polygon
if view.colliderect(i.rect):
# Exact check if this item is roughly colliding with the fov polygon
mask = pygame.mask.from_surface(i.image)
if pygame.mask.from_surface(view_layer).overlap(mask, (0, 0)):
# For now, colour the polygon red as indication
signal = pygame.draw.polygon(program.screen, RED, [(entity.x, entity.y), coords_1, coords_2])
print("Detection")
pygame.display.update(signal)
我尝试的方法有什么问题,或者有更好的方法吗?
谢谢,克雷斯
2条答案
按热度按时间fumotvh31#
pygame.sprite.collide_mask()
用于pygame.sprite.Sprite
对象。pygame.sprite.collide_mask()
的参数是sprites而不是masks。sprite对象需要具有属性.rect
和.mask
。需要rect
属性来计算屏幕上对象之间的位置偏移,mask
是包含位掩码的pygame.mask.Mask
对象。例如
另请参阅如何制作碰撞遮罩?
如果您不使用
pygame.sprite.Sprite
,则必须使用pygame.mask.Mask.overlap
。例如,如果你有两个
pygame.mask.Mask
对象(mask1
,mask2
),分别位于(x1
,y1
)和(x2
,y2
):另请参阅PyGame中的遮罩之间的碰撞和PyGame与遮罩的碰撞不起作用。
w8f9ii692#
感谢你的评分还有其他问题,以及与我的代码,这就是为什么我认为张贴这作为答案。
我做了一个单独的表面来画多边形。更多的数学涉及到定义多边形内接的矩形,并将原始(显示)多边形坐标转换到新的表面上。曲面的大小应与计算的边界矩形相同。
至于面具计算本身,基本上就是Rabbid76的答案。
辅助函数: