Pygame中非主Surface上矩形与鼠标移动事件的碰撞检测问题
解决方案
你遇到的坐标不匹配是分层Surface渲染的常规场景,有两种成熟的处理方式,代码实现都非常简单:
方案1:将全局鼠标坐标转换为背包Surface的局部坐标做碰撞检测
这是最推荐的方案,不需要修改你现有物品坐标的存储逻辑,只需要在碰撞检测前做一步坐标换算:
- 用鼠标全局坐标减去背包Surface在主屏幕的坐标,得到鼠标相对于背包的局部坐标
- 直接用这个局部坐标和物品存储的、相对于背包的rect做碰撞检测即可
代码修改示例(碰撞检测部分)
if event.type == pygame.MOUSEMOTION and not gameMaster.textBlurbShowing and inventoryClicked: inv = player.inventory # 先判断鼠标是否在背包区域内,不在直接跳过,优化性能 if not inv.rect.collidepoint(event.pos): continue # 换算鼠标相对于背包的局部坐标 rel_mouse_x = event.pos[0] - inv.posx rel_mouse_y = event.pos[1] - inv.posy for item in inv.contents: if item.rect.collidepoint(rel_mouse_x, rel_mouse_y): print('Collided') # hover文本是绘制在主Surface上的,直接用全局鼠标坐标即可,加10偏移避免遮挡鼠标 hoverText(item.desc, (event.pos[0] + 10, event.pos[1] + 10))
方案2:计算物品在主屏幕的全局坐标做碰撞检测
如果你习惯用全局坐标做碰撞,也可以把物品的局部rect叠加背包的坐标,得到全局rect后再和鼠标坐标碰撞:
if event.type == pygame.MOUSEMOTION and not gameMaster.textBlurbShowing and inventoryClicked: inv = player.inventory for item in inv.contents: # 生成物品对应的全局rect global_item_rect = item.rect.move(inv.posx, inv.posy) if global_item_rect.collidepoint(event.pos): print('Collided') hoverText(item.desc, (event.pos[0] + 10, event.pos[1] + 10))
原理说明
Pygame本身没有内置的跨Surface坐标自动转换接口,这种手动坐标换算是分层渲染场景下的标准操作,逻辑轻量且易维护,不存在不合理的问题。
内容的提问来源于stack exchange,提问作者madmonkey
相关产品推荐
相关产品推荐

