diff --git a/game/presentation/views/board_cell_unit.gd b/game/presentation/views/board_cell_unit.gd index 42026571..df0ae451 100644 --- a/game/presentation/views/board_cell_unit.gd +++ b/game/presentation/views/board_cell_unit.gd @@ -22,6 +22,18 @@ var contact_corners: Array = [] # 斜向共享角码 0=NW/1=NE/2=SW/3=SE( var contact_col := Color(0, 0, 0, 0) # 当前呼吸色(alpha 0 = 不画) var plate := false # 数字色牌开关(BoardView paint 按已开格 glyph 写入——原则二) var outline_sides: Array = [] # 墙格地面朝向描边码 0=N/1=S/2=W/3=E(轮廓加强批——程序侧结构件) +# ── 高墙感 D 投影档(2026-09-28 挑档落码——研究件四变体用户裁 D=C+地面投影,ITB 同款高度线索)── +# 南立面 = 墙格南缘内侧「口沿高光线 + 双段暗带」(邻地面格才画,墙群内聚);地面投影 = 北邻墙格 +# 在本已开格北缘投渐隐暗带。参数按研究件 64px 拼版实测比例换算(立面双段 0.16/0.25 格边、投影带 +# 0.22 格边;坐标推导留档 commit)。素材缺位程序化回退同样服役(结构归程序——art-bible §8.5)。 +var facade_south := false: # 南立面开关(BoardView paint 按「南邻已开格」写入) + set(v): + facade_south = v + queue_redraw() +var proj_band := 0.0: # 地面投影带宽(像素,0 = 不画——BoardView 按北邻墙判定写入) + set(v): + proj_band = v + queue_redraw() var glyph := "": # 文字位——数字/雷/旗/人/?(现行视觉旗与数字互斥,同位承载) set(v): glyph = v @@ -51,6 +63,16 @@ var bevel := 0.0: # 顶面倒角强度(0=关——立体原 set(v): bevel = v queue_redraw() +# ── D 投影档绘制常量(研究件实测取色——立面高光/双段暗带/地面投影;黑罩 alpha 叠加实测等效)── +const FACADE_HIGHLIGHT_PX := 2.0 # 口沿高光线厚(像素) +const FACADE_NEAR_FRAC := 0.16 # 立面近段高(格边比——研究件 10/64) +const FACADE_FAR_FRAC := 0.25 # 立面远段高(格边比——研究件 16/64) +const FACADE_HIGHLIGHT_COL := Color8(196, 172, 132) # 口沿高光(研究件取色暖米白) +const FACADE_NEAR_COL := Color(0, 0, 0, 0.60) # 立面近段黑罩(墙顶 132→52 实测 α≈0.61) +const FACADE_FAR_COL := Color(0, 0, 0, 0.82) # 立面远段黑罩(墙顶 132→24 实测 α≈0.82) +const PROJECTION_NEAR_COL := Color(0, 0, 0, 0.28) # 投影贴墙段(地面 66→46 实测 α≈0.28) +const PROJECTION_MID_COL := Color(0, 0, 0, 0.16) # 投影中段(渐隐) +const PROJECTION_EDGE_COL := Color(0, 0, 0, 0.06) # 投影远段(渐隐收边) # ── 素材槽位(本批全 null = 程序化占位服役;art-bible §8.2 格面 32×32 暂定档)── var tex_base: Texture2D = null # ① 砖面底 var tex_mutation: Texture2D = null # ② 变异纹带 @@ -79,6 +101,8 @@ func _draw() -> void: 2: or_ = Rect2(0, 0, ow, edge) 3: or_ = Rect2(edge - ow, 0, ow, edge) draw_rect(or_, oc, true) + _draw_south_facade() + _draw_north_projection() # 瓦片态描边覆盖层(高墙瓦片接线批 2026-09-26):tex_base 在位时 BoardView 传入的 bg_sb # 已降级为「透明底 + 描边」载体——呼吸微光/主角蓝框画在瓦片之上(art-bible §1.2 叠层序 # 不变:底 < 纹带 < 数字 < 旗 < 焦点高亮);素材缺位回退走 elif 程序化原样,零观感变化 @@ -89,6 +113,7 @@ func _draw() -> void: # 带宽 4px 贴格边内侧(坐标推导:N=[0,0,edge,4] S=[0,edge-4,edge,4] W=[0,0,4,edge] E=[edge-4,0,4,edge]; # 半条边=沿邻边自角点起 edge/2;角点圆 r=6 贴角点圆心,近白芯 r=2.5 提亮) if contact_col.a > 0.0: + _draw_north_projection() # 平色回退+微光并发的英雄格补画(瓦片路径已画——同像素重复无观感差) var band := 4.0 var half := edge * 0.5 for b in contact_bands: @@ -124,6 +149,8 @@ func _draw() -> void: draw_rect(Rect2(edge - band, pt.y if int(cc) == 1 else pt.y - half, band, half), contact_col, true) elif bg_sb != null: draw_style_box(bg_sb, rect) + _draw_south_facade() # 平色回退路径——D 投影档两件同样服役(结构归程序) + _draw_north_projection() # 顶面倒角(立体原型批:光源左上——上/左内沿受光 2px、下/右内沿背光 2px;内缩 2px 让 # 呼吸微光/主角蓝边框保持最外沿可见;强度随档位) if bevel > 0.0: @@ -170,6 +197,33 @@ func _draw() -> void: draw_rect(Rect2(1, 1, edge - 2.0, edge - 2.0), Color(hl_color, 0.55), false, 2.0) # 2px 内描边(旧 hl Panel 等价) +# 南立面(D 档件一——墙格南缘内侧,自底边向上:双段暗带在下、口沿高光线贴其上沿): +# 坐标推导(自格底边起算):远段=[edge−far, edge],近段=[edge−far−near, edge−far], +# 高光线=[edge−far−near−hl, edge−far−near]——与研究件「墙顶面→高光→暗段→更暗段→格界」下行序一致 +func _draw_south_facade() -> void: + if not facade_south: + return + var far_h := edge * FACADE_FAR_FRAC + var near_h := edge * FACADE_NEAR_FRAC + var y_far := edge - far_h + var y_near := y_far - near_h + var y_hl := y_near - FACADE_HIGHLIGHT_PX + draw_rect(Rect2(0.0, y_hl, edge, FACADE_HIGHLIGHT_PX), FACADE_HIGHLIGHT_COL, true) + draw_rect(Rect2(0.0, y_near, edge, near_h), FACADE_NEAR_COL, true) + draw_rect(Rect2(0.0, y_far, edge, far_h), FACADE_FAR_COL, true) + + +# 地面投影(D 档件二——北邻墙格在本已开格北缘投渐隐暗带,自北缘向南三段衰减): +# 坐标推导:三等分 proj_band,α 0.28/0.16/0.06(研究件实测贴墙 α≈0.28、带末渐融入地面) +func _draw_north_projection() -> void: + if proj_band <= 0.0: + return + var seg := proj_band / 3.0 + draw_rect(Rect2(0.0, 0.0, edge, seg), PROJECTION_NEAR_COL, true) + draw_rect(Rect2(0.0, seg, edge, seg), PROJECTION_MID_COL, true) + draw_rect(Rect2(0.0, seg * 2.0, edge, seg), PROJECTION_EDGE_COL, true) + + # 文字位绘制:水平居中 + 垂直居中(基线 = (格高 − 字高)/2 + 上伸部——旧 Button 居中对齐等价) func _draw_glyph(g: String, col: Color, fs: int) -> void: var f := font if font != null else ThemeDB.fallback_font diff --git a/game/presentation/views/board_view.gd b/game/presentation/views/board_view.gd index 337ce527..d67e875e 100644 --- a/game/presentation/views/board_view.gd +++ b/game/presentation/views/board_view.gd @@ -54,6 +54,9 @@ const SEP := 2 # 格间距(旧 GridContainer v/ # §1.4 注记待 art-bible 并行批落籍后补写) const DEPTH_PX := 8.0 # 悬崖厚度(像素) const DEPTH_BEVEL := 0.6 # 顶面倒角强度 +# 高墙感 D 投影档(2026-09-28 挑档落码):地面投影带宽 = 格边比(研究件 64px 拼版实测 14/64≈0.22; +# 立面/投影色参数在 CellUnit 常量——绘制侧单点) +const WALL_PROJECTION_FRAC := 0.22 # 英雄单位演出参数(棋盘小人贴图批 2026-09-25——计划书 §3.B/C 时长档) const HERO_FRAME_PX := 32.0 # 英雄帧画布边长(素材 32×32 锁定——缩放比分母) @@ -683,12 +686,28 @@ func _paint_cell(c: Vector2i, hero: Vector2i) -> void: u.glyph_color = digit_col u.plate = revealed and glyph != "" # 数字色牌(原则二——已开格字形全垫牌;旗在未开格不垫) u.outline_sides = [] - if _tiles_ok and not revealed: + u.facade_south = false + u.proj_band = 0.0 + var south_n: Vector2i = c + Vector2i(0, 1) + var north_n: Vector2i = c + Vector2i(0, -1) + var south_in: bool = south_n.x >= 0 and south_n.y >= 0 and south_n.x < _board.width and south_n.y < _board.height + var north_in: bool = north_n.x >= 0 and north_n.y >= 0 and north_n.x < _board.width and north_n.y < _board.height + if not revealed: + # 高墙感 D 投影档(2026-09-28 挑档落码):南邻地面格 → 墙格南缘立「口沿高光+双段暗带」立面 + #(邻地面才画——墙-墙内界保墙群内聚,轮廓加强批同口径);板外=墙不画 + u.facade_south = south_in and _minesweeper.is_revealed(south_n) # 轮廓加强:墙格四邻中已开(地面)格朝向记描边码(板外=墙不描——保墙群外轮廓只在墙/地交界) for d in [Vector2i(0, -1), Vector2i(0, 1), Vector2i(-1, 0), Vector2i(1, 0)]: var n: Vector2i = c + d if n.x >= 0 and n.y >= 0 and n.x < _board.width and n.y < _board.height and _minesweeper.is_revealed(n): - u.outline_sides.append(0 if d.y < 0 else (1 if d.y > 0 else (2 if d.x < 0 else 3))) + var code := 0 if d.y < 0 else (1 if d.y > 0 else (2 if d.x < 0 else 3)) + if code == 1 and u.facade_south: + continue # 南缘由立面件承载(高光+双段暗带)——2px 描边让位防三重叠黑 + u.outline_sides.append(code) + else: + # 地面投影:北邻墙格在本已开格北缘投渐隐暗带(ITB 同款高度线索——带宽按格边比例常量) + if north_in and not _minesweeper.is_revealed(north_n): + u.proj_band = u.edge * WALL_PROJECTION_FRAC u.badge_glyph = _update_badge(c) u.queue_redraw()