- 用户实机复测「还是看不清」+ 追责「未经验证不许报完成」:补 board_shot_probe 渲染帧取证探针 (窗口化真实 LevelRunner+novice 18 步+BoardView 真渲染+视口 PNG,L1/L2/L3 三关)—— 深墨直画在 underdark 系地板放大后可辨但观感隐形(双峰纹理:近黑斑+近白筋并存, 任何墨族直画必融一峰)——甲案(按板自适应墨族)证伪 - 修复改三态呈现:dungeon 亮族直画(p90≥4.5/均值≥2.5)/中暗板深墨直画(均值门收紧 3.0)/ 双峰板色牌垫底(素牌+深墨 12:1 纹理免疫——v2 色牌形制复役) - 目视验证(本会话亲验渲染帧):L2/L3 数字素牌深墨清晰可读,取证图 artwork/qa-board-shots-20261001/(board_L1/L2/L3 + _zoom_L2 证伪对照) - 机检同步:terrain_tile_sets_test 三态断言 19/19;art-bible v3.4(三态+目视验证面入流程); 冒烟断言随新语义更新(雷当量 6/8/8 钉值/大奖励与 L3 上限允许模拟档购血叠加——v3.4 购物 改变 max_hp 序列语义,非功能回归) - 轻闸:冒烟 596/0+四探针 PASS;剂量-响应点(slip 半档 N=100)L1 36%/战役 1%——悬崖三点齐
63 lines
2.6 KiB
GDScript
63 lines
2.6 KiB
GDScript
# VERTICAL SLICE - NOT FOR PRODUCTION
|
|
# 棋盘渲染帧取证探针(2026-10-01——数字墨族按板自适应修复的目视验证面:机检≠看得清)。
|
|
# 必须**窗口化**运行(headless 无渲染面):
|
|
# Godot_console.exe --path . res://smoke/board_shot_probe.tscn -- <输出目录>
|
|
# 流程:L1/L2/L3 各起一板(真实 LevelRunner+settle_batch 驱动 ~18 步 novice——自然揭示数字/旗),
|
|
# BoardView 真渲染,frame_post_draw 同步后抓视口 PNG。零存档触碰(无 save_manager 引用)。
|
|
extends Node
|
|
|
|
const AutoPlayer := preload("res://smoke/auto_player.gd")
|
|
|
|
|
|
func _ready() -> void:
|
|
var args := OS.get_cmdline_user_args()
|
|
var out := args[0] if args.size() >= 1 and args[0] != "" else "user://board-shots"
|
|
DirAccess.make_dir_recursive_absolute(out)
|
|
await get_tree().process_frame
|
|
var db = load("res://core/config_db.gd").new()
|
|
var ok: bool = db.load_tables("res://data/tables", true)
|
|
if not ok:
|
|
push_error("[board_shot] 表加载失败")
|
|
get_tree().quit(1)
|
|
return
|
|
var ui_font: Font = load("res://presentation/views/ui_kit.gd").load_font(load("res://presentation/views/ui_kit.gd").FONT_UI)
|
|
var targets := [[1, "L1_dungeon"], [2, "L2_underdark"], [3, "L3_deep_underdark"]]
|
|
for t in targets:
|
|
var level_index: int = t[0]
|
|
var tag: String = t[1]
|
|
var rng = load("res://core/rng_service.gd").new()
|
|
rng.set_master_seed(420000 + level_index)
|
|
var runner = load("res://core/level_runner.gd").new(db, rng)
|
|
if not runner.start_level(level_index, 420000 + level_index, {}, 0):
|
|
push_error("[board_shot] 开关失败 level=%d" % level_index)
|
|
get_tree().quit(1)
|
|
return
|
|
var settlement = runner.current_battle()
|
|
for i in range(18):
|
|
var act: Dictionary = AutoPlayer.novice_action(settlement.minesweeper)
|
|
var kind := String(act.get("kind", "stop"))
|
|
if kind == "stop":
|
|
break
|
|
var op := kind
|
|
if kind == "flag":
|
|
op = "flag_place"
|
|
settlement.minesweeper.settle_batch([{"action": op, "cell": act.get("cell")}])
|
|
var view = load("res://presentation/views/board_view.gd").new()
|
|
view.size = Vector2(900, 900)
|
|
view.position = Vector2(40, 40)
|
|
if ui_font != null:
|
|
view.set_world_font(ui_font)
|
|
add_child(view)
|
|
view.rebuild(settlement.minesweeper.current_board(), settlement.minesweeper)
|
|
for i in range(6):
|
|
await get_tree().process_frame
|
|
await RenderingServer.frame_post_draw
|
|
var img := get_viewport().get_texture().get_image()
|
|
var path := "%s/board_%s.png" % [out, tag]
|
|
img.save_png(path)
|
|
print("[board_shot] saved %s (%dx%d)" % [path, img.get_width(), img.get_height()])
|
|
view.queue_free()
|
|
await get_tree().process_frame
|
|
print("[board_shot] done")
|
|
get_tree().quit(0)
|