Files

475 lines
20 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// genmaps.js — 生成《崩坏童话:蜜糖村》全部 10 张 Tiled 地图 (.tmx)
// 用法: /Applications/Tiled.app/Contents/MacOS/Tiled -e tools/tiled/genmaps.js
// 说明: -e 模式无编辑器,tiled.open/TileMap 绘制 API 不可用,故用 TextFile 直接写 .tmx XML。
// 导出: Tiled --export-map --embed-tilesets in.tmx out.json (必须 --embed-tilesetsJSON 才有 image 字段)
//
// 约定(与 CONTRACT.md §3 一致):
// - 固定三层:ground(瓦片层)/ obstacles(瓦片层,图层属性 collides=true/ objects(点对象层)
// - 瓦片 gid = CONTRACT §2 瓦片 id + 1obstacles 中空格 = gid 0
// - 点对象坐标 = 所在瓦片中心像素 (tx*16+8, ty*16+8)
// - door 属性 target=目标地图 key, spawn=目标地图中的 spawn id= "from_"+本图 key),双向成对
var OUT = '/Users/leidianyayi/Documents/GitHub/ModelTest20260714/Kimi-K3/public/assets/maps/';
// ---- 瓦片 gid 表(id+1----
var G = {
grass:1, flowerA:2, flowerB:3, deepGrass:4, dirt:5, stone:6, stoneAlt:7, brick:8,
waterA:9, waterB:10, shoreN:11, shoreS:12, shoreW:13, shoreE:14,
bedPink:15, bedYellow:16, berry:17, berryEmpty:18,
treeTL:19, treeTR:20, treeBL:21, treeBR:22, bush:23, stump:24, rock:25, sign:26,
fenceH:27, fenceV:28, lamp:29, ribbonR:30, ribbonY:31, ribbonB:32,
creamWall:33, creamWallWin:34, woodWall:35, roofOL:36, roofOM:37, roofOR:38,
doorT:39, doorTop:40, window:41, chimney:42, wellTL:43, wellTR:44, wellBL:45, wellBR:46,
mailbox:47, board:48, floorA:49, floorB:50, wallIn:51, wallInWin:52,
bedTL:53, bedTR:54, bedBL:55, bedBR:56, counterL:57, counterR:58, oven:59,
shelfE:60, shelfF:61, table:62, chair:63, rug:64, calendar:65, recipe:66, fileP:67,
picTL:68, picTR:69, picBL:70, picBR:71, benchL:72, benchR:73, stool:74, cabinet:75,
fridge:76, sink:77, plant:78, barrel:79, crate:80, fogA:81, fogB:82, fogC:83,
wFloor:84, wWall:85, wPanel:86, wDoor:87, wBedTL:88, wBedTR:89, wBedBL:90, wBedBR:91,
wCab:92, wMon:93, wCur:94, wFloor2:95, wLamp:96, ladder:97, bridgeH:98, bridgeV:99,
mushroom:100, flR:101, flY:102, flB:103, honey:104, bread:105, letter:106, book:107,
candle:108, basket:109, bucket:110, broom:111, cake:112, roofRL:113, roofRM:114, roofRR:115,
roofBL:116, roofBM:117, roofBR:118, pinkWall:119, pinkWallWin:120, stoneWall:121,
stoneWallWin:122, awning:123, clock:124, flag:125, garC:126, garM:127, empty:128
};
// ---- 基础工具(ES5----
function grid(w, h, v) {
var a = [];
for (var y = 0; y < h; y++) {
var r = [];
for (var x = 0; x < w; x++) r.push(v);
a.push(r);
}
return a;
}
function newMap(w, h) { return { w: w, h: h, ground: grid(w, h, 0), obs: grid(w, h, 0), objs: [] }; }
function fill(l, x, y, w, h, g) {
for (var j = y; j < y + h; j++)
for (var i = x; i < x + w; i++) l[j][i] = g;
}
function put(l, x, y, g) { l[y][x] = g; }
// 确定性散点随机数(固定种子,结果可复现)
function rnd(x, y, s) {
var n = Math.sin(x * 127.1 + y * 311.7 + s * 74.7) * 43758.5453;
return n - Math.floor(n);
}
function obj(m, name, tx, ty, props) {
m.objs.push({ name: name, x: tx * 16 + 8, y: ty * 16 + 8, props: props });
}
function spawn(m, tx, ty, id) { obj(m, 'spawn', tx, ty, [['id', id]]); }
function door(m, tx, ty, target, sp) { obj(m, 'door', tx, ty, [['target', target], ['spawn', sp]]); }
function npc(m, tx, ty, id) { obj(m, 'npc', tx, ty, [['id', id]]); }
function inter(m, tx, ty, id) { obj(m, 'interact', tx, ty, [['id', id]]); }
function tree2x2(m, x, y) {
put(m.obs, x, y, G.treeTL); put(m.obs, x + 1, y, G.treeTR);
put(m.obs, x, y + 1, G.treeBL); put(m.obs, x + 1, y + 1, G.treeBR);
}
// 草地散点装饰(ground 层,无碰撞)
function scatter(m, seed, d) {
for (var y = 0; y < m.h; y++) {
for (var x = 0; x < m.w; x++) {
var r = rnd(x, y, seed);
var g = 0;
if (r < d[0]) g = G.flowerA;
else if (r < d[1]) g = G.flowerB;
else if (r < d[2]) g = G.deepGrass;
else if (r < d[3]) g = [G.flR, G.flY, G.flB][(x + y) % 3];
if (g) m.ground[y][x] = g;
}
}
}
// 室外房屋:5 宽 × 4 高,朝南单门,整体进 obstacles
function houseS(m, x, y, roofL, roofM, roofR, chimney) {
for (var i = 0; i < 5; i++) {
var t = (i === 0) ? roofL : (i === 4 ? roofR : roofM);
put(m.obs, x + i, y, t);
put(m.obs, x + i, y + 1, t);
}
if (chimney) put(m.obs, x + 1, y, G.chimney);
put(m.obs, x, y + 2, G.creamWall);
put(m.obs, x + 1, y + 2, G.creamWallWin);
put(m.obs, x + 2, y + 2, G.doorTop);
put(m.obs, x + 3, y + 2, G.creamWallWin);
put(m.obs, x + 4, y + 2, G.creamWall);
put(m.obs, x, y + 3, G.creamWall);
put(m.obs, x + 1, y + 3, G.creamWall);
put(m.obs, x + 2, y + 3, G.doorT);
put(m.obs, x + 3, y + 3, G.creamWall);
put(m.obs, x + 4, y + 3, G.creamWall);
}
// 室内外壳:木地板满铺(ground),墙围边(obstacles),底边留门(门瓦片在 ground)
function indoorShell(m, wins, doorX) {
for (var y = 0; y < m.h; y++)
for (var x = 0; x < m.w; x++)
m.ground[y][x] = ((x + y) % 2 === 0) ? G.floorA : G.floorB;
m.ground[m.h - 1][doorX] = G.doorT;
for (var x2 = 0; x2 < m.w; x2++) {
m.obs[0][x2] = G.wallIn;
if (x2 !== doorX) m.obs[m.h - 1][x2] = G.wallIn;
}
for (var i = 0; i < wins.length; i++) m.obs[0][wins[i]] = G.wallInWin;
for (var y2 = 1; y2 < m.h - 1; y2++) {
m.obs[y2][0] = G.wallIn;
m.obs[y2][m.w - 1] = G.wallIn;
}
}
// ================= 1. house 12×8 小满小屋 =================
function buildHouse() {
var m = newMap(12, 8);
indoorShell(m, [3, 8], 5);
// 床(睡觉过日)+ 床头日历(C1)
put(m.obs, 1, 1, G.bedTL); put(m.obs, 2, 1, G.bedTR);
put(m.obs, 1, 2, G.bedBL); put(m.obs, 2, 2, G.bedBR);
put(m.obs, 3, 1, G.calendar);
// 桌椅 + 盆栽 + 地毯
put(m.obs, 8, 4, G.table); put(m.obs, 7, 4, G.chair); put(m.obs, 9, 4, G.chair);
put(m.obs, 10, 1, G.plant);
put(m.ground, 5, 3, G.rug); put(m.ground, 6, 3, G.rug);
put(m.ground, 5, 4, G.rug); put(m.ground, 6, 4, G.rug);
spawn(m, 3, 3, 'default');
spawn(m, 5, 5, 'from_plaza');
door(m, 5, 6, 'plaza', 'from_house');
inter(m, 1, 3, 'bed');
inter(m, 3, 2, 'calendar');
return m;
}
// ================= 2. plaza 30×20 村广场(枢纽) =================
function buildPlaza() {
var m = newMap(30, 20);
fill(m.ground, 0, 0, 30, 20, G.grass);
scatter(m, 7, [0.05, 0.10, 0.15, 0.18]);
// 石路:南北 x=14/15,东西 y=9/10,通往四座房屋的小路
var y, x;
for (y = 0; y < 20; y++) {
put(m.ground, 14, y, (y % 3 === 0) ? G.stoneAlt : G.stone);
put(m.ground, 15, y, (y % 3 === 0) ? G.stoneAlt : G.stone);
}
for (x = 0; x < 30; x++) {
put(m.ground, x, 9, (x % 3 === 0) ? G.stoneAlt : G.stone);
put(m.ground, x, 10, (x % 3 === 0) ? G.stoneAlt : G.stone);
}
var stubs = [4, 11, 18, 25];
for (var s = 0; s < stubs.length; s++)
for (y = 5; y <= 9; y++) put(m.ground, stubs[s], y, G.stone);
// 中央广场砖(庆典场地核心)
fill(m.ground, 11, 8, 8, 5, G.brick);
// 庆典彩带(广场四角,装饰无碰撞;透明瓦片须放 obstacles 层,ground 层会露黑底)
put(m.obs, 11, 7, G.ribbonR); put(m.obs, 18, 7, G.ribbonY);
put(m.obs, 11, 13, G.ribbonB); put(m.obs, 18, 13, G.ribbonR);
// 四周房屋:小屋/杂货店=橙屋顶,面包房/诊所=红屋顶
houseS(m, 2, 1, G.roofOL, G.roofOM, G.roofOR, true); // house 门 x=4
houseS(m, 9, 1, G.roofRL, G.roofRM, G.roofRR, true); // bakery 门 x=11
houseS(m, 16, 1, G.roofOL, G.roofOM, G.roofOR, true); // shop 门 x=18
houseS(m, 23, 1, G.roofRL, G.roofRM, G.roofRR, false); // clinic 门 x=25
// 公告板 + 三个花坛 + 双子鸟大树
put(m.obs, 14, 8, G.board);
put(m.obs, 10, 8, G.bedPink); put(m.obs, 19, 8, G.bedYellow); put(m.obs, 14, 13, G.bedPink);
tree2x2(m, 12, 14);
// 村口邮筒(大宝)+ 路灯 + 装饰树/灌木
put(m.obs, 2, 8, G.mailbox);
put(m.obs, 10, 6, G.lamp); put(m.obs, 19, 6, G.lamp);
tree2x2(m, 1, 6); tree2x2(m, 27, 14); tree2x2(m, 1, 16);
put(m.obs, 8, 16, G.bush); put(m.obs, 21, 17, G.bush); put(m.obs, 16, 15, G.bush);
// 地图边缘装饰(留出 4 个路口)
function skip(x2, y2) {
return (y2 === 0 && (x2 === 14 || x2 === 15)) || (y2 === 19 && (x2 === 14 || x2 === 15)) ||
(x2 === 0 && (y2 === 9 || y2 === 10)) || (x2 === 29 && (y2 === 9 || y2 === 10));
}
function edge(x2, y2) {
var r = rnd(x2, y2, 9);
put(m.obs, x2, y2, r < 0.5 ? G.bush : (r < 0.75 ? G.rock : G.stump));
}
for (x = 0; x < 30; x++) { if (!skip(x, 0)) edge(x, 0); if (!skip(x, 19)) edge(x, 19); }
for (y = 1; y < 19; y++) { if (!skip(0, y)) edge(0, y); if (!skip(29, y)) edge(29, y); }
// 对象
spawn(m, 14, 11, 'default');
spawn(m, 4, 7, 'from_house'); // 落点距门 24px,防回弹
spawn(m, 11, 7, 'from_bakery');
spawn(m, 18, 7, 'from_shop');
spawn(m, 25, 7, 'from_clinic');
spawn(m, 1, 10, 'from_lake');
spawn(m, 28, 10, 'from_field');
spawn(m, 14, 2, 'from_well'); // 落点距门 24px,防回弹
spawn(m, 15, 18, 'from_fog');
door(m, 4, 5, 'house', 'from_plaza');
door(m, 11, 5, 'bakery', 'from_plaza');
door(m, 18, 5, 'shop', 'from_plaza');
door(m, 25, 5, 'clinic', 'from_plaza');
door(m, 0, 9, 'lake', 'from_plaza');
door(m, 29, 10, 'field', 'from_plaza');
door(m, 14, 0, 'well', 'from_plaza');
door(m, 15, 19, 'fog', 'from_plaza');
npc(m, 15, 8, 'afu'); // 公告板旁
npc(m, 12, 14, 'bird'); // 双子鸟,树上
npc(m, 7, 12, 'squirrel');
npc(m, 22, 14, 'fox');
npc(m, 3, 8, 'dabao'); // 村口邮筒旁(PRD §4
inter(m, 14, 9, 'noticeboard');
inter(m, 10, 9, 'flowerbed_1');
inter(m, 19, 9, 'flowerbed_2');
inter(m, 14, 14, 'flowerbed_3');
return m;
}
// ================= 3. bakery 15×10 面包房 =================
function buildBakery() {
var m = newMap(15, 10);
indoorShell(m, [3, 7, 11], 7);
fill(m.ground, 5, 5, 3, 2, G.rug);
// 两段柜台 + 烤炉(C2 配方纸在桌上)
put(m.obs, 4, 3, G.counterL); put(m.obs, 5, 3, G.counterR);
put(m.obs, 8, 3, G.counterL); put(m.obs, 9, 3, G.counterR);
put(m.obs, 12, 1, G.oven);
put(m.obs, 10, 6, G.table); put(m.obs, 11, 6, G.recipe);
put(m.obs, 13, 8, G.barrel); put(m.obs, 1, 8, G.plant);
spawn(m, 7, 6, 'default');
spawn(m, 7, 7, 'from_plaza');
door(m, 7, 8, 'plaza', 'from_bakery');
npc(m, 5, 2, 'yuanyuan'); // 柜台后
inter(m, 4, 4, 'counter_bread');
inter(m, 11, 7, 'recipe_paper');
return m;
}
// ================= 4. shop 15×10 杂货店 =================
function buildShop() {
var m = newMap(15, 10);
indoorShell(m, [3, 7, 11], 7);
fill(m.ground, 6, 6, 3, 2, G.rug);
// 上排 9 格满货架(C5:同一商品重复 9 格)+ 下排空满混排
var x;
for (x = 3; x <= 11; x++) put(m.obs, x, 1, G.shelfF);
for (x = 3; x <= 11; x++) put(m.obs, x, 4, (x % 3 === 0) ? G.shelfE : G.shelfF);
put(m.obs, 1, 7, G.crate); put(m.obs, 1, 8, G.barrel); put(m.obs, 13, 1, G.plant);
spawn(m, 7, 6, 'default');
spawn(m, 7, 7, 'from_plaza');
door(m, 7, 8, 'plaza', 'from_shop');
npc(m, 2, 5, 'mimi');
npc(m, 11, 7, 'hedgehog');
inter(m, 7, 2, 'shelf_count');
return m;
}
// ================= 5. clinic 12×8 诊所 =================
function buildClinic() {
var m = newMap(12, 8);
indoorShell(m, [3, 8], 5);
// 芙医生的桌 + 桌上文件(C8)
put(m.obs, 8, 2, G.table); put(m.obs, 9, 2, G.fileP);
put(m.obs, 9, 3, G.chair);
put(m.obs, 1, 1, G.cabinet); put(m.obs, 10, 6, G.plant);
spawn(m, 6, 5, 'default');
spawn(m, 5, 5, 'from_plaza');
door(m, 5, 6, 'plaza', 'from_clinic');
npc(m, 8, 1, 'fuyisheng'); // 桌后
inter(m, 8, 3, 'doctor_desk');
return m;
}
// ================= 6. lake 24×16 湖畔 =================
function buildLake() {
var m = newMap(24, 16);
fill(m.ground, 0, 0, 24, 16, G.grass);
scatter(m, 21, [0.06, 0.11, 0.15, 0.18]);
var x, y;
// 石路:东门(23,10)通向长椅与野餐区
for (x = 3; x <= 23; x++) put(m.ground, x, 10, (x % 3 === 0) ? G.stoneAlt : G.stone);
// 野餐布(T7,走上去触发,放 ground 可行走)
put(m.ground, 15, 10, G.picTL); put(m.ground, 16, 10, G.picTR);
put(m.ground, 15, 11, G.picBL); put(m.ground, 16, 11, G.picBR);
put(m.ground, 3, 12, G.mushroom);
// 湖水:北半边大片湖,水岸瓦片围边(全部进 obstacles)
for (y = 0; y <= 5; y++)
for (x = 2; x <= 21; x++)
put(m.obs, x, y, ((x + y) % 2 === 0) ? G.waterA : G.waterB);
for (x = 1; x <= 22; x++) put(m.obs, x, 6, G.shoreS);
for (y = 0; y <= 5; y++) { put(m.obs, 1, y, G.shoreW); put(m.obs, 22, y, G.shoreE); }
// 长椅(龟爷爷)+ 树木花草装饰
put(m.obs, 10, 8, G.benchL); put(m.obs, 11, 8, G.benchR);
tree2x2(m, 1, 13); tree2x2(m, 20, 12);
put(m.obs, 8, 14, G.bush); put(m.obs, 12, 13, G.bush);
put(m.obs, 5, 9, G.rock); put(m.obs, 14, 14, G.stump);
spawn(m, 21, 11, 'default');
spawn(m, 22, 10, 'from_plaza');
door(m, 23, 10, 'plaza', 'from_lake');
npc(m, 12, 8, 'guiyeye'); // 长椅旁
npc(m, 6, 12, 'pig');
inter(m, 16, 11, 'picnic_mat');
return m;
}
// ================= 7. field 20×14 花田 =================
function buildField() {
var m = newMap(20, 14);
fill(m.ground, 0, 0, 20, 14, G.grass);
scatter(m, 33, [0.10, 0.18, 0.24, 0.32]);
var x, y;
// 土路横穿(西门进出)
for (x = 0; x <= 19; x++) put(m.ground, x, 7, G.dirt);
// 浇花点花丛(T2/T12 用,ground 装饰)
put(m.ground, 15, 9, G.flR); put(m.ground, 16, 9, G.flY); put(m.ground, 17, 9, G.flB);
put(m.ground, 15, 10, G.flY); put(m.ground, 16, 10, G.flR); put(m.ground, 17, 10, G.flB);
// 栅栏围边,西门留口
for (x = 0; x <= 19; x++) { put(m.obs, x, 0, G.fenceH); put(m.obs, x, 13, G.fenceH); }
for (y = 1; y <= 12; y++) { if (y !== 7) put(m.obs, 0, y, G.fenceV); put(m.obs, 19, y, G.fenceV); }
// 5 丛莓果(T6
var berries = [[4, 4], [9, 4], [14, 4], [6, 9], [12, 9]];
for (var b = 0; b < berries.length; b++) put(m.obs, berries[b][0], berries[b][1], G.berry);
// 树木装饰
tree2x2(m, 16, 1);
put(m.obs, 2, 11, G.bush); put(m.obs, 10, 11, G.bush); put(m.obs, 2, 2, G.rock);
spawn(m, 2, 7, 'default');
spawn(m, 1, 7, 'from_plaza');
door(m, 0, 7, 'plaza', 'from_field');
npc(m, 10, 7, 'chick');
inter(m, 4, 5, 'berry_1');
inter(m, 9, 5, 'berry_2');
inter(m, 14, 5, 'berry_3');
inter(m, 6, 10, 'berry_4');
inter(m, 12, 10, 'berry_5');
inter(m, 16, 10, 'water_point');
return m;
}
// ================= 8. well 14×10 古井空地 =================
function buildWell() {
var m = newMap(14, 10);
fill(m.ground, 0, 0, 14, 10, G.grass);
scatter(m, 45, [0.07, 0.13, 0.17, 0.19]);
var y;
// 土场 + 南门土路
fill(m.ground, 5, 3, 4, 4, G.dirt);
for (y = 7; y <= 9; y++) { put(m.ground, 6, y, G.dirt); put(m.ground, 7, y, G.dirt); }
put(m.ground, 3, 4, G.mushroom); put(m.ground, 10, 6, G.mushroom);
// 中央古井(C7
put(m.obs, 6, 4, G.wellTL); put(m.obs, 7, 4, G.wellTR);
put(m.obs, 6, 5, G.wellBL); put(m.obs, 7, 5, G.wellBR);
// 四周树木
tree2x2(m, 1, 1); tree2x2(m, 11, 1); tree2x2(m, 1, 7); tree2x2(m, 11, 7);
put(m.obs, 4, 2, G.bush); put(m.obs, 9, 2, G.bush);
put(m.obs, 4, 8, G.bush); put(m.obs, 9, 8, G.bush);
put(m.obs, 4, 5, G.rock); put(m.obs, 9, 5, G.rock);
spawn(m, 6, 8, 'default');
spawn(m, 7, 8, 'from_plaza');
door(m, 7, 9, 'plaza', 'from_well');
inter(m, 6, 6, 'ancient_well');
return m;
}
// ================= 9. fog 20×8 雾墙边界 =================
function buildFog() {
var m = newMap(20, 8);
fill(m.ground, 0, 0, 20, 8, G.grass);
scatter(m, 57, [0.05, 0.09, 0.20, 0.20]);
var x, y;
// 雾前深草带 + 北门土路
for (x = 0; x <= 19; x++) put(m.ground, x, 4, G.deepGrass);
for (y = 0; y <= 4; y++) { put(m.ground, 9, y, G.dirt); put(m.ground, 10, y, G.dirt); }
// 远端(南侧)雾墙铺满,进 obstacles(E3 入口)
for (y = 5; y <= 7; y++)
for (x = 0; x <= 19; x++)
put(m.obs, x, y, [G.fogA, G.fogB, G.fogC][(x + y) % 3]);
// 两侧树木
tree2x2(m, 1, 1); tree2x2(m, 17, 1);
put(m.obs, 4, 3, G.bush); put(m.obs, 15, 3, G.bush);
put(m.obs, 0, 3, G.bush); put(m.obs, 19, 3, G.bush);
put(m.obs, 6, 2, G.rock);
spawn(m, 10, 2, 'default');
spawn(m, 9, 2, 'from_plaza'); // 落点距门 >24px,防回弹
door(m, 10, 0, 'plaza', 'from_fog');
inter(m, 10, 4, 'fog_wall'); // 雾前可达格
return m;
}
// ================= 10. white 20×14 白色层(走廊 + 病房) =================
function buildWhite() {
var m = newMap(20, 14);
var x, y;
// 默认白墙铺底;上半 20×6 走廊 + 左下 10×8 病房刷白地板
fill(m.ground, 0, 0, 20, 14, G.wWall);
for (y = 1; y <= 5; y++)
for (x = 1; x <= 18; x++)
m.ground[y][x] = (x % 4 === 0 && y % 2 === 0) ? G.wFloor2 : G.wFloor;
for (y = 7; y <= 12; y++)
for (x = 1; x <= 8; x++)
m.ground[y][x] = ((x + y) % 3 === 0) ? G.wFloor2 : G.wFloor;
put(m.ground, 4, 6, G.wFloor); put(m.ground, 5, 6, G.wFloor); // 走廊↔病房通道格
// 墙体(obstacles):北墙(含墙板/天花板灯)、东西墙、南墙、右下实心墙块、病房北/东墙
for (x = 0; x <= 19; x++) put(m.obs, x, 0, G.wWall);
put(m.obs, 5, 0, G.wPanel); put(m.obs, 10, 0, G.wPanel); put(m.obs, 15, 0, G.wPanel);
put(m.obs, 3, 0, G.wLamp); put(m.obs, 8, 0, G.wLamp);
put(m.obs, 13, 0, G.wLamp); put(m.obs, 18, 0, G.wLamp);
for (y = 1; y <= 13; y++) { put(m.obs, 0, y, G.wWall); put(m.obs, 19, y, G.wWall); }
for (x = 1; x <= 9; x++) put(m.obs, x, 13, G.wWall);
fill(m.obs, 10, 6, 10, 8, G.wWall); // 右下 10×8 实心(房间之外)
for (x = 1; x <= 9; x++) if (x !== 4 && x !== 5) put(m.obs, x, 6, G.wWall);
for (y = 6; y <= 13; y++) put(m.obs, 9, y, G.wWall);
put(m.obs, 9, 8, G.wCur); put(m.obs, 9, 9, G.wCur); // 白窗帘挂在东墙上
// 病房家具:白床 + 白监护仪 + 白柜
put(m.obs, 2, 8, G.wBedTL); put(m.obs, 3, 8, G.wBedTR);
put(m.obs, 2, 9, G.wBedBL); put(m.obs, 3, 9, G.wBedBR);
put(m.obs, 4, 8, G.wMon);
put(m.obs, 7, 12, G.wCab);
spawn(m, 17, 3, 'default'); // 走廊一端
return m;
}
// ================= 序列化 =================
function csv(l, w, h) {
var s = '';
for (var y = 0; y < h; y++) {
var row = '';
for (var x = 0; x < w; x++) {
row += l[y][x];
if (x < w - 1) row += ',';
}
s += row;
if (y < h - 1) s += ',\n';
}
return s;
}
function tmx(m) {
var s = '<?xml version="1.0" encoding="UTF-8"?>\n';
s += '<map version="1.10" tiledversion="1.12.2" orientation="orthogonal" renderorder="right-down"' +
' width="' + m.w + '" height="' + m.h + '" tilewidth="16" tileheight="16" infinite="0"' +
' nextlayerid="4" nextobjectid="' + (m.objs.length + 1) + '">\n';
s += ' <tileset firstgid="1" source="tileset.tsx"/>\n';
s += ' <layer id="1" name="ground" width="' + m.w + '" height="' + m.h + '">\n';
s += ' <data encoding="csv">\n' + csv(m.ground, m.w, m.h) + '\n </data>\n </layer>\n';
s += ' <layer id="2" name="obstacles" width="' + m.w + '" height="' + m.h + '">\n';
s += ' <properties>\n <property name="collides" type="bool" value="true"/>\n </properties>\n';
s += ' <data encoding="csv">\n' + csv(m.obs, m.w, m.h) + '\n </data>\n </layer>\n';
s += ' <objectgroup id="3" name="objects">\n';
for (var i = 0; i < m.objs.length; i++) {
var o = m.objs[i];
s += ' <object id="' + (i + 1) + '" name="' + o.name + '" x="' + o.x + '" y="' + o.y + '">\n';
s += ' <properties>\n';
for (var p = 0; p < o.props.length; p++)
s += ' <property name="' + o.props[p][0] + '" value="' + o.props[p][1] + '"/>\n';
s += ' </properties>\n <point/>\n </object>\n';
}
s += ' </objectgroup>\n</map>\n';
return s;
}
function writeMap(name, m) {
var f = new TextFile(OUT + name + '.tmx', TextFile.WriteOnly);
f.write(tmx(m));
f.commit();
tiled.log('wrote ' + name + '.tmx (' + m.w + 'x' + m.h + ', ' + m.objs.length + ' objects)');
}
writeMap('house', buildHouse());
writeMap('plaza', buildPlaza());
writeMap('bakery', buildBakery());
writeMap('shop', buildShop());
writeMap('clinic', buildClinic());
writeMap('lake', buildLake());
writeMap('field', buildField());
writeMap('well', buildWell());
writeMap('fog', buildFog());
writeMap('white', buildWhite());
tiled.log('all 10 maps done');