7.0 KiB
7.0 KiB
Godot 农场地图拖动功能检验
日期:2026-05-12
范围
本轮检验对象是 Godot 主农场的地图拖动预览能力:
- 地图可拖动范围最大为
2000x2000。 - 默认进入农场时,土地内容位于地图中心。
- 背景图不足时先使用现有背景拉伸铺底,不额外补图。
- 拖动地图不能误触土地菜单、扩建弹窗或长按提示。
- 缩放、建筑点击、扩建入口和固定 HUD 不能被拖动能力破坏。
模块拆分结论
该功能已经按现有架构拆出,主逻辑没有堆回 game_scene.gd。
| 模块 | 职责 | 当前判断 |
|---|---|---|
scripts/ui/farm/farm_viewport_controller.gd |
农场内容根节点、2000x2000 地图、默认居中、单指/鼠标拖动、双指/Ctrl 滚轮缩放、边界 clamp |
拖动功能核心已独立 |
scripts/ui/farm/farm_interaction_coordinator.gd |
土地点击、长按、菜单、背包;只通过 on_scene_pan_started/finished 抑制拖动误触 |
和地图拖动保持低耦合 |
scripts/ui/game_scene_runtime_assembler.gd |
创建缩放控制器和土地交互模块,并连接拖动开始/结束回调 | 只做装配 |
scripts/ui/game_scene.gd |
当前只保留扩建图标透明命中区的坐标同步 | 仍有一个可继续迁出的 UI 坐标桥接点 |
控制器已命名为 FarmViewportController,避免只体现缩放而遗漏拖动视口职责。
当前实现
地图边界
地图范围使用常量:
const MAP_PREVIEW_SIZE := Vector2(2000.0, 2000.0)
拖动偏移由 _clamped_scene_offset() 限制:
var scaled_map_size := MAP_PREVIEW_SIZE * _zoom
var min_offset := _panel_size - scaled_map_size
clampf(value.x, minf(min_offset.x, 0.0), 0.0)
clampf(value.y, minf(min_offset.y, 0.0), 0.0)
以当前屏幕 640x960 为例:
| 缩放 | 缩放后地图 | X 偏移范围 | Y 偏移范围 | 结论 |
|---|---|---|---|---|
0.6667 |
约 1333x1333 |
[-693, 0] |
[-373, 0] |
缩小时仍有可预览区域,不露出黑边 |
1.0 |
2000x2000 |
[-1360, 0] |
[-1040, 0] |
满足 2000 地图拖动 |
1.3 |
2600x2600 |
[-1960, 0] |
[-1640, 0] |
放大后边界随缩放扩大 |
边界设计合理:偏移范围以“缩放后的地图尺寸 - 屏幕尺寸”为准,缩放和拖动共用同一套 clamp,不会在缩放后越界。
默认居中
默认进入时执行:
- 把
Ground、House、DogHouse、FenceBack、GameView、FenceFront、PetLayer移到FarmSceneRoot。 - 从
GameView下严格匹配Land+ 数字的节点计算土地包围盒。 - 将土地包围盒中心平移到
2000x2000地图中心。 - 将镜头偏移设为地图中心对准屏幕中心。
当前顺序是安全的:计算土地包围盒发生在 LandHitLayer、LandLight 等运行时节点创建前,因此不会把命中层误算进土地范围。
拖动与点击冲突
当前使用 PAN_DRAG_THRESHOLD = 8 像素区分点击和拖动。
- 移动距离小于阈值:仍按点击处理。
- 移动距离达到阈值:进入地图拖动。
- 拖动开始时调用
FarmInteractionCoordinator.on_scene_pan_started()。 - 拖动结束后调用
on_scene_pan_finished(),延迟清理抑制标记。
土地点击被抑制的路径:
FarmViewportController pan started
-> FarmInteractionCoordinator.on_scene_pan_started()
-> stop long press timer
-> suppress next land press
-> hide selection UI
该设计能避免“拖动土地后弹出土地菜单或扩建弹窗”的误触。
固定 UI 与农场内容分离
只迁移农场内容到 FarmSceneRoot,顶部 HUD、左侧按钮、底部世界/家园按钮仍留在主场景固定层。因此拖动地图不会带动 HUD。
背景策略
当前使用 FarmZoomBackdrop 将原背景拉伸到 2000x2000,并隐藏原 Ground。这符合“背景图不够先不用管”的要求。后续补齐大地图背景时,只需要替换 FarmZoomBackdrop 的纹理来源,不需要重写拖动逻辑。
功能检验结果
| 检验项 | 结果 |
|---|---|
| 默认土地在视野中心 | 通过 |
| 鼠标拖动地图可移动视野 | 通过 |
| 拖动后不弹扩建面板 | 通过 |
| 拖动后不弹土地菜单 | 通过 |
| HUD 不随地图拖动 | 通过 |
| Web 导出后可运行 | 通过 |
| smoke 主流程 | 通过 |
截图记录:
docs/ui-baseline/godot-map-pan-final-default.pngdocs/ui-baseline/godot-map-pan-final-after-drag.pngdocs/ui-baseline/godot-map-pan-rename-default.pngdocs/ui-baseline/godot-map-pan-rename-after-drag.png
已执行验证
godot --headless --path godot/FarmGodot --check-only --script res://scripts/ui/farm/farm_viewport_controller.gd
godot --headless --path godot/FarmGodot --check-only --script res://scripts/ui/farm/farm_interaction_coordinator.gd
godot --headless --path godot/FarmGodot --check-only --script res://scripts/ui/game_scene_runtime_assembler.gd
godot --headless --path godot/FarmGodot --check-only --script res://scripts/ui/game_scene.gd
godot --headless --path godot/FarmGodot --script res://tools/verify_p0.gd
godot --headless --path godot/FarmGodot --import --quit
godot --headless --path godot/FarmGodot --export-release Web build/web/index.html
npm run smoke:godot:web
浏览器验证目标:
http://127.0.0.1:8792/index.html
边界风险
| 风险 | 当前影响 | 建议 |
|---|---|---|
2000x2000 固定在控制器常量里 |
后续如果不同地图皮肤尺寸不同,需要改代码 | 改成从 game_scene_runtime_assembler.gd 的 constants 注入 |
| 建筑直接命中仍是按点击入口处理 | 拖动从建筑区域开始时,后续可能需要更严格的 tap/release 判定 | 若出现误触,把农场建筑 direct hit 改为 release 后、且未超过拖动阈值才触发 |
| 缩放没有围绕双指中心或鼠标位置缩放 | 当前可用,但放大时视角体验不够细 | 后续按手势中心调整 _scene_offset |
| 没有惯性滑动和边界回弹 | 当前符合第一版预览需求 | 后续如果要接近原生手感,可加轻量 Tween,但要避免 _process 常驻计算 |
优化优先级
P0 暂无阻断问题。
P1:
- 将地图尺寸从常量改为装配层配置,便于不同背景/地图皮肤切换。
- 把扩建图标命中区同步从
game_scene.gd迁到SceneHitRouter或农场交互模块,进一步减薄主场景。 - 建筑 direct hit 改为 tap 语义,避免未来拖动从房屋/狗窝起手时误触面板。
已处理:
FarmSceneZoomController已重命名为FarmViewportController,文件同步改为farm_viewport_controller.gd。- 土地包围盒匹配已从
Land*改为Land+ 数字,避免LandPreview*这类装饰节点被纳入默认居中计算。
P2:
- 增加缩放中心保持逻辑,让双指缩放时手指中点下的地图内容保持稳定。
- 增加可选惯性拖动和边界阻尼。
- 背景素材补齐后,把
FarmZoomBackdrop改为真实大图或分块贴图,避免拉伸纹理。