diff --git a/game/presentation/views/board_cell_unit.gd b/game/presentation/views/board_cell_unit.gd index 7187ebd4..b4435c6b 100644 --- a/game/presentation/views/board_cell_unit.gd +++ b/game/presentation/views/board_cell_unit.gd @@ -73,12 +73,22 @@ const FACADE_FAR_COL := Color(0, 0, 0, 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) # 投影远段(渐隐收边) +# ── E 格高墙面(圣经 v3.5 冻结① 2026-09-30——地面格南邻墙→南部 30% 承接墙面:墙顶纹理原亮度 +# 直贴零暗档零阴影〔用户终裁「它们是同样颜色的」〕;墙脚阴线只画地面/墙面交界;(b)-(c) 交界 +# 无边框由 BoardView 侧跳过墙格北向描边承载)── +const E_FACADE_FRAC := 0.30 # 墙面承接高(格边比——用户指令 30%) +const E_FACADE_FOOT_COL := Color8(52, 42, 32) # 墙脚阴线(方向稿同色) # ── 素材槽位(本批全 null = 程序化占位服役;art-bible §8.2 格面 32×32 暂定档)── var tex_base: Texture2D = null # ① 砖面底 var tex_mutation: Texture2D = null # ② 变异纹带 var tex_glyph: Texture2D = null # ③ 数字 var tex_badge: Texture2D = null # ③' 徽章 var tex_flag: Texture2D = null # ④ 旗 +var tex_facade: Texture2D = null # ⑥ E 格墙面材质(v3.5——南邻墙顶 center 瓦片同源,BoardView 注入) +var facade_strip := false: # E 格开关(BoardView paint 按「已开格且南邻未开墙」写入——瓦片态专用) + set(v): + facade_strip = v + queue_redraw() # 变异角标(迭代 6 T6——程序化,tex_mutation 纹带槽留给变异纹带六型自产批): # "flat_damage" = 未开格伤害型变异,左下角危险红三角(开格有代价的策略纹理标记) @@ -119,6 +129,7 @@ func _draw() -> void: draw_rect(or_, oc, true) _draw_south_facade() _draw_north_projection() + _draw_e_facade() # 瓦片态描边覆盖层(高墙瓦片接线批 2026-09-26):tex_base 在位时 BoardView 传入的 bg_sb # 已降级为「透明底 + 描边」载体——呼吸微光/主角蓝框画在瓦片之上(art-bible §1.2 叠层序 # 不变:底 < 纹带 < 数字 < 旗 < 焦点高亮);素材缺位回退走 elif 程序化原样,零观感变化 @@ -130,6 +141,7 @@ func _draw() -> void: # 半条边=沿邻边自角点起 edge/2;角点圆 r=6 贴角点圆心,近白芯 r=2.5 提亮) if contact_col.a > 0.0: _draw_north_projection() # 平色回退+微光并发的英雄格补画(瓦片路径已画——同像素重复无观感差) + _draw_e_facade() # E 格墙面补画(同上——英雄格兼 E 格时瓦片路径已画,重复无害) var band := 4.0 var half := edge * 0.5 for b in contact_bands: @@ -251,6 +263,21 @@ func _draw_north_projection() -> void: draw_rect(Rect2(0.0, seg * 2.0, edge, seg), PROJECTION_EDGE_COL, true) +# E 格高墙面(圣经 v3.5 冻结① 2026-09-30——方向稿 draw_facade 移植):本格已开且南邻为墙 → +# 南部 30% 承接墙面。材质 = 墙顶 center 瓦片顶部 30% 区带**原亮度**直贴(零暗档零阴影); +# 墙脚阴线只画地面/墙面交界(strip 顶缘 1px);墙面底缘(格界处)不画任何线——直接接南侧墙顶 +# (v3.4 用户裁定:白边导致两截)。仅瓦片态服役(tex_facade 缺位 = 平色回退原语义不动)。 +func _draw_e_facade() -> void: + if not facade_strip or tex_facade == null: + return + var strip_h := edge * E_FACADE_FRAC + var y0 := edge - strip_h + var ts := tex_facade.get_size() + draw_texture_rect_region(tex_facade, Rect2(0.0, y0, edge, strip_h), + Rect2(0.0, 0.0, ts.x, ts.y * E_FACADE_FRAC)) + draw_rect(Rect2(0.0, y0, edge, 1.0), E_FACADE_FOOT_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 484ec1b9..2df89b18 100644 --- a/game/presentation/views/board_view.gd +++ b/game/presentation/views/board_view.gd @@ -714,6 +714,8 @@ func _paint_cell(c: Vector2i, hero: Vector2i) -> void: u.outline_sides.assign([]) # typed Array[int](代码审查批 3 类型收紧——assign 保持引用语义) u.facade_south = false u.proj_band = 0.0 + u.tex_facade = null + u.facade_strip = false 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 @@ -729,11 +731,18 @@ func _paint_cell(c: Vector2i, hero: Vector2i) -> void: 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 描边让位防三重叠黑 + if code == 0 and _tiles_ok: + continue # v3.5 冻结① (b)-(c) 交界无边框:墙面直贴接墙顶(E 格墙面件在邻格承载)——北向描边退役(平色回退态保留描边) 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 + # E 格高墙面(圣经 v3.5 冻结①——方向稿 is_facade_cell 口径):已开格南邻未开墙 → 南部 30% + # 承接墙面(材质=同板墙顶 center 瓦片,原亮度直贴);仅瓦片态启用——平色回退保持原语义 + if south_in and not _minesweeper.is_revealed(south_n) and _tiles_ok: + u.facade_strip = true + u.tex_facade = _tiles.get("wall_center") # ②( 魔法道具叠加层(迭代 7 T4):真视格=红内缩框;预读格=奖励身份徽章(identity_resolver 既有 # 只读面取字形——零数据复制,badge 位复用);已开格标记自然退位(refresh 逐拍重算) if not revealed: @@ -848,6 +857,11 @@ func _load_board_tiles(board_type: String = "dungeon") -> void: if tex == null: _request_dungeon_fallback(board_type) return + # 地板归一(圣经 v3.5 冻结①/§1.4 样张 v3 记录——已开格底归一世界底层档 L≈0.10,带 0.08–0.14): + # 方向稿 _v3_darken_floors 同式移植;现行瓦片 L≈0.036 低于带下沿故实为提亮;素材重产归资产批, + # 本归一为程序代役(逐批装载时对 freshly-loaded 原图测光,幂等) + for i in range(floors.size()): + floors[i] = _normalize_floor_luma(floors[i]) # 六镜像件(词表 §二:wall_e←wall_w / wall_ne←wall_nw / wall_se←wall_sw / # wall_end_e←wall_end_w / wall_in_ne←wall_in_nw / wall_in_se←wall_in_sw;只水平翻转禁旋转 # ——北受光不受损) @@ -880,6 +894,34 @@ static func _flip_tex(tex: Texture2D) -> Texture2D: return ImageTexture.create_from_image(img) +# 地板瓦片明度归一(v3.5 批 B1——方向稿 _v3_darken_floors 同式移植):8×8 双线性重采样均值测光 +# (sRGB→线性域,Rec.709 系数),增益 k=(目标/实测)^(1/2.2) 钳 [0.6,1.8],逐通道 sRGB 域线性拉伸。 +# 输入恒为 freshly-loaded 原图(load_tex 每次盘读)——幂等可重入;32×32 五变体开销可忽略 +static func _normalize_floor_luma(tex: Texture2D, target_l: float = 0.10) -> Texture2D: + var img: Image = tex.get_image() + if img.is_compressed(): + img.decompress() + img.convert(Image.FORMAT_RGBA8) + var small: Image = img.duplicate() + small.resize(8, 8, Image.INTERPOLATE_BILINEAR) + var sum := 0.0 + for y in range(8): + for x in range(8): + var p := small.get_pixel(x, y) + sum += 0.2126 * _srgb_lin(p.r) + 0.7152 * _srgb_lin(p.g) + 0.0722 * _srgb_lin(p.b) + var k := pow(target_l / maxf(sum / 64.0, 0.001), 1.0 / 2.2) + k = clampf(k, 0.6, 1.8) + for y in range(img.get_height()): + for x in range(img.get_width()): + var c := img.get_pixel(x, y) + img.set_pixel(x, y, Color(minf(c.r * k, 1.0), minf(c.g * k, 1.0), minf(c.b * k, 1.0), c.a)) + return ImageTexture.create_from_image(img) + + +static func _srgb_lin(c: float) -> float: + return c / 12.92 if c <= 0.04045 else pow((c + 0.055) / 1.055, 2.4) + + # 格坐标确定性散列(禁 RNG/禁 randomize 纪律——「初始化随机落定禁逐轮重掷」圣经原则三落点: # 同格坐标恒同值,refresh/重绘/逐轮不变)。乘加混合 + 移位雪崩;64 位整型乘法回绕即哈希语义 #(GDScript int 溢出静默回绕),板域 10×10/12×12 内 mod 10/mod 5 分布均匀