《魔法植物》大地图设计(promote004 定向多区域)

本文介绍 magic-plant-demopromote004promote004.md)落地的大地图设计:从"66×38 一张径向小图"扩到 400×320 定向多区域大地图。 配套:map_progress.md(进度区域设计原则)· dev_manual.md §6(地图/生成) · m6_append_review.md(实现复盘)。 日期:2026-09-03 · 版本:0.1-preview · 程序化种子:MapGenerator.generate(seed)(同 seed 必同图)


0. 一句话概述

把地图从"基地居中、径向五档"改成"沿东北↔西南主轴做定向分区的 45° 菱形大地图":陆地划成 T0基地 → T1林缘 → T2中环 → T3洞窟 → Boss预留 五段,沿 p = x − y(NE 大、SW 小)从东北到西南依次排开;水做整图外缘,河流/石墙做区域交界的门带。每个区域面积精确 = 当前图面积 × 指定倍数。

        T2 中环(东北 · 跨河)
             ▲  桥 bridge
   T1 林缘(中 · 包基地四周,四向延申不同)
      ▲ 魔法门 magic_gate(西南石墙)
   T3 洞窟(西南 · 无光)
      ▲  最终门 final
   Boss 预留(最西南 · 占位)

1. 世界与网格

说明
MapGenerator.TILE 16 px 每格边长
MapGenerator.GRID Vector2i(400, 320) 格数;x∈[-200,200)y∈[-160,160)
MapGenerator.HALF Vector2i(200, 160) 半宽/半高
世界尺寸 6400 × 5120 px 400×16 × 320×16
BASE_CENTER Vector2i(0,0) 基地中心(世界原点)
SAFE_R 10 (tile) 基地安全半径,无怪无危险 tile
AREA0 66×38 = 2508 当前图面积,用作"倍数"基准

坐标换算:cell_world(c) = Vector2(c.x*16+8, c.y*16+8)world_cell(p) = Vector2i(floor(p.x/16), floor(p.y/16))(逆用,供 region_at_world 判玩家所在区)。


2. 区域模型(RegionMap.Region

enum Region { BASE, T1, T2, T3, BOSS }

每格一个区域标签,供怪/菇/门/黑暗定位。面积目标 = AREA0 × 倍数(用户拍板口径):

区域 倍数 目标面积(格) 构成
BASE T0 安全区 基地(家/田/床/合成台/魔法书),无怪
T1 林缘 12× 30,096 围绕基地四周展开,教学与首战
T2 中环 15,048 东北,跨河
T3 洞窟 22,572 西南,无光
BOSS ≥10,032 最西南,占位(兜底吸收剩余陆地)

陆地总数 = (12+6+9+4)×2508 = 31×2508 = 77,748 格;其余(128,000 − 77,748 = 50,252 格)为水/外缘


3. 布局与方向(为什么是 45° 菱形)

地图不是正方形,而是沿 NE↔SW 主轴旋转了 45° 的菱形(见 §10 截图 map_regions.png)。原因是分区用 p = x − y 做主序,q = x + y 做带宽:

  • p = x − y:东北角(x 大、y 小)→ p 最大;西南角 → p 最小。分区从东北到西南按 p 降序
  • q = x + y:夹角带 |q| ≤ qmax 内的格子才算陆地;qmax 由二分校准(见 §4)。

各方向延申(用户要求,对应 GATE_TARGETS 落点):

方向 延申 处理
右上(NE / 东北) 最多 T2 跨河,主门 bridge 落点 (46,-46)
左上(NW) / 右下(SE) 适当 各拓出一块后直接水缘作外轮廓障碍
左下(SW / 西南) 最少 却画石墙当障碍,需 magic_gate 通关

4. 分区几何(p-轴定向分区 + qmax 二分校准)

MapGenerator._calibrate_partition()

  1. 二分找 qmax:让 |q|≤qmax(且排除基地安全区)的陆地格数 = LAND_TARGET(77,748)。lo=60, hi=260,逐步收敛。
  2. 收集陆地格,按 p 降序(NE→SW)排序 land.sort_custom(_p(a) > _p(b))
  3. 沿 p 降序分切ZONE_ORDER = [T2, T1, T3, BOSS]。从最大的 p(东北)开始,依次填满 CAPS 目标面积;Boss 用 cap=∞ 兜底,吸收剩余全部陆地(故 ≥4×)。
  4. 记录各区边界 p 值 _pcut_t2/_pcut_t1/_pcut_t3,作为后续画河/画墙的切割线。

面积精确:T2/T1/T3 严格 = 倍数;Boss ≥ 4×(无上限,吃尾)。


5. 门的布局(GATE_DEFS / GATE_TARGETS

const GATE_DEFS := {
    &"bridge":     {"before": T1, "after": T2,  "dir": Vector2i(1,-1),  "tile": "RIVER"},
    &"magic_gate": {"before": T1, "after": T3,  "dir": Vector2i(-1,1),  "tile": "WALL"},
    &"final":      {"before": T3, "after": BOSS, "dir": Vector2i(-1,1),  "tile": "WALL"},
}
const GATE_TARGETS := {
    &"bridge":     Vector2i(46,-46),   # NE(T1 臂端 / 河对岸)
    &"magic_gate": Vector2i(-22,22),   # SW 石墙
    &"final":      Vector2i(-96,96),   # 更远 SW(T3↔Boss)
}

画交界带 → 穿门洞

  • _cut_for(gid) 取对应区域边界 p 值;在边界 |p − cut| ≤ 厚 处铺 WATER(桥,厚 2)或 WALL(石墙,厚 2)。
  • _punch_gate(gid) 在交界带内找"before 侧距目标最近的一格",沿 dir 往 after 侧穿。关键修复(promote004 bug):不停在"第一个 after 格"(那格仍裹在河/墙带里),而是穿到 _is_dry(nxt)(非 WATER/WALL 的干地)才停——保证门洞两侧都落在可走地面,经 _carve_path 主路 + Gate 挡板即可"先连通、用门阻碍"。记录门 {cell, across, rect, before, after}(rect 供 Gate.setup 摆碰撞/交互)。

开锁无环(map_progress §2 关键红线):每个开锁物只能由该门之前已可达区域的材料合成——桥钥←T1、魔法门钥←T2、光明晶石←T2夜(灼心芝挪到 T2 夜可采)、最终钥←T3。绝不出现"所需材料在门后"的卡死。


6. 地表与障碍

  • 地表_sample_terrain):FastNoiseLite(TYPE_SIMPLEXfrequency=0.018fractal_octaves=4
  • 每格先设 GRASS;噪声 >0.52FARM(农田块);< -0.86 且靠近带缘 → 局部水袋(NW/SE 边缘)。
  • 没有任何 zone 认领的格(带外、四角)→ WATER —— 这就是"水做整图外缘"。
  • 基地安全区强制回填草地。
  • 交界_place_gates_and_features 在 T1/T2 画河、T1/T3 与 T3/Boss 画石墙(见 §5)。
  • 主路径_carve_paths 从基地沿 Drunkard's Walk 挖一条主路穿三处门 gap(wobble=0.25),门内直线贯通(wobble=0.0)。
  • 障碍_plant_obstacles):Poisson 撒(约 6% 草地)、(约 8%,仅 T2/T3),避开基地与路径,且 _near_any 去重。
  • 装饰_scatter_deco):草点/花/小石(约 5% 草地)。

7. 区域内容规则(level_map.gd spawn)

怪物与蘑菇MonsterData.region / CropData.region 分带_region_for_tagT2/T3 精确,其余归 T1):

  • 怪物成群 3–5(promote004 集群遇敌):_spawn_monsters 在目标区选簇中心,_nearest_n 取最近 3–5 格各放一只,clusters = min(2, cells/5) 最多两簇。
  • 蘑菇按 zone 分散、稀疏_spawn_wild):count = clamp(cells/400, 3, 28),按 crop.region 落区,昼夜决定可见。
  • 远离基地安全半径_safe_spawn_cellsSAFE_R+3 内、障碍格上不刷)。

8. T3 无光洞窟(DarknessCave

features/lighting/darkness.gdclass_name DarknessCave extends CanvasLayer,放在 Main 的 UI CanvasLayer 之前,故遮世界、露 HUD):

状态 遮罩 alpha 视觉
不在 T3 0 正常
在 T3 且未戴 light_crystal 0.965 近全黑(Color(0,0,0.02)
在 T3 且戴着 light_crystal 0.22 微弱洞窟调性(可辨认)
  • 逻辑:_target_alpha()level_map.region_at_world(player.global_position),只在 == T3 时才非 0;再读 PlayerState.is_equipped(&"light_crystal") 分档。
  • 过渡:_processlerpf 平滑淡入/淡出。
  • 纯表现层:只读 PlayerState/LevelMap,不改数据。

9. 进度闭环(开锁无环 ladder)

基地(T0) 种田/采集/睡觉
   │ 靠「T1 蘑菇 + 林缘怪掉」合成 桥钥
   ▼
过河 bridge ──► T2 中环 采蘑菇/打怪
   │ 靠「T2 蘑菇 + 中环怪掉」合成 魔法门钥;夜间采 灼心芝 → 光明晶石
   ▼
魔法门 magic_gate ──► T3 洞窟(须戴光明晶石才看得见)
   │ 靠「T3 蘑菇 + 洞窟怪掉」合成 最终钥
   ▼
最终门 final ──► Boss 地牢(预留占位)
  • 种田 = 变强:合成/升级所需蘑菇数大幅上调(见 §11),采集几下不够,必须回家种。
  • 昼夜驱动:灼心芝(光明晶石原料)只在 T2 夜间可采 → 强迫"挑时段出门"。
  • 首个法术:开局解锁 绽华/星刺(基础攻击),其余靠首次采集对应蘑菇解锁。

10. 截图对照

截图 内容 验证点
map_regions 45° 菱形分区配色:青=T2(NE)/绿=T1(中)/紫=T3(SW)/红=Boss(最SW)/白圈=基地 定向分区:五区沿 NE→SW 排开,基地居中
map_terrain 实地景:绿色草地/棕色农田/蓝色水外缘与河流、黑色石墙带、土黄 Drunkard's Walk 主路 地形系统:水外缘、河/墙交界带、主路径穿门
sys_upgrade 魔法书·魔药祭坛:列出带 upgrade_cost 的蘑菇法术,显示 升阶效果/消耗(锥心芝 10/4) 系统层:法术升级 UI 读 upgrade_cost 扣料
sys_bag 背包:光明晶石带绿框=已穿戴 系统层:装备入口(点击穿/脱,绿框标注)
sys_dark_no T3 未戴光明晶石:近全黑 T3 黑暗:无光门槛(alpha≈0.965)
sys_dark_yes T3 戴上光明晶石:视野恢复、洞窟色调 T3 黑暗:穿戴恢复(alpha≈0.22)

11. 数据从哪改(用户核心问题)

.tres(Content 懒加载自取),别信 tools/generate_content.gd(已与 .tres 脱节):

想改 目录/文件 字段
配方材料量 resources/recipes/*.tres inputs[].count(桥钥=8银芒+1魔牙、魔法门钥=8晶铠+1孢粹、光明晶石=8灼心芝+1腐脂、最终钥=8绯泪+1洞窟之核)
法术升级消耗 resources/abilities/*.tres upgrade_cost(第1级基数 = 本系菇×4 + 虹髓芝×1;cost_for_rank(rank) 按 rank 递增=越升越贵)
作物产量 resources/crops/*.tres yields[].count(3→5)
野生菇所属 zone resources/crops/*.tres region = &"T1"/"T2"/"T3"
怪物所属 zone resources/monsters/*.tres region
装备/穿戴 resources/items/light_crystal.tres type=3(EQUIP)player_state.gdequip/unequip/is_equipped
区域面积倍数 scenes/map_generator.gd CAPS + AREA0
门落点/方向 scenes/map_generator.gd GATE_DEFS/GATE_TARGETS

12. 验证

  • --import exit 0(无解析错)。
  • tools/map_gen_test.gd35/0(网格 / 面积比 / 基地安全 / 各门 gap 连通 / 各区可达 / seed 复现 / 成群 + 新增:门洞落干地(across 非水、cell→across 全程 PATH))。
  • 多 seed 复检:12 seed × 3 门洞 → across 均落干地、桥洞跨河连续(防随机 seed 复现"缺区块")。
  • --headless 主场景引导 exit 0。
  • tools/sys_verify.gd22/0(升级扣料/升阶/材料不足 false/无素材基础法术不可升、穿脱、T3 黑暗 0.96↔0.33)。
  • tools/sys_shot.gd(窗口模式,勿 --headless):shots/sys_{upgrade,bag,dark_no,dark_yes}.png 目视核验。