feat(presentation): 换肤最小可看批——格面高墙瓦片接线(查表合成器 16 情形+镜像+凹角回落+变体哈希,缺位整批回退)+敌人立绘槽接线(八敌种路径常量+按 id 装载,缺位字形回退等价)+接触带微光切换(英雄格周界空间侧蓝族,旧绿相退役)+台账 176
This commit is contained in:
1 parent
3b6c69adb3
commit
79f2efc8eb
5 files changed
+323
-22
No files matched your search
@@ -205,6 +205,33 @@ func enemy_body_at(i: int) -> Node2D:
|
||||
return _cards[i]
|
||||
|
||||
|
||||
# 敌种立绘路径映射(enemy_id → UiKit 纹理常量,键集 = art-bible §4.6.4 八敌种)。显式 match 单点:
|
||||
# UiKit 常量是逐条 const 声明(非字典),Object.get 不达脚本常量、禁动态拼键取值;放本视图 =
|
||||
# 素材装载属组合点职责(主角侧同款先例 _init TEX_HERO_PORTRAIT),StandeeBody 保持纯收 tex 面。
|
||||
# 素材缺位 load_tex→null→set_portrait_texture 字形回退(表现与素材批前逐位一致);未录键返回 null
|
||||
# 走默认字形「敌」(与 StandeeBody._portrait_glyph 默认档同口径)——数据表扩键先补此处映射。
|
||||
func _enemy_portrait_tex(enemy_id: String) -> Texture2D:
|
||||
match enemy_id:
|
||||
"goblin":
|
||||
return UiKit.load_tex(UiKit.TEX_ENEMY_GOBLIN)
|
||||
"bugbear":
|
||||
return UiKit.load_tex(UiKit.TEX_ENEMY_BUGBEAR)
|
||||
"ogre_chief":
|
||||
return UiKit.load_tex(UiKit.TEX_ENEMY_OGRE_CHIEF)
|
||||
"giant_spider":
|
||||
return UiKit.load_tex(UiKit.TEX_ENEMY_GIANT_SPIDER)
|
||||
"drider":
|
||||
return UiKit.load_tex(UiKit.TEX_ENEMY_DRIDER)
|
||||
"duergar":
|
||||
return UiKit.load_tex(UiKit.TEX_ENEMY_DUERGAR)
|
||||
"hook_horror":
|
||||
return UiKit.load_tex(UiKit.TEX_ENEMY_HOOK_HORROR)
|
||||
"duergar_king":
|
||||
return UiKit.load_tex(UiKit.TEX_ENEMY_DUERGAR_KING)
|
||||
_:
|
||||
return null
|
||||
|
||||
|
||||
# 敌方站桩投影更新:数量不变 = 就地更新(死亡灰化/受击闪烁等站桩上动画不被逐行刷新重置——禁瞬消纪律);
|
||||
# 数量变化 = 新战斗域,重建站桩槽(轮内不增删,无回流)
|
||||
func set_enemies(cards_data: Array) -> void:
|
||||
@@ -220,6 +247,8 @@ func set_enemies(cards_data: Array) -> void:
|
||||
world.add_child(body)
|
||||
body.slot_row = _make_slot_companion(enemy_box)
|
||||
body.set_data(d)
|
||||
# 敌种立绘接线(仅重建拍装载一次;flip=false——敌像素材基准朝右,翻转义务归素材批)
|
||||
body.set_portrait_texture(_enemy_portrait_tex(String(d.get("enemy_id", ""))), false)
|
||||
_cards.append(body)
|
||||
_sync_layout.call_deferred()
|
||||
return
|
||||
|
||||
@@ -15,6 +15,11 @@ var edge := 46.0: # 格边长(BoardView.set_cell_area 单点
|
||||
edge = v
|
||||
queue_redraw()
|
||||
var bg_sb: StyleBoxFlat = null # 格底 StyleBox(BoardView 每次 paint 重建;呼吸微光就地改边框)
|
||||
# ── 接触带微光绘制面(2026-09-26 批:可挖域微光自"墙格整框"改"英雄格周界空间侧"——art-bible §3.2 v2.8;
|
||||
# 仅英雄格单元承载,BoardView.refresh 按可挖域写边/角码、_process 逐拍更新呼吸色)──
|
||||
var contact_bands: Array = [] # 正交接触边码 0=N/1=S/2=W/3=E(该侧整条边)
|
||||
var contact_corners: Array = [] # 斜向共享角码 0=NW/1=NE/2=SW/3=SE(角点+两侧各半条边)
|
||||
var contact_col := Color(0, 0, 0, 0) # 当前呼吸色(alpha 0 = 不画)
|
||||
var glyph := "": # 文字位——数字/雷/旗/人/?(现行视觉旗与数字互斥,同位承载)
|
||||
set(v):
|
||||
glyph = v
|
||||
@@ -58,6 +63,49 @@ func _draw() -> void:
|
||||
# 呼吸微光/主角蓝框由 BoardView 改 bg_sb 后触发重绘)
|
||||
if tex_base != null:
|
||||
draw_texture_rect(tex_base, rect, false)
|
||||
# 瓦片态描边覆盖层(高墙瓦片接线批 2026-09-26):tex_base 在位时 BoardView 传入的 bg_sb
|
||||
# 已降级为「透明底 + 描边」载体——呼吸微光/主角蓝框画在瓦片之上(art-bible §1.2 叠层序
|
||||
# 不变:底 < 纹带 < 数字 < 旗 < 焦点高亮);素材缺位回退走 elif 程序化原样,零观感变化
|
||||
if bg_sb != null:
|
||||
draw_style_box(bg_sb, rect)
|
||||
|
||||
# 接触带微光(英雄格周界空间侧——正交邻墙=整条边;斜向=共享角点+两侧各半条边;光不进墙格):
|
||||
# 带宽 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:
|
||||
var band := 4.0
|
||||
var half := edge * 0.5
|
||||
for b in contact_bands:
|
||||
var r := Rect2()
|
||||
match int(b):
|
||||
0: r = Rect2(0, 0, edge, band)
|
||||
1: r = Rect2(0, edge - band, edge, band)
|
||||
2: r = Rect2(0, 0, band, edge)
|
||||
3: r = Rect2(edge - band, 0, band, edge)
|
||||
draw_rect(r, contact_col, true)
|
||||
for cc in contact_corners:
|
||||
var pt := Vector2.ZERO
|
||||
match int(cc):
|
||||
0: pt = Vector2(0, 0)
|
||||
1: pt = Vector2(edge, 0)
|
||||
2: pt = Vector2(0, edge)
|
||||
3: pt = Vector2(edge, edge)
|
||||
draw_circle(pt, 6.0, contact_col)
|
||||
draw_circle(pt, 2.5, Color(1, 1, 1, minf(1.0, contact_col.a * 0.95)))
|
||||
# 半条边:角点沿两条邻边各延伸 edge/2(坐标推导:横带沿 N/S 自角点向板心侧 half;
|
||||
# NW/SE 半带 x=y=角点坐标,NE/SE 半带自 edge-half 收进——正交整边时重叠同色无害)
|
||||
if int(cc) == 0 or int(cc) == 1:
|
||||
# N 侧横带:NW 自 x=0、NE 自 x=edge-half
|
||||
draw_rect(Rect2(pt.x if int(cc) == 0 else pt.x - half, 0.0, half, band), contact_col, true)
|
||||
if int(cc) == 2 or int(cc) == 3:
|
||||
# S 侧横带:SW 自 x=0、SE 自 x=edge-half
|
||||
draw_rect(Rect2(pt.x if int(cc) == 2 else pt.x - half, edge - band, half, band), contact_col, true)
|
||||
if int(cc) == 0 or int(cc) == 2:
|
||||
# W 侧竖带:NW 自 y=0、SW 自 y=edge-half
|
||||
draw_rect(Rect2(0.0, pt.y if int(cc) == 0 else pt.y - half, band, half), contact_col, true)
|
||||
if int(cc) == 1 or int(cc) == 3:
|
||||
# E 侧竖带:NE 自 y=0、SE 自 y=edge-half
|
||||
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)
|
||||
# 顶面倒角(立体原型批:光源左上——上/左内沿受光 2px、下/右内沿背光 2px;内缩 2px 让
|
||||
|
||||
@@ -36,7 +36,7 @@ const COL_HERO := UiKit.HERO_BLUE # 小人边框——小人蓝 #2E6
|
||||
const COL_FLAG := UiKit.FLAG_RED # 旗朱 #C63D22
|
||||
const COL_GOLD := UiKit.GOLD # 奖励金 #F0A828
|
||||
const COL_PATH := UiKit.HERO_BLUE # 路径预览点迹——小人蓝细线
|
||||
const COL_DIG_EDGE := UiKit.DIG_EDGE # 可挖域呼吸微光基色(绿相,明度贴格底)
|
||||
const COL_CONTACT := UiKit.CONTACT_GLOW # 接触带微光基色(蓝族浅一档·近白蓝——§3.2 v2.8;旧绿相退役 2026-09-26)
|
||||
const COL_HL_TARGET := UiKit.GOLD # 悬停目标格边框(金)
|
||||
const REWARD_BADGE := { # 已开格格面资源身份 icon(cell_type 九型键;极性视觉归批 2)
|
||||
"attack": "攻", "defense": "守", "heal": "医", "blast": "爆", "weaken": "弱", "pierce": "穿", "magic": "魔", # 穿/魔 = 伤害道具批 2026-09-18
|
||||
@@ -70,6 +70,31 @@ const HERO_BOUNCE := 0.82 # 弹跳压缩比(scale.y 1→0.82→1 脚底收
|
||||
const HERO_SHADOW_PX := Vector2(32, 12) # 脚下椭圆影屏幕尺寸(Godot 组件合成——径向渐变纹理压扁,
|
||||
# 贴图零改动,2026-09-26 用户裁决走引擎侧)
|
||||
|
||||
# ── 高墙/地面瓦片纹理路径单点(棋盘高墙瓦片接线批 2026-09-26)──
|
||||
# 素材 PNG 不入 git(用户裁定)——一律 UiKit.load_tex(exists 守卫)装载,禁 preload;
|
||||
# 缺位返回 null,整批任一缺位 = 弃用瓦片走程序化平色回退(BRICK/FLOOR,fresh checkout 冒烟不炸)。
|
||||
# 路径常量落本文件单点(ui_kit.gd 由并行批占用,任务书 §2.5 禁入)。词表 =
|
||||
# design/research/board-tile-vocab-plan-a-2026-09-26.md(16 唯一墙瓦片 + 5 地面变体;
|
||||
# 东/东北/东南/end_e/in_ne/in_se 六镜像件运行时 flip_x 合成,不出文件——词表 §二)。
|
||||
const TEX_WALL_CENTER := "res://assets/art/board/terrain_wall_center_dungeon.png"
|
||||
const TEX_WALL_CENTER_CRACK := "res://assets/art/board/terrain_wall_center_crack_dungeon.png"
|
||||
const TEX_WALL_CENTER_SPECKLE := "res://assets/art/board/terrain_wall_center_speckle_dungeon.png"
|
||||
const TEX_WALL_N := "res://assets/art/board/terrain_wall_n_dungeon.png"
|
||||
const TEX_WALL_S := "res://assets/art/board/terrain_wall_s_dungeon.png"
|
||||
const TEX_WALL_W := "res://assets/art/board/terrain_wall_w_dungeon.png" # wall_e = 运行时镜像
|
||||
const TEX_WALL_NW := "res://assets/art/board/terrain_wall_nw_dungeon.png" # wall_ne = 运行时镜像
|
||||
const TEX_WALL_SW := "res://assets/art/board/terrain_wall_sw_dungeon.png" # wall_se = 运行时镜像
|
||||
const TEX_WALL_HRUN := "res://assets/art/board/terrain_wall_hrun_dungeon.png"
|
||||
const TEX_WALL_VRUN := "res://assets/art/board/terrain_wall_vrun_dungeon.png"
|
||||
const TEX_WALL_END_N := "res://assets/art/board/terrain_wall_end_n_dungeon.png"
|
||||
const TEX_WALL_END_S := "res://assets/art/board/terrain_wall_end_s_dungeon.png"
|
||||
const TEX_WALL_END_W := "res://assets/art/board/terrain_wall_end_w_dungeon.png" # wall_end_e = 运行时镜像
|
||||
const TEX_WALL_LONE := "res://assets/art/board/terrain_wall_lone_dungeon.png"
|
||||
const TEX_WALL_IN_NW := "res://assets/art/board/terrain_wall_in_nw_dungeon.png" # wall_in_ne = 运行时镜像
|
||||
const TEX_WALL_IN_SW := "res://assets/art/board/terrain_wall_in_sw_dungeon.png" # wall_in_se = 运行时镜像
|
||||
const TEX_FLOOR_FMT := "res://assets/art/board/terrain_floor_dungeon_%d.png" # 1..5 变体
|
||||
const TILE_FLOOR_VARIANTS := 5 # 地面瓦片变体数(词表 §一 floor_1..5)
|
||||
|
||||
var _wrap: CenterContainer
|
||||
var _svp_container: SubViewportContainer
|
||||
var _viewport: SubViewport
|
||||
@@ -81,6 +106,7 @@ var _identity_cb := Callable() # 地图战斗资源 身份解析回调(组
|
||||
var _mask_cb := Callable() # 地形变异 数字遮蔽回调(组合根注入只读面)——Vector2i → bool(true = 该格数字不显示)
|
||||
var _diggable := {} # 可挖域(8 向相邻未开格)——呼吸微光作用集
|
||||
var _breath_t := 0.0
|
||||
var _contact_unit: Node2D = null # 接触带承载单元(=英雄格 CellUnit;rebuild 随清场复位)
|
||||
var _dig_glow := false # 挖掘期才允许唯一在动元素(art-bible §2.1)
|
||||
var _hover := Vector2i(-9, -9)
|
||||
var _last_click := {"cell": Vector2i(-9, -9), "ms": -100000}
|
||||
@@ -99,6 +125,11 @@ var _hero_move_tw: Tween
|
||||
var _hero_bump_tw: Tween
|
||||
var _hero_dig_tw: Tween
|
||||
|
||||
# ── 瓦片状态(高墙瓦片接线批 2026-09-26;素材缺位 = 全 false/空——程序化平色回退)──
|
||||
var _tiles := {} # 词表键 → Texture2D(镜像件已预翻转;装载见 _load_board_tiles)
|
||||
var _floor_tiles: Array[Texture2D] = [] # 地面瓦片五变体(下标 0..4 = floor_1..5)
|
||||
var _tiles_ok := false # false = 素材缺位/未装载——bg_sb 程序化平色原路径
|
||||
|
||||
var cell_size: float: # 只读属性(ui_layout_probe 断言面——旧私有名 _cell 的契约化出口)
|
||||
get:
|
||||
return _cell
|
||||
@@ -125,6 +156,7 @@ func _init() -> void:
|
||||
_desat_mat.set_shader_parameter("strength", 0.0)
|
||||
_hero_tex_idle = UiKit.load_tex(UiKit.TEX_HERO_IDLE)
|
||||
_hero_tex_walk = UiKit.load_tex(UiKit.TEX_HERO_WALK)
|
||||
_load_board_tiles() # 高墙/地面瓦片整批守卫装载(缺位静默回退——英雄批同款纪律,禁刷屏)
|
||||
|
||||
|
||||
func board() -> BoardData:
|
||||
@@ -210,6 +242,7 @@ func rebuild(board: BoardData, minesweeper) -> void:
|
||||
child.queue_free()
|
||||
_world.hero = null # 英雄精灵随清场退役——下拍 refresh 经 ensure_hero 重建(首建即时落位)
|
||||
_cells.clear()
|
||||
_contact_unit = null
|
||||
_hero_last = Vector2i(-99, -99)
|
||||
_r0.clear()
|
||||
_hover = Vector2i(-9, -9)
|
||||
@@ -227,6 +260,11 @@ func rebuild(board: BoardData, minesweeper) -> void:
|
||||
u.position = Vector2(c) * stride
|
||||
u.bevel = DEPTH_BEVEL # 定稿倒角——新建格单元继承
|
||||
u.use_parent_material = true # 去饱和材质挂 BoardWorld——单元随世界材质灰化
|
||||
if _tiles_ok:
|
||||
# NEAREST 采样(2026-09-26 用户拍板:32×32 源 × 45/36px 格边非整数缩放接受档,
|
||||
# 与英雄小人 1.5× 豁免同级——圣经 §8.2 豁免注记归 art-bible 批补写);只在瓦片
|
||||
# 模式启用——程序化回退路径渲染零扰动(含格面文字采样不回退不变化)
|
||||
u.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
|
||||
u.font = _world.board_font
|
||||
_world.add_child(u)
|
||||
_cells[c] = u
|
||||
@@ -247,6 +285,7 @@ func refresh() -> void:
|
||||
for x in _board.width:
|
||||
_paint_cell(Vector2i(x, y), hero)
|
||||
_refresh_hover_after_paint()
|
||||
_apply_contact_bands()
|
||||
_update_hero(hero) # 英雄精灵 diff 驱动(棋盘小人贴图批 2026-09-25)
|
||||
|
||||
|
||||
@@ -591,7 +630,18 @@ func _paint_cell(c: Vector2i, hero: Vector2i) -> void:
|
||||
digit_col = COL_FLAG
|
||||
else:
|
||||
bg = COL_BRICK
|
||||
var sb := UiKit.panel_flat(bg, bg.darkened(0.15), 3)
|
||||
# 瓦片模式(高墙接线批 2026-09-26):tex_base = 查表瓦片(未开=墙瓦片/已开=地面瓦片),
|
||||
# bg_sb 降级为透明描边载体——只承载呼吸微光/主角蓝框(CellUnit 瓦片态画在瓦片之上),
|
||||
# 程序化平色退役;瓦片分配=格坐标哈希,初始化落定后逐拍稳定(禁逐轮重掷——圣经原则三)
|
||||
var sb: StyleBoxFlat
|
||||
var tile: Texture2D = null
|
||||
if _tiles_ok:
|
||||
# Color.TRANSPARENT 载体(引擎常量——视图禁内联色字面量纪律;透明+零描边=瓦片上不画任何东西)
|
||||
sb = UiKit.panel_flat(Color.TRANSPARENT, Color.TRANSPARENT, 3, 0)
|
||||
tile = _floor_tile_for(c) if revealed else _wall_tile_for(c)
|
||||
else:
|
||||
# 素材整批缺位回退 = 现行程序化平色路径(fresh checkout 冒烟不炸——任务书 §2.2)
|
||||
sb = UiKit.panel_flat(bg, bg.darkened(0.15), 3)
|
||||
if is_hero:
|
||||
sb.set_border_width_all(3)
|
||||
sb.border_color = COL_HERO
|
||||
@@ -599,6 +649,7 @@ func _paint_cell(c: Vector2i, hero: Vector2i) -> void:
|
||||
# 贴图缺位回退字形「人」(项目纹理槽惯例——贴图在位=格内字形退役,单位本体由独立精灵承载)
|
||||
glyph = "人"
|
||||
digit_col = COL_HERO
|
||||
u.tex_base = tile
|
||||
u.bg_sb = sb
|
||||
u.glyph = glyph
|
||||
u.glyph_color = digit_col
|
||||
@@ -606,38 +657,199 @@ func _paint_cell(c: Vector2i, hero: Vector2i) -> void:
|
||||
u.queue_redraw()
|
||||
|
||||
|
||||
# ---- 可挖域 8 向常驻呼吸微光(挖掘期唯一在动元素) ----
|
||||
# ---- 可挖域接触带呼吸微光(挖掘期唯一在动元素——§3.2 v2.8 画法:光画英雄格周界空间侧,
|
||||
# 正交邻墙=整条边、斜向=共享角点+两侧各半条边;旧"墙格整框绿相"退役 2026-09-26 批) ----
|
||||
|
||||
func set_dig_glow_enabled(on: bool) -> void:
|
||||
_dig_glow = on
|
||||
if not on:
|
||||
if on:
|
||||
_apply_contact_bands() # 相位重入(结算→挖掘):refresh 未跑也重挂带几何
|
||||
else:
|
||||
_reset_breath()
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if not _dig_glow or _diggable.is_empty():
|
||||
return
|
||||
if _contact_unit == null or not is_instance_valid(_contact_unit):
|
||||
return
|
||||
_breath_t += delta
|
||||
if UiKit.motion_scale < 1.0:
|
||||
return # 减动效:呼吸停格(保留当前微光边框——静态可辨、无持续运动)
|
||||
return # 减动效:呼吸停格(refresh/enable 时已施静态色——静态可辨、无持续运动)
|
||||
var k := 0.5 + 0.5 * sin(_breath_t * 3.0) # 3 rad/s≈0.48Hz——无 >3 次/秒频闪(AC 基线)
|
||||
var col := COL_DIG_EDGE.lerp(UiKit.DIG_EDGE_DEEP, 0.55 - 0.35 * k)
|
||||
for c in _diggable:
|
||||
var u: Node2D = _cells.get(c)
|
||||
if u == null or u.bg_sb == null:
|
||||
continue
|
||||
u.bg_sb.set_border_width_all(2)
|
||||
u.bg_sb.border_color = col
|
||||
u.queue_redraw()
|
||||
_contact_unit.contact_col = COL_CONTACT.lerp(UiKit.CONTACT_GLOW_DEEP, 0.55 - 0.35 * k)
|
||||
_contact_unit.queue_redraw()
|
||||
|
||||
|
||||
# 带几何写入(refresh / set_dig_glow_enabled(true) 挂点):清旧承载件→按英雄格可挖域写边/角码→施色
|
||||
func _apply_contact_bands() -> void:
|
||||
if _contact_unit != null and is_instance_valid(_contact_unit) and (_cells.get(_minesweeper.hero_pos()) != _contact_unit if _minesweeper != null else true):
|
||||
_contact_unit.contact_col = Color(0, 0, 0, 0)
|
||||
_contact_unit.queue_redraw()
|
||||
_contact_unit = null
|
||||
if _board == null or _minesweeper == null or not _dig_glow:
|
||||
return
|
||||
var hu: Node2D = _cells.get(_minesweeper.hero_pos())
|
||||
if hu == null:
|
||||
return
|
||||
_contact_unit = hu
|
||||
var bands: Array = []
|
||||
var corners: Array = []
|
||||
for d in [Vector2i(0, -1), Vector2i(0, 1), Vector2i(-1, 0), Vector2i(1, 0)]:
|
||||
if _diggable.has(_minesweeper.hero_pos() + d):
|
||||
bands.append(0 if d.y < 0 else (1 if d.y > 0 else (2 if d.x < 0 else 3)))
|
||||
for d in [Vector2i(-1, -1), Vector2i(1, -1), Vector2i(-1, 1), Vector2i(1, 1)]:
|
||||
if _diggable.has(_minesweeper.hero_pos() + d):
|
||||
corners.append(0 if (d.x < 0 and d.y < 0) else (1 if d.x > 0 and d.y < 0 else (2 if d.x < 0 else 3)))
|
||||
hu.contact_bands = bands
|
||||
hu.contact_corners = corners
|
||||
var k := 0.5 + 0.5 * sin(_breath_t * 3.0)
|
||||
hu.contact_col = COL_CONTACT.lerp(UiKit.CONTACT_GLOW_DEEP, 0.55 - 0.35 * k)
|
||||
hu.queue_redraw()
|
||||
|
||||
|
||||
func _reset_breath() -> void:
|
||||
for c in _diggable:
|
||||
var u: Node2D = _cells.get(c)
|
||||
if u != null and u.bg_sb != null:
|
||||
u.bg_sb.set_border_width_all(1)
|
||||
u.bg_sb.border_color = u.bg_sb.bg_color.darkened(0.15)
|
||||
u.queue_redraw()
|
||||
if _contact_unit != null and is_instance_valid(_contact_unit):
|
||||
_contact_unit.contact_col = Color(0, 0, 0, 0)
|
||||
_contact_unit.queue_redraw()
|
||||
|
||||
|
||||
# ---- 高墙/地面瓦片接线(2026-09-26 批;词表 = design/research/board-tile-vocab-plan-a-2026-09-26.md) ----
|
||||
|
||||
# 瓦片整批守卫装载(_init 单次调用):21 枚全成才启用——任一缺位按整批缺位处理(禁同板混渲染;
|
||||
# fresh checkout 无素材目录 → 静默全回退)。缺位不 push_error——可选素材缺位是预期路径非故障
|
||||
# (英雄批 load_tex 纪律同款,防冒烟刷屏)。镜像件运行时 flip_x 合成,不出文件。
|
||||
func _load_board_tiles() -> void:
|
||||
var t := {
|
||||
"wall_center": UiKit.load_tex(TEX_WALL_CENTER),
|
||||
"wall_center_crack": UiKit.load_tex(TEX_WALL_CENTER_CRACK),
|
||||
"wall_center_speckle": UiKit.load_tex(TEX_WALL_CENTER_SPECKLE),
|
||||
"wall_n": UiKit.load_tex(TEX_WALL_N),
|
||||
"wall_s": UiKit.load_tex(TEX_WALL_S),
|
||||
"wall_w": UiKit.load_tex(TEX_WALL_W),
|
||||
"wall_nw": UiKit.load_tex(TEX_WALL_NW),
|
||||
"wall_sw": UiKit.load_tex(TEX_WALL_SW),
|
||||
"wall_hrun": UiKit.load_tex(TEX_WALL_HRUN),
|
||||
"wall_vrun": UiKit.load_tex(TEX_WALL_VRUN),
|
||||
"wall_end_n": UiKit.load_tex(TEX_WALL_END_N),
|
||||
"wall_end_s": UiKit.load_tex(TEX_WALL_END_S),
|
||||
"wall_end_w": UiKit.load_tex(TEX_WALL_END_W),
|
||||
"wall_lone": UiKit.load_tex(TEX_WALL_LONE),
|
||||
"wall_in_nw": UiKit.load_tex(TEX_WALL_IN_NW),
|
||||
"wall_in_sw": UiKit.load_tex(TEX_WALL_IN_SW),
|
||||
}
|
||||
var floors: Array[Texture2D] = []
|
||||
for i in range(1, TILE_FLOOR_VARIANTS + 1):
|
||||
floors.append(UiKit.load_tex(TEX_FLOOR_FMT % i))
|
||||
for k in t:
|
||||
if t[k] == null:
|
||||
return
|
||||
for tex in floors:
|
||||
if tex == null:
|
||||
return
|
||||
# 六镜像件(词表 §二: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;只水平翻转禁旋转
|
||||
# ——北受光不受损)
|
||||
t["wall_e"] = _flip_tex(t["wall_w"] as Texture2D)
|
||||
t["wall_ne"] = _flip_tex(t["wall_nw"] as Texture2D)
|
||||
t["wall_se"] = _flip_tex(t["wall_sw"] as Texture2D)
|
||||
t["wall_end_e"] = _flip_tex(t["wall_end_w"] as Texture2D)
|
||||
t["wall_in_ne"] = _flip_tex(t["wall_in_nw"] as Texture2D)
|
||||
t["wall_in_se"] = _flip_tex(t["wall_in_sw"] as Texture2D)
|
||||
_tiles = t
|
||||
_floor_tiles = floors
|
||||
_tiles_ok = true
|
||||
|
||||
|
||||
# 水平镜像贴图运行时合成(flip_h 语义):Image 级逐位翻转后重建 ImageTexture——CellUnit 零改动。
|
||||
# VRAM 压缩源先解压(flip_x 不支持压缩格式);32×32 原尺寸逐位翻转,无 ±1px 取整问题
|
||||
static func _flip_tex(tex: Texture2D) -> Texture2D:
|
||||
var img := tex.get_image()
|
||||
if img.is_compressed():
|
||||
img.decompress()
|
||||
img.flip_x()
|
||||
return ImageTexture.create_from_image(img)
|
||||
|
||||
|
||||
# 格坐标确定性散列(禁 RNG/禁 randomize 纪律——「初始化随机落定禁逐轮重掷」圣经原则三落点:
|
||||
# 同格坐标恒同值,refresh/重绘/逐轮不变)。乘加混合 + 移位雪崩;64 位整型乘法回绕即哈希语义
|
||||
#(GDScript int 溢出静默回绕),板域 10×10/12×12 内 mod 10/mod 5 分布均匀
|
||||
static func _cell_hash(c: Vector2i) -> int:
|
||||
var h := c.x * 374761393 + c.y * 668265263
|
||||
h = (h ^ (h >> 13)) * 1274126177
|
||||
return h ^ (h >> 16)
|
||||
|
||||
|
||||
# 四正交邻墙判定(词表 §三.1:板外视为墙;未开格=墙、已开格=地板——用户世界观口径「未开=墙、
|
||||
# 已开=挖出的空间」)。唯一调用面 _paint_cell(refresh 对 _minesweeper 非空守卫在先)
|
||||
func _is_wall(c: Vector2i) -> bool:
|
||||
if c.x < 0 or c.y < 0 or c.x >= _board.width or c.y >= _board.height:
|
||||
return true
|
||||
return not _minesweeper.is_revealed(c)
|
||||
|
||||
|
||||
# 墙瓦片查表(词表 §一 16 正交情形映射 + §三.2 凹角回落):nf/ef/sf/wf = 北/东/南/西邻是地板。
|
||||
# 16 情形 = 0 地板(center 族)+ 3 地板×4(端头)+ 2 地板×6(条带/凸角)+ 1 地板×4(单缘)
|
||||
# + 4 地板(lone),逐分支穷尽
|
||||
func _wall_tile_for(c: Vector2i) -> Texture2D:
|
||||
var nf := not _is_wall(c + Vector2i(0, -1))
|
||||
var ef := not _is_wall(c + Vector2i(1, 0))
|
||||
var sf := not _is_wall(c + Vector2i(0, 1))
|
||||
var wf := not _is_wall(c + Vector2i(-1, 0))
|
||||
if nf and ef and sf and wf:
|
||||
return _wall_center_tile(c) # 四邻皆墙 → 对角凹角/中心三变体(下位函数)
|
||||
if nf and ef and sf:
|
||||
return _tiles["wall_end_w"] # 仅西墙(端头·东连墙)
|
||||
if ef and sf and wf:
|
||||
return _tiles["wall_end_s"] # 仅北墙(端头·南连地板、北连墙)
|
||||
if nf and sf and wf:
|
||||
return _tiles["wall_end_e"] # 仅东墙(= end_w 镜像)
|
||||
if nf and ef and wf:
|
||||
return _tiles["wall_end_n"] # 仅南墙(端头·北向死头、南连墙)
|
||||
if nf and sf:
|
||||
return _tiles["wall_hrun"] # 上下地板 = 横条带中段
|
||||
if ef and wf:
|
||||
return _tiles["wall_vrun"] # 左右地板 = 竖条带中段
|
||||
if nf and wf:
|
||||
return _tiles["wall_nw"] # 凸角(上+左地板)
|
||||
if nf and ef:
|
||||
return _tiles["wall_ne"] # 凸角镜像
|
||||
if sf and wf:
|
||||
return _tiles["wall_sw"] # 凸角(下+左地板)
|
||||
if sf and ef:
|
||||
return _tiles["wall_se"] # 凸角镜像
|
||||
if nf:
|
||||
return _tiles["wall_n"] # 北缘(上方地板)
|
||||
if ef:
|
||||
return _tiles["wall_e"] # 东缘(镜像件)
|
||||
if sf:
|
||||
return _tiles["wall_s"] # 南缘(下方地板)
|
||||
return _tiles["wall_w"] # 西缘(仅西地板——16 情形穷尽收尾)
|
||||
|
||||
|
||||
# 四邻皆墙格:对角凹角优先 nw > ne > sw > se(词表 §三.2——双凹角不做专件,多对角地板回落
|
||||
# 首中单凹角件,残留 1px 缝为已裁决可接受限);无对角地板 → 中心三变体按格坐标哈希 60/20/20
|
||||
func _wall_center_tile(c: Vector2i) -> Texture2D:
|
||||
if not _is_wall(c + Vector2i(-1, -1)):
|
||||
return _tiles["wall_in_nw"] # 西北对角是地板
|
||||
if not _is_wall(c + Vector2i(1, -1)):
|
||||
return _tiles["wall_in_ne"] # 东北对角是地板(镜像件)
|
||||
if not _is_wall(c + Vector2i(-1, 1)):
|
||||
return _tiles["wall_in_sw"] # 西南对角是地板
|
||||
if not _is_wall(c + Vector2i(1, 1)):
|
||||
return _tiles["wall_in_se"] # 东南对角是地板(镜像件)
|
||||
var m := posmod(_cell_hash(c), 10)
|
||||
if m < 6:
|
||||
return _tiles["wall_center"] # 6/10 = 60%
|
||||
if m < 8:
|
||||
return _tiles["wall_center_crack"] # 2/10 = 20%
|
||||
return _tiles["wall_center_speckle"] # 2/10 = 20%
|
||||
|
||||
|
||||
# 地面瓦片五变体按格坐标哈希均匀分配(词表 §一 floor_1..5 / §三.3「同法哈希分配」;
|
||||
# posmod 保非负下标)
|
||||
func _floor_tile_for(c: Vector2i) -> Texture2D:
|
||||
return _floor_tiles[posmod(_cell_hash(c), _floor_tiles.size())]
|
||||
|
||||
|
||||
# ---- 自绘光标纹理(镐/旗——引擎内置光标无此语义;程序化占位,headless 跳过) ----
|
||||
|
||||
@@ -47,8 +47,9 @@ const DARK_TEXT_FAINT := Color8(160, 150, 138)# 未达节点文字
|
||||
|
||||
const BRICK := Color8(201, 175, 131) # 棋盘·未开掩尘地砖 #C9AF83
|
||||
const FLOOR := Color8(179, 154, 120) # 棋盘·已开裸土 #B39A78
|
||||
const DIG_EDGE := Color8(120, 190, 120) # 可挖域呼吸微光绿
|
||||
const DIG_EDGE_DEEP := Color8(46, 80, 60) # 可挖域呼吸暗端(lerp 目标)
|
||||
const CONTACT_GLOW := Color8(214, 236, 255) # 可挖域接触带微光(蓝族浅一档·近白蓝——art-bible §3.2 v2.8 定稿;
|
||||
# 旧绿相 DIG_EDGE 随画法切换退役 2026-09-26 批)
|
||||
const CONTACT_GLOW_DEEP := Color8(150, 190, 230) # 接触带呼吸暗端(lerp 目标)
|
||||
|
||||
const BG_ROOT := Color8(30, 25, 20) # 屏幕根底
|
||||
const BG_OVERLAY := Color8(28, 22, 18) # 模态遮罩底
|
||||
@@ -80,6 +81,16 @@ static func motion(dur: float) -> float:
|
||||
const TEX_HERO_IDLE := "res://assets/art/character/character_hero_idle.png"
|
||||
const TEX_HERO_WALK := "res://assets/art/character/character_hero_walk.png"
|
||||
const TEX_HERO_PORTRAIT := "res://assets/art/character/character_hero_portrait.png" # B 区站桩立绘 48×48(源档 candidates/hero-idle/hero_idle_01.png,2026-09-26 用户点名换装)
|
||||
# 敌种立绘(B 区站桩 2026-09-26 槽接线批)——文件键 = 数据表主键 enemy_id(圣经 §8.3 命名规范),
|
||||
# 键集 = art-bible §4.6.4 八敌种;素材批入库前全部缺位(load_tex→null→字形回退),入库即显示零代码换装
|
||||
const TEX_ENEMY_GOBLIN := "res://assets/art/character/character_enemy_goblin.png" # 地精
|
||||
const TEX_ENEMY_BUGBEAR := "res://assets/art/character/character_enemy_bugbear.png" # 熊地精
|
||||
const TEX_ENEMY_OGRE_CHIEF := "res://assets/art/character/character_enemy_ogre_chief.png" # 食人魔酋长
|
||||
const TEX_ENEMY_GIANT_SPIDER := "res://assets/art/character/character_enemy_giant_spider.png" # 巨蜘蛛
|
||||
const TEX_ENEMY_DRIDER := "res://assets/art/character/character_enemy_drider.png" # 蛛化卓尔精灵
|
||||
const TEX_ENEMY_DUERGAR := "res://assets/art/character/character_enemy_duergar.png" # 灰矮人
|
||||
const TEX_ENEMY_HOOK_HORROR := "res://assets/art/character/character_enemy_hook_horror.png" # 钩爪恐魔
|
||||
const TEX_ENEMY_DUERGAR_KING := "res://assets/art/character/character_enemy_duergar_king.png" # 灰矮人石君王
|
||||
|
||||
|
||||
# 素材纹理守卫装载(exists 检查避开缺位树上 ResourceLoader 报错刷屏——冒烟/无素材检出静默回退)
|
||||
|
||||
@@ -461,4 +461,5 @@
|
||||
171. **站桩本体 Node2D 化批(Phase B T3,2026-09-26,本会话——循环 1 最重卡;worktree battle-stage-node2d-20260926)**:站桩本体自 Control(旧 StandeeView **退役删除**)平移为 Node2D 世界精灵 **standee_body.gd**(新件,无 class_name 经 preload)。**行为面 17 方法契约逐项保持(C3)**——set_data/set_hero/_set_hp/set_idle/set_effects/set_effects_cleared_feedback/set_order/set_pending/_play_intent_motion/set_portrait_texture(tex,flip)/mark_dead/is_dead/flash_hit/_revive/_update_name_line/_refresh_portrait_glyph+is_dead,调用点 hud_presenter:53-54/79-80、main:309/441/475/495/503、main:768/770 零改排。**等价平移清单(C9)**——立绘=set_portrait_texture 惰性 Sprite2D(NEAREST+flip_h+整数 2×=48 源盒 96px)缺位回退字形(人/▂/▆/█/✕/敌 draw_string);底座=UiKit.panel_flat(STONE 系) StyleBox.draw 直绘;血条=直角矩形 hp_value 属性 tween 0.15 递减(引擎默认主题深底/蓝填充近似平移——色值列目检清单);顺位徽标 ①②③ GOLD_DEEP;意图徽标=draw_set_transform 弹入 scale 1.6→1+字形前倾 4°→0(旧只转字形 Label——贴图态无动画等价保持);名字行=护甲图标+纯名 draw_string 居中(AC 不展示 2026-09-26 终裁);受击闪白 modulate 1.6/1.4/1.2→白/死灰;死亡=灰化+rotation 2.5/-1.5/0 摇摆塌陷+意图退位(禁瞬消)+**状态行随 mark_dead 同拍隐藏(代拍板②待追认)**;复活=全态重置。**批内代拍板默认(待追认)**——①slot_row+悬停 tooltip 保留 Control 载体挂壳层(_companion_layer 顶层,敌伴随件宿主=**enemy_box 语义改写「站桩壳层伴随件容器」HBoxContainer→Control**,手动定位随世界同步,探针 :97 计数面不变);②定位同步=world_to_shell 单点(T2 建挂),_sync_layout 挂点=ready/NOTIFICATION_RESIZED/_row.resized(明细带展收改行高随动)/set_enemies 重建,站桩盒高=行高(旧 HBox FILL 拉伸等价)、敌右对齐 +8 间距等价;③hero_standee/enemy 站桩成员类型 StandeeView→Node2D(StandeeBody),**hero_standee_center/enemy_standee_center 改 world_to_shell(本体中心)=壳层口径(C4)**。ui_probe 敌站桩断言等价改写(台账 170 前例):穿透明(enemy_box 子件 _name_label/_armor_icon/_intent_badge/_hp_bar)→本体出口 enemy_body_at(i)+name_line_probe()/intent_probe()/has_world_hp_bar——呈现口径逐字保持。**踩坑记录**——standee_body 漏声明 _portrait_tex 成员→编译连坐 main.gd 假性两错(w/h 推断失败),editor --quit 前置闸暴露后修复。**验证**——editor --quit 0 error+冒烟 557/0(=基线零增删)+五探针全绿(ui_probe/ui_click 问题=0/ui_tune/ui_input 十一断言/layout 外框零漂移 stage 1280×252 逐位=T0 基线)+static_scan exit0+文档三闸零漂移。进入 T4。
|
||||
172. **信号与演出等价证明批(Phase B T4,2026-09-26,本会话——循环 1;worktree battle-stage-node2d-20260926,零代码变更纯取证)**:等价证明落盘 `production/qa/battle-stage-node2d-等价证明-2026-09-26.md`——①**调用点 grep 对比零 diff**:main.gd→stage 九处调用(309/310/439/441/475/495/503/768/770)与 hud_presenter→hero_standee 四处投喂(53/54/79/80)逐字节一致;hud_presenter/main/core/** 文件级 git diff 基线=零行变更(投喂链零改动实证+核心层零接触)。②**时序常量逐字对照**——血条递减 0.15/意图弹入 0.10+0.16/前倾 0.10+0.14/死亡摇摆 0.12+0.1+0.08 与 modulate (0.62,0.62,0.62,0.9)/受击闪白 0.08+0.2 与 (1.6,1.4,1.2)/复活复位/清空反馈 1.2+0.8 全部逐字同(前倾项注记:旧仅转字形 Label、贴图态无动画——新等价保持)。③**写路径逐行同构**——on_step_row_fx(早退链+flash+killed→mark_dead)/set_enemies 数量分叉/clear_enemies/gray_all_enemies/set_round_text/set_settle_focus 逐行同构;弹道落点 hero/enemy_standee_center 签名不变、实现改 world_to_shell(本体中心)=壳层口径保持(C4)。④结构性差异五笔登记(本体载体/slot_row 壳层化/enemy_box 语义/血条直角矩形呈现/ui_probe 本体探针出口)=非漂移改判,指向台账 170/171。轻闸全绿(冒烟 557/0+ui_probe+ui_input 十一断言+static_scan exit0)。进入 T5。
|
||||
173. **探针取证与断言同步批(Phase B T5,2026-09-26,本会话——循环 1;worktree battle-stage-node2d-20260926,零常驻代码变更)**:①**临时取证探针**(跑完即删,台账 152 先例;踩坑复录=裸 .gd 无 tscn 载体跑场景探针=静默挂死,补 tscn 包装解):真实战斗态 B 区场景树 dump——**世界子树(SubViewport 内)Button=0/GridContainer=0/HBox=0**(站桩载体归零证);世界站桩本体 hero=true+enemies=1(StandeeBody)、伴随件容器子件=1 与本体数一致;壳层 HBox 逐件语义标注=文本行载体+StatusSlotRow 伴随件+log 内部(零站桩载体残留)。②ui_probe 敌站桩断言等价改写已于 T3 随批落地(enemy_box 子件穿透明→stage.enemy_body_at(i).name_line_probe()/intent_probe()/has_world_hp_bar 本体出口,呈现口径逐字保持——台账 171 改判记录);ui_click_probe :223 hero_standee.slot_row 伴随件引用=零改动即兼容(tooltip 机制零返工——代拍板①实证)。③ui_input_probe 十一断言原样全绿(B 区改造零波及 D 区实证——grep stage/standee/enemy 零命中在案)。取证报告本条即档案。轻闸全绿(冒烟 557/0+五探针 PASS)。进入 T6。
|
||||
174. **文档随批与登记批(Phase B T6,2026-09-26,本会话——循环 1)**:①architecture.md——Last Updated 行+D1 层表形态行补 BattleStageView 例外(StageWorld/StandeeBody,slot_row 伴随件留壳层,Phase A/B 双注记引 ADR-0006)。②HUD框架.md——v0.10 渲染技术注记行(Phase B 同构改造/契约不变/伴随件/C6 复用/预算不变/等价证明外链)。③battle.md——2026-09-26 实现注记修订行(B 区 Node2D 化/setter 面保持/弹道锚点壳层口径/外框 252px 零改动)。④board-node2d-migration-plan.md §3——「Phase B 预留」改写为「已落地」(实施面三点+挂点复用)+**样张硬前置条款按裁决①作废落文**(样张冻结只卡换皮/演出批=循环 2 前置,不卡结构迁移)。⑤Alpha 清单状态列更新(A5 已实证转周期化复跑件待建/F1F2 全绿注记/F4 待 T7 对拍+修订记录行)。⑥06 待办核对=本批无解决条目(呈现层测试分级条 B/C 档与本批无涉;样张硬前置非 06 登记项)。验证=文档三闸对 T0 基线逐字节零新增(lint/link/term 三 diff 空)+轻闸随批全绿。进入 T7。
|
||||
174. **文档随批与登记批(Phase B T6,2026-09-26,本会话——循环 1)**:①architecture.md——Last Updated 行+D1 层表形态行补 BattleStageView 例外(StageWorld/StandeeBody,slot_row 伴随件留壳层,Phase A/B 双注记引 ADR-0006)。②HUD框架.md——v0.10 渲染技术注记行(Phase B 同构改造/契约不变/伴随件/C6 复用/预算不变/等价证明外链)。③battle.md——2026-09-26 实现注记修订行(B 区 Node2D 化/setter 面保持/弹道锚点壳层口径/外框 252px 零改动)。④board-node2d-migration-plan.md §3——「Phase B 预留」改写为「已落地」(实施面三点+挂点复用)+**样张硬前置条款按裁决①作废落文**(样张冻结只卡换皮/演出批=循环 2 前置,不卡结构迁移)。⑤Alpha 清单状态列更新(A5 已实证转周期化复跑件待建/F1F2 全绿注记/F4 待 T7 对拍+修订记录行)。⑥06 待办核对=本批无解决条目(呈现层测试分级条 B/C 档与本批无涉;样张硬前置非 06 登记项)。验证=文档三闸对 T0 基线逐字节零新增(lint/link/term 三 diff 空)+轻闸随批全绿。进入 T7。
|
||||
176. **换肤最小可看批——格面瓦片接线+敌像槽接线+接触带微光切换(2026-09-26,本会话——用户令「其他任务子 agent 委派」;worktree skin-wiring-20260926,两个并行子 agent+主会话微光,主编排者统一跑闸)**:①**格面高墙瓦片接线**(子 agent A,按任务书+词表逐条)——board_view.gd 新增 16 墙+5 地面瓦片路径常量(单点本文件,ui_kit 让位并行避撞)+整批守卫装载 `_tiles_ok`(21 枚全成才启用,任一缺位整批静默回退程序化平色,禁同板混渲染,fresh checkout 安全)+查表合成器(16 正交情形 Python 穷举对词表逐条命中/镜像 6 件 flip_x 运行时合成禁旋转/凹角回落 nw>ne>sw>se/center 变体+地面 5 变体格坐标哈希 60/20/20——纯确定性无 RNG)+`_paint_cell` 瓦片分支(tex_base=查表件,bg_sb 降透明描边载体,呼吸/蓝框通道不变)+cell_unit `_draw` 瓦片态补画 bg_sb 覆盖层;非整数 NEAREST 缩放=台账 166 已拍板档。②**敌人立绘槽接线**(子 agent B)——ui_kit 八敌种 TEX_ENEMY_<id> 常量(§4.6.4 键集,域_对象键命名)+battle_stage_view `_enemy_portrait_tex` match 映射(显式函数,UiKit const 不可动态 get 已注记)+set_enemies 重建拍 set_portrait_texture 接线(tex=null 字形回退逐位等价——素材零张在库为预期态,入库即自动显示零代码换装);签名零变更,ui_probe 断言面零触碰。③**接触带微光切换**(主会话,§3.2 v2.8 画法落码)——旧「墙格整框绿相」退役(DIG_EDGE/DIG_EDGE_DEEP 常量删)→**英雄格周界空间侧**:正交邻墙=整条边/斜向=共享角点圆+两侧各半条边(坐标推导注释在案,SW/SE+NE/SE 两处半带首版写反已修),带宽 4px 贴格边,蓝族近白蓝 CONTACT_GLOW #D6ECFF↔CONTACT_GLOW_DEEP 呼吸 0.48Hz 保留,减动效停格静态可辨;承载=英雄格 CellUnit 三属性(bands/corners/col),refresh+set_dig_glow_enabled(true) 双挂点,rebuild 复位。**验证**——editor --quit 0 error+冒烟 557/0+五探针全绿(probe stage 外框逐位零漂移)+static_scan exit0+文档三闸对基线零漂移+**MC 12 局 sha256=de8225b3 与基线逐位一致**(渲染批零核心接触铁证)。**遗留知悉**——词表 §五已知限制未修(成对双凹角 1px 缝/混合凹角缺落点/平铺重复感,按纪律不顺手修);瓦片态字形经 NEAREST 采样微锐化=预期;素材缺位回退路径全部保留。**待实机目检**——格面瓦片观感/微光蓝带/墙群拼缝(用户终验,任务书 §3.5)。
|
||||
Reference in new issue
Block a user