按 code-conventions §1.4.1 第三轮定稿执行:core 22+schemas 18+presentation 根 14+views 28,全部头注 #→##、删日期/变更叙事/GDD 与架构反向链接/字段与域清单/机制描述,保留职责摘要+真实使用约束(防事故禁令/单一入口/信号契约每信号一行)。main.gd 31→5 行、save_manager 45→5 行、adventure_runner 37→5 行为最大单件。子代理分模块执行(波一 core+schemas、波二 presentation+views,并发≤2)。验收=tools/verify_comment_only_change.py 逐字节校验(82 文件头注区外逐行一致=零行为变更)+audit_file_headers 全绿;纯注释批免冒烟(先例 5843270)
107 lines
5.8 KiB
GDScript
107 lines
5.8 KiB
GDScript
## VERTICAL SLICE - NOT FOR PRODUCTION
|
||
## BoardWorld——棋盘 Node2D 世界根(SubViewport 内 CellUnit 容器):世界级去饱和材质与字体注入挂点。
|
||
## 无 class_name——使用方经 preload 引用。
|
||
extends Node2D
|
||
|
||
var board_font: Font = null # 字体注入槽位(null = ThemeDB.fallback_font——与旧 Button 缺省主题字体同源)
|
||
var hero: Sprite2D = null # 英雄单位精灵(棋盘小人贴图批 2026-09-25——移动实体独立于 CellUnit 格面
|
||
# 语义,计划书 §3.A;null = 未创建/随 rebuild 清场,BoardView.refresh 经
|
||
# ensure_hero 重建。texture 缺位时 BoardView 不调本方法=字形「人」回退路径)
|
||
|
||
|
||
# 英雄精灵惰性创建(幂等):脚底锚(offset 上移半高——scale.y 弹跳向脚底收敛不悬空)+ z_index=1
|
||
# 压格面之上(挥铲特效在 SubViewport 之外恒更上层,满足「格面之上、特效之下」叠序);NEAREST =
|
||
# SubViewport 缩放下像素清晰(默认 Linear 会糊);use_parent_material = 随世界去饱和材质灰化
|
||
#(结算期与 CellUnit 同口径——基批漏挂,本批补齐)。返回值便于 BoardView 即时落位。
|
||
# 脚下椭圆影(2026-09-26 用户裁决走 Godot 组件合成、贴图零改动):径向渐变纹理 ×黑色半透明
|
||
# modulate 压扁,挂英雄子件(z_index=-1 相对回落格面之上、英雄之下——位移/翻转/弹跳随父件
|
||
# 同步免费拿;尺寸换算归 BoardView.HERO_SHADOW_PX 常量)。纹理 filter 用 LINEAR 保渐变平滑
|
||
#(NEAREST 会把渐变打回条带)。
|
||
func ensure_hero(tex: Texture2D, shadow_px: Vector2, scale: float) -> Sprite2D:
|
||
if hero != null:
|
||
return hero
|
||
var grad := Gradient.new()
|
||
grad.set_color(0, Color(1, 1, 1, 1))
|
||
grad.set_color(1, Color(1, 1, 1, 0))
|
||
var shadow_tex := GradientTexture2D.new()
|
||
shadow_tex.gradient = grad
|
||
shadow_tex.width = 64
|
||
shadow_tex.height = 64
|
||
shadow_tex.fill = GradientTexture2D.FILL_RADIAL
|
||
shadow_tex.fill_from = Vector2(0.5, 0.5)
|
||
shadow_tex.fill_to = Vector2(0.5, 0.0)
|
||
var shadow := Sprite2D.new()
|
||
shadow.texture = shadow_tex
|
||
shadow.modulate = Color(0, 0, 0, 0.35)
|
||
shadow.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR
|
||
shadow.scale = shadow_px / (64.0 * scale) # 子件缩放叠父件 scale——目标屏幕尺寸 ÷ (纹理边 × 父档)
|
||
shadow.position = Vector2.ZERO # 椭圆中心 = 脚锚点(贴脚——上批 (0,2) 下坠让影子与脚脱开,用户报缺陷)
|
||
shadow.z_index = -1 # 相对父件回落:格面(z=0 树序在先)之上、英雄本体之下
|
||
shadow.use_parent_material = true # 随英雄链世界去饱和材质
|
||
hero = Sprite2D.new()
|
||
hero.texture = tex
|
||
hero.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
|
||
hero.centered = true
|
||
# 脚浮修正(2026-09-26,样张预筛发现+用户实机确认的登记缺陷——台账 169/175 移交):素材底部 7 行全透明
|
||
#(内容底 = 源 row 24,自中心 16-7.5=8.5px),旧 offset -16 按纹理底=内容底假设成立时脚悬空 8.5×1.5≈12.75px;
|
||
# 修正 offset.y = -8.5 → 内容底恰落 position(脚锚=格底往上 25% 线,台账 162 口径——头仍越上格沿)
|
||
hero.offset = Vector2(0.0, -8.5) # 纹理中心上移 8.5 源 px——position = 视觉脚底中点
|
||
hero.z_index = 1
|
||
hero.use_parent_material = true
|
||
add_child(hero)
|
||
hero.add_child(shadow)
|
||
return hero
|
||
|
||
# ── 立体悬崖(BoardView.set_cell_area / _update_world_size 单点驱动;厚度定稿 8px=中档 2026-09-24)──
|
||
var depth_px := 0.0: # 悬崖厚度(像素;0 = 平面)
|
||
set(v):
|
||
depth_px = v
|
||
queue_redraw()
|
||
var slab := Vector2.ZERO: # 网格矩形像素尺寸(不含悬崖外延)
|
||
set(v):
|
||
slab = v
|
||
queue_redraw()
|
||
var stride_px := 48.0: # 格步距(cell + SEP——列分隔缝对齐格边界)
|
||
set(v):
|
||
stride_px = v
|
||
queue_redraw()
|
||
var cols := 0: # 列数(正面悬崖竖缝数 = cols−1)
|
||
set(v):
|
||
cols = v
|
||
queue_redraw()
|
||
var mat: Color = UiKit.BRICK # 材质锚色(掩尘 #C9AF83 与 UiKit.BRICK 同值——T4 裸色收口改引单点;侧面由此派生明暗,BoardView 传入可覆写)
|
||
|
||
|
||
func _draw() -> void:
|
||
if depth_px <= 0.0 or slab == Vector2.ZERO:
|
||
return
|
||
var w := slab.x
|
||
var h := slab.y
|
||
var d := depth_px
|
||
var front := mat.darkened(0.55) # 正面悬崖(背光)
|
||
var right := mat.darkened(0.38) # 右侧悬崖(微受光)
|
||
# 正面悬崖带 + 右侧悬崖带
|
||
draw_rect(Rect2(0, h, w, d), front, true)
|
||
draw_rect(Rect2(w, 0, d, h + d), right, true)
|
||
# 正面列分隔竖缝(对齐格边界——ITB 悬崖列感)
|
||
for i in range(1, cols):
|
||
var x := float(i) * stride_px - 1.0
|
||
draw_rect(Rect2(x, h, 2.0, d), front.darkened(0.25), true)
|
||
# 岩层横纹(两条微暗横带——碎石层理)
|
||
draw_rect(Rect2(0, h + d * 0.38, w, 1.5), front.darkened(0.18), true)
|
||
draw_rect(Rect2(0, h + d * 0.72, w, 1.5), front.darkened(0.12), true)
|
||
# 悬崖口沿高光(顶面与悬崖交界 1px 亮线——倒角受光)
|
||
draw_rect(Rect2(0, h, w, 1.0), mat.lightened(0.18), true)
|
||
draw_rect(Rect2(w, 0, 1.0, h), mat.lightened(0.12), true)
|
||
# 顶面接触 AO(网格内侧贴边 2px 暗带——顶面陷进阴影的衔接感)
|
||
draw_rect(Rect2(0, h - 2.0, w, 2.0), Color(0, 0, 0, 0.18), true)
|
||
draw_rect(Rect2(w - 2.0, 0, 2.0, h), Color(0, 0, 0, 0.14), true)
|
||
# 底线(悬崖最底 2px 最暗——收边)
|
||
draw_rect(Rect2(0, h + d - 2.0, w + d, 2.0), front.darkened(0.35), true)
|
||
# 底部悬浮影(中厚档起——悬浮岛离地感;三层渐隐)
|
||
if d >= 8.0:
|
||
var layers := [Color(0, 0, 0, 0.16), Color(0, 0, 0, 0.10), Color(0, 0, 0, 0.05)]
|
||
for i in layers.size():
|
||
var sh := 3.0 + float(i) * 3.0
|
||
draw_rect(Rect2(sh, h + d + sh * 0.5, w + d - sh * 1.5, float(2 + i)), layers[i], true)
|