python - Pygame - 返回碰撞位置
问题描述
如何获得两个精灵之间碰撞的确切位置?
如果有多个像素重叠,可能会得到一个像素位置列表。我想在那个时候产生粒子,并且其他功能也需要它。
伪代码:
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)
解决方案
基于答案: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 对。很明显,这一步需要将屏幕坐标转换为精灵坐标,但这只是精灵当前屏幕的减法x
和y
.
您真正想要的是位图交点的“边缘”,但这是另一个问题。
推荐阅读
- java - Spark Dataset - 如何通过修改现有列值来创建新列
- ruby-on-rails - Rails 多个搜索参数和默认值
- html - Emmet 扩展缩写在具有属性的 Visual Studio Code 中不起作用
- ssl - 设置配置了 SSL 的 Nginx 服务器
- joomla3.0 - 有没有人实施过 joomla 3 内容审批工作流程
- consul - 如何在 consul 中删除 wan 连接的数据中心
- c# - ASP.NET Core:具有范围的 JWT 令牌
- javascript - JavaScript - - 委托设计模式的类设计模式,Object.create() 的新构造函数
- wordpress - 找不到wordpress页面,wordpress安装在子目录下
- c# - Neo4j 架构迁移?