本机首次具备引擎自验证能力后的首跑修复。四条命令 + 主场景 180 帧全绿: - --import exit=0(漂移门 git diff data/build 空) - --validate-only exit=0 RESULT: PASS - test_runner exit=0 PASS(584 检查,8/8 用例) - sim_main exit=0(报告落 tests/sim_reports/report-2026-10-20.json) - 主场景 --quit-after 180 exit=0 零 ERROR/WARNING(F5 可玩) 预定位错误(team-lead 清单): - R1 economy_state.gd:596 enthone_ready -> enthrone_ready(单点故障连锁) - R2 hud_root.gd:142,160 HorizontalAlignment.LEFT -> HORIZONTAL_ALIGNMENT_LEFT - R3 boss_arena.gd 补 var _pending_hall_index := -1 - R4 hall_band_world.gd:95 删 "_ = ext"(非法语句;--check-only 定位) - R5 sheet_importer._type_ok 补 object->Dictionary / array->Array(9 条假违规) - R6 game_state.gd econ==null 防护(防 autoload 崩每帧刷错打满管道挂死) 引擎新暴露错误: - R7 prestige_model floor() Variant 推断(4.7.2 按错误)连锁编译失败 - R8 gates.gd var pass 保留字;R9 %g/%.*f 格式符 ×6 处 - R10 greedy.gd Dictionary.get() 推断;R11 probe_p1 条件表达式推断 - R12 测试用例 data 参数统一标 BalanceData(无类型参数成员调用返 Variant) - R13 boss_battle 用例 Dictionary 下标运算显式 float 化 - R14 band_world_root.compute_ranges 返回 Array[Vector2](类型化数组不隐式转换) 测试侧数值修正(根因已核实,实现符合设计): - gen3 可购断言 merit 1000->2000(800 文书 + 1200 首购) - 开场伤害断言改"循环至 ACTIVE 即停"(INTRO 结束 tick 不计军列伤) - 容量断言预算 30->34s(战斗真实给 intro 3s + active 30s) 工程加固: - EconomyState 红线守卫首次越线才报(sim 长跑日志 6.5MB->1KB) - stage_world.gd stretch=false(SubViewport 手动尺寸驱动生效) 知识缺口登记:docs/engineering/2026-10-20-f-engine-first-run-notes.md sim 首轮数据:主口径 11/14 过(#2/#3/#12/#13/#14 FAIL 待文策渊裁定)
185 lines
6.3 KiB
GDScript
185 lines
6.3 KiB
GDScript
extends Node
|
||
|
||
# ============================================================================
|
||
# 探针 P1 —— Godot 4.7 hint_screen_texture / SCREEN_TEXTURE 语义
|
||
# 架构依据:§11 P1 / §5.2(ADR-2 单趟 fused 后处理的 CanvasLayer 拓扑)
|
||
# 实测手册:docs/engineering/2026-10-19-f-w1-probe-p1-manual.md
|
||
# 结论回填:docs/engineering/probes/P1-result.md
|
||
#
|
||
# 三问:
|
||
# ① 背景/世界色是否含入 SCREEN_TEXTURE 采样(后处理 L1 能否看见 L0)
|
||
# ② CanvasLayer 排序语义(L1 后处理在 L0 世界之上、L2 UI 之下)
|
||
# ③ UI 层是否被后处理污染(UI 保持 crisp、不被 shader 调制)
|
||
#
|
||
# 场景在 _ready() 中代码化搭建(不手写 .tscn 降低出错面)。
|
||
# 键位:1 直通 | 2 反色 | 3 红染 | 4 纯绿 | V 显/隐后处理层 | S 截图 user:// | Esc 退出
|
||
# ============================================================================
|
||
|
||
enum PostMode { PASSTHROUGH, INVERT, RED_TINT, SOLID_GREEN }
|
||
|
||
var _post: ColorRect
|
||
var _post_visible := true
|
||
var _mode: int = PostMode.PASSTHROUGH
|
||
var _mat: ShaderMaterial
|
||
var _hud: Label
|
||
var _shot_n := 0
|
||
|
||
|
||
func _ready() -> void:
|
||
_build_world()
|
||
_build_post()
|
||
_build_ui()
|
||
_print_environment()
|
||
|
||
|
||
func _build_world() -> void:
|
||
var world := CanvasLayer.new()
|
||
world.name = "L0_World"
|
||
world.layer = 0
|
||
add_child(world)
|
||
|
||
var bg := ColorRect.new()
|
||
bg.name = "Background"
|
||
bg.color = Color("#23384F") # 已知底色:后处理里能看见它 = 世界含入采样
|
||
bg.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||
world.add_child(bg)
|
||
|
||
var marker := ColorRect.new()
|
||
marker.name = "WorldMarker"
|
||
marker.color = Color("#D08A2E")
|
||
marker.position = Vector2(400, 240)
|
||
marker.size = Vector2(480, 240)
|
||
world.add_child(marker)
|
||
|
||
var world_label := Label.new()
|
||
world_label.name = "WorldLabel"
|
||
world_label.text = "L0 World: bg #23384F + marker #D08A2E"
|
||
world_label.position = Vector2(24, 180)
|
||
world_label.add_theme_color_override("font_color", Color.WHITE)
|
||
world.add_child(world_label)
|
||
|
||
|
||
func _build_post() -> void:
|
||
var post_layer := CanvasLayer.new()
|
||
post_layer.name = "L1_PostProcess"
|
||
post_layer.layer = 1
|
||
add_child(post_layer)
|
||
|
||
var sh := load("res://tests/probe_p1_screen_texture/probe_p1.gdshader") as Shader
|
||
_mat = ShaderMaterial.new()
|
||
_mat.shader = sh
|
||
_mat.set_shader_parameter("mode", PostMode.PASSTHROUGH)
|
||
|
||
_post = ColorRect.new()
|
||
_post.name = "PostProcessRect"
|
||
_post.material = _mat
|
||
_post.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||
_post.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||
post_layer.add_child(_post)
|
||
|
||
|
||
func _build_ui() -> void:
|
||
var ui_layer := CanvasLayer.new()
|
||
ui_layer.name = "L2_UI"
|
||
ui_layer.layer = 2
|
||
add_child(ui_layer)
|
||
|
||
var root := Control.new()
|
||
root.name = "UIRoot"
|
||
root.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||
ui_layer.add_child(root)
|
||
|
||
# UI 样本:四色板 + 一块纯白。被后处理污染 = 颜色变了/出现着色/纸纹
|
||
var chip_colors := [
|
||
Color("#1A1614"), Color("#EDE6D8"), Color("#B03A2E"),
|
||
Color("#3A5A6B"), Color("#FFFFFF"),
|
||
]
|
||
var chip_names := ["墨 #1A1614", "骨白 #EDE6D8", "朱砂 #B03A2E", "靛 #3A5A6B", "纯白 #FFFFFF"]
|
||
for i in chip_colors.size():
|
||
var chip := ColorRect.new()
|
||
chip.name = "Chip%d" % i
|
||
chip.color = chip_colors[i]
|
||
chip.size = Vector2(200, 40)
|
||
chip.position = Vector2(960, 48 + i * 56)
|
||
root.add_child(chip)
|
||
var lbl := Label.new()
|
||
lbl.name = "ChipLabel%d" % i
|
||
lbl.text = chip_names[i]
|
||
lbl.position = Vector2(1010, 54 + i * 56)
|
||
if chip_colors[i].get_luminance() > 0.5:
|
||
lbl.add_theme_color_override("font_color", Color.BLACK)
|
||
else:
|
||
lbl.add_theme_color_override("font_color", Color.WHITE)
|
||
root.add_child(lbl)
|
||
|
||
_hud = Label.new()
|
||
_hud.name = "HUDHelp"
|
||
_hud.text = _help_text()
|
||
_hud.position = Vector2(24, 648)
|
||
_hud.add_theme_color_override("font_color", Color.WHITE)
|
||
root.add_child(_hud)
|
||
|
||
|
||
func _help_text() -> String:
|
||
var mode_names := ["PASS直通", "INVERT反色", "RED红染", "GREEN纯绿"]
|
||
# 条件表达式含数组下标 → Variant;`:=` 推断触发 INFERENCE_ON_VARIANT(4.7.2 按错误)→ 显式标注
|
||
var mode_name: String = mode_names[_mode] if _mode >= 0 and _mode < mode_names.size() else "?"
|
||
return "探针 P1 | 1 直通 2 反色 3 红染 4 纯绿 | V 显/隐后处理层(当前:%s)| S 截图到 user:// | Esc 退出 | 当前 mode=%s" % [
|
||
"显示" if _post_visible else "隐藏", mode_name]
|
||
|
||
|
||
func _input(event: InputEvent) -> void:
|
||
var key_event := event as InputEventKey
|
||
if key_event != null and key_event.pressed and not key_event.echo:
|
||
match key_event.keycode:
|
||
KEY_1:
|
||
_set_mode(PostMode.PASSTHROUGH)
|
||
KEY_2:
|
||
_set_mode(PostMode.INVERT)
|
||
KEY_3:
|
||
_set_mode(PostMode.RED_TINT)
|
||
KEY_4:
|
||
_set_mode(PostMode.SOLID_GREEN)
|
||
KEY_V:
|
||
_post_visible = not _post_visible
|
||
_post.visible = _post_visible
|
||
_hud.text = _help_text()
|
||
KEY_S:
|
||
_screenshot()
|
||
KEY_ESCAPE:
|
||
get_tree().quit()
|
||
|
||
|
||
func _set_mode(m: int) -> void:
|
||
_mode = m
|
||
_mat.set_shader_parameter("mode", m)
|
||
_hud.text = _help_text()
|
||
var mode_names := ["PASS直通", "INVERT反色", "RED红染", "GREEN纯绿"]
|
||
print("P1 mode → %d(%s)" % [m, mode_names[m] if m >= 0 and m < mode_names.size() else "?"])
|
||
|
||
|
||
func _screenshot() -> void:
|
||
var tex := get_viewport().get_texture()
|
||
if tex == null:
|
||
push_warning("P1: viewport texture 为空,回退:请用系统截图(Win+Shift+S)")
|
||
return
|
||
var img := tex.get_image()
|
||
if img == null:
|
||
push_warning("P1: get_image() 失败,回退:请用系统截图(Win+Shift+S)")
|
||
return
|
||
var path := "user://p1_mode_%d_%02d.png" % [_mode, _shot_n]
|
||
_shot_n += 1
|
||
var err := img.save_png(path)
|
||
print("P1 screenshot → ", path, " err=", err)
|
||
|
||
|
||
func _print_environment() -> void:
|
||
var v := Engine.get_version_info()
|
||
print("=== P1 probe 环境(截图请连同此段一起归档)===")
|
||
print("godot: %d.%d.%d %s" % [int(v.major), int(v.minor), int(v.patch), str(v.status)])
|
||
print("rendering_method: ", ProjectSettings.get_setting("rendering/renderer/rendering_method"))
|
||
print("adapter: ", RenderingServer.get_video_adapter_name())
|
||
print("viewport: ", get_viewport().get_visible_rect().size)
|
||
print("stretch: ", ProjectSettings.get_setting("display/window/stretch/mode"), " / ", ProjectSettings.get_setting("display/window/stretch/aspect"))
|
||
print("=== 键位:1 直通 | 2 反色 | 3 红染 | 4 纯绿 | V 显隐后处理 | S 截图 | Esc 退出 ===")
|