如何在on_click事件及鼠标悬停中调整游戏地图的鼠标坐标?
鼠标坐标转换与交互事件处理方案
核心坐标转换逻辑
先明确屏幕坐标转世界坐标的核心公式——因为相机拖拽会实时改变视口位置,所以每次计算都要基于当前相机的视口左下角坐标:世界坐标 = 调整后的鼠标屏幕坐标 + 相机视口左下角坐标
注意大部分系统的屏幕坐标原点是左上角,而游戏世界通常以左下角为原点,所以需要先反转鼠标的Y轴:调整后的鼠标Y = 屏幕高度 - 鼠标原始Y
再代入公式完成转换。
点击事件(on_click/UIMouseEvent)中的坐标处理
- 在点击事件回调里,先从事件对象中获取鼠标的原始屏幕坐标(
x、y) - 按上述步骤转换为世界坐标
- 遍历所有可交互建筑,检查世界坐标是否落在建筑的碰撞范围内(比如矩形区域的坐标判断)
- 命中则触发对应建筑的点击逻辑
示例伪代码:
def on_click(event): # 获取原始鼠标屏幕坐标 screen_x = event.x screen_y = event.y # 转换为以左下角为原点的屏幕坐标 adjusted_screen_y = screen_height - screen_y # 转世界坐标 world_x = screen_x + camera.viewport_left world_y = adjusted_screen_y + camera.viewport_bottom # 检测建筑点击 for building in buildings: if (building.x <= world_x <= building.x + building.width and building.y <= world_y <= building.y + building.height): building.on_click() break
悬停事件的持续坐标处理
悬停需要每帧更新鼠标坐标,不能只依赖单次事件:
- 在游戏主循环或全局更新回调中,实时获取当前鼠标的屏幕坐标
- 转换为世界坐标后,每帧检查是否落在某个建筑的碰撞范围内
- 切换建筑的悬停状态(比如高亮),同时处理离开悬停的情况(上一帧悬停的建筑未命中时,取消高亮)
示例伪代码:
last_hovered_building = None def update(delta_time): # 实时获取鼠标屏幕坐标 screen_x = input.get_mouse_x() screen_y = input.get_mouse_y() adjusted_screen_y = screen_height - screen_y world_x = screen_x + camera.viewport_left world_y = adjusted_screen_y + camera.viewport_bottom current_hovered = None for building in buildings: if (building.x <= world_x <= building.x + building.width and building.y <= world_y <= building.y + building.height): current_hovered = building break # 更新悬停状态 if current_hovered != last_hovered_building: if last_hovered_building: last_hovered_building.end_hover() if current_hovered: current_hovered.start_hover() last_hovered_building = current_hovered
关键注意点
- 相机拖拽时要实时更新
viewport_left和viewport_bottom这两个核心坐标,确保转换逻辑始终准确 - 如果使用游戏引擎(如Unity、Godot),引擎通常提供内置的坐标转换方法(比如Unity的
Camera.ScreenToWorldPoint),但核心逻辑和手动转换一致 - 大量建筑的场景下,建议用空间划分(比如网格分区)优化碰撞检测,避免每帧遍历所有建筑
内容的提问来源于stack exchange,提问作者MeCephi
相关产品推荐
相关产品推荐

