2026-05-13開發日誌
- 日期:2026-05-13
- 專案:Cá xấu Duckduck
今日總結
解決 power_puzzle 在手機上管線位置跑掉的問題,並修正 PuzzleBox 定位方式,讓謎題格線在任何螢幕尺寸上都能正確對齊背景圖框框。
問題一:座標系統不一致(Control vs Node2D)
原因
_cell_center() 和 _get_cell_at() 用的是 _puzzle_box.position(UI 座標), 但 Sprite2D 放在 PipeContainer(Node2D,canvas 座標)。 兩個座標系在電腦模擬時剛好對齊,換到手機不同解析度就跑掉。
修法
gdscript
# 舊
_puzzle_box.position.x + ...
# 新
var origin := _puzzle_box.get_global_rect().position
origin.x + ...get_global_rect().position 回傳的是 canvas 空間的實際位置,與 Node2D 一致。
問題二:_ready() 時 Layout 尚未完成
原因
_ready() 被呼叫時,Godot 還沒完成 Control 節點的 Layout 計算, 所以 _puzzle_box.size 和 get_global_rect() 回傳的值不正確,導致格線尺寸算錯。
修法
將 grid 建立邏輯移出 _ready(),等一幀後再執行:
gdscript
func _ready() -> void:
_fade_rect.color = Color(0, 0, 0, 1)
_fade_in()
_load_textures()
_close_btn.pressed.connect(_on_close_pressed)
await get_tree().process_frame # 等 Layout 完成
_setup_grid()
func _setup_grid() -> void:
var rect := _puzzle_box.get_global_rect()
var pad_x := rect.size.x * 0.05
var pad_y := rect.size.y * 0.05
_tile_size = minf(
(rect.size.x - 2 * pad_x - (GRID_COLS - 1) * TILE_GAP) / GRID_COLS,
(rect.size.y - 2 * pad_y - (GRID_ROWS - 1) * TILE_GAP) / GRID_ROWS
)
_grid_offset = Vector2(
(rect.size.x - (_tile_size * GRID_COLS + (GRID_COLS - 1) * TILE_GAP)) * 0.5,
(rect.size.y - (_tile_size * GRID_ROWS + (GRID_ROWS - 1) * TILE_GAP)) * 0.5
)
_build_grid()
_update_flow()Padding 改為螢幕比例(各邊 5%),移除原本寫死的 -30.0 px。
問題三:PuzzleBox 用固定 pixel 定位
原因
PuzzleBox 原本用 layout_mode = 0 加上固定 offset(879, 167, 1640, 1006), 這些是針對設計解析度 2560×1080 的絕對座標,換手機就全部跑位。
修法
改為 anchor 比例定位:
anchor_left = 0.326
anchor_top = 0.114
anchor_right = 0.658
anchor_bottom = 0.925這樣 PuzzleBox 永遠是螢幕寬高的固定百分比,不依賴任何固定尺寸。
問題四:背景圖 stretch_mode 導致 Y 軸比例跑掉
原因(核心問題)
| stretch_mode | 行為 | 問題 |
|---|---|---|
| 6(KEEP_ASPECT_COVERED) | 等比縮放填滿,超出部分裁切 | 不同螢幕裁切量不同,框框 % 位置跑掉 |
| 0(SCALE) | X / Y 各自獨立拉伸填滿 | 寬高比不同時,Y 軸拉伸量 ≠ X,左右正確但上下錯 |
| 5(KEEP_ASPECT_CENTERED) | 等比縮放置中,多出的空間加黑邊 | 框框在圖片中的比例永遠不變 ✓ |
最終修法
stretch_mode = 5圖片保持原始比例,框框的 % 位置在任何螢幕上都一致,anchor 值可以共用。
最終結果
- 手機與模擬器顯示一致 ✓
- 格線正確對齊背景圖框框 ✓
- 所有定位數值改為比例,無固定 px ✓
