648 lines
16 KiB
JavaScript
648 lines
16 KiB
JavaScript
/**
|
|
* Generate 10 Tiled-compatible JSON maps per PRD §10.
|
|
* Also writes .tmx for optional `tiled --export-map` round-trip.
|
|
*/
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
const outDir = path.join(__dirname, '../public/assets/maps');
|
|
const tmxDir = path.join(__dirname, '../mapsrc');
|
|
fs.mkdirSync(outDir, { recursive: true });
|
|
fs.mkdirSync(tmxDir, { recursive: true });
|
|
|
|
const TILE = 16;
|
|
|
|
const TILESET = {
|
|
firstgid: 1,
|
|
columns: 16,
|
|
image: '../tilesets/village.png',
|
|
imagewidth: 256,
|
|
imageheight: 128,
|
|
tilecount: 128,
|
|
tilewidth: 16,
|
|
tileheight: 16,
|
|
name: 'village',
|
|
margin: 0,
|
|
spacing: 0,
|
|
tiles: [
|
|
// collidable tiles
|
|
...[9, 10, 11, 12, 13, 14, 15, 19, 20, 21, 22, 24, 26, 29, 30, 35, 41, 46].map((id) => ({
|
|
id,
|
|
properties: [{ name: 'collides', type: 'bool', value: true }],
|
|
})),
|
|
],
|
|
};
|
|
|
|
function emptyGrid(w, h, fill = 0) {
|
|
return Array.from({ length: w * h }, () => fill);
|
|
}
|
|
|
|
function set(data, w, x, y, v) {
|
|
if (x < 0 || y < 0 || x >= w) return;
|
|
data[y * w + x] = v;
|
|
}
|
|
|
|
function fillRect(data, w, x0, y0, x1, y1, v) {
|
|
for (let y = y0; y <= y1; y++) {
|
|
for (let x = x0; x <= x1; x++) set(data, w, x, y, v);
|
|
}
|
|
}
|
|
|
|
function border(data, w, h, v) {
|
|
for (let x = 0; x < w; x++) {
|
|
set(data, w, x, 0, v);
|
|
set(data, w, x, h - 1, v);
|
|
}
|
|
for (let y = 0; y < h; y++) {
|
|
set(data, w, 0, y, v);
|
|
set(data, w, w - 1, y, v);
|
|
}
|
|
}
|
|
|
|
function makeMap(name, w, h, build) {
|
|
const ground = emptyGrid(w, h, 1); // grass gid 1 (tile index 0 is empty, firstgid=1 → tile 0 empty, tile1 grass)
|
|
// Our tileset: tile index in image 0 = empty transparent; index 1 = grass
|
|
// firstgid 1 means GID 1 = tile index 0. Let's use firstgid 1 where GID N = image tile (N-1)
|
|
// Simpler: firstgid=1, and we store image-tile-index+1 as GID.
|
|
// grass is image tile 1 → GID 2
|
|
for (let i = 0; i < ground.length; i++) ground[i] = 2; // grass
|
|
|
|
const obstacles = emptyGrid(w, h, 0);
|
|
const objects = [];
|
|
|
|
const api = {
|
|
w,
|
|
h,
|
|
ground,
|
|
obstacles,
|
|
objects,
|
|
// GID 0 = empty; image tile index N → GID N+1. Passing 0 clears (no collision).
|
|
setG: (x, y, imgTile) => set(ground, w, x, y, imgTile <= 0 ? 0 : imgTile + 1),
|
|
setO: (x, y, imgTile) => set(obstacles, w, x, y, imgTile <= 0 ? 0 : imgTile + 1),
|
|
clearO: (x, y) => set(obstacles, w, x, y, 0),
|
|
fillG: (x0, y0, x1, y1, imgTile) =>
|
|
fillRect(ground, w, x0, y0, x1, y1, imgTile <= 0 ? 0 : imgTile + 1),
|
|
fillO: (x0, y0, x1, y1, imgTile) =>
|
|
fillRect(obstacles, w, x0, y0, x1, y1, imgTile <= 0 ? 0 : imgTile + 1),
|
|
borderO: (imgTile) => {
|
|
const gid = imgTile <= 0 ? 0 : imgTile + 1;
|
|
for (let x = 0; x < w; x++) {
|
|
set(obstacles, w, x, 0, gid);
|
|
set(obstacles, w, x, h - 1, gid);
|
|
}
|
|
for (let y = 0; y < h; y++) {
|
|
set(obstacles, w, 0, y, gid);
|
|
set(obstacles, w, w - 1, y, gid);
|
|
}
|
|
},
|
|
spawn: (x, y) => {
|
|
objects.push({
|
|
id: objects.length + 1,
|
|
name: 'spawn',
|
|
type: 'spawn',
|
|
x: x * TILE,
|
|
y: y * TILE,
|
|
width: TILE,
|
|
height: TILE,
|
|
});
|
|
},
|
|
npc: (name, x, y) => {
|
|
objects.push({
|
|
id: objects.length + 1,
|
|
name,
|
|
type: 'npc',
|
|
x: x * TILE,
|
|
y: y * TILE,
|
|
width: TILE,
|
|
height: TILE,
|
|
properties: [{ name: 'npcId', type: 'string', value: name }],
|
|
});
|
|
},
|
|
door: (name, x, y, target, targetSpawn) => {
|
|
// Door tiles must be walkable (clear obstacle collision)
|
|
set(obstacles, w, x, y, 0);
|
|
objects.push({
|
|
id: objects.length + 1,
|
|
name,
|
|
type: 'door',
|
|
x: x * TILE,
|
|
y: y * TILE,
|
|
width: TILE,
|
|
height: TILE,
|
|
properties: [
|
|
{ name: 'target', type: 'string', value: target },
|
|
{ name: 'spawn', type: 'string', value: targetSpawn || 'spawn' },
|
|
],
|
|
});
|
|
},
|
|
interact: (name, x, y, interactId) => {
|
|
objects.push({
|
|
id: objects.length + 1,
|
|
name,
|
|
type: 'interact',
|
|
x: x * TILE,
|
|
y: y * TILE,
|
|
width: TILE,
|
|
height: TILE,
|
|
properties: [{ name: 'interactId', type: 'string', value: interactId }],
|
|
});
|
|
},
|
|
};
|
|
|
|
build(api);
|
|
|
|
const map = {
|
|
compressionlevel: -1,
|
|
height: h,
|
|
width: w,
|
|
infinite: false,
|
|
layers: [
|
|
{
|
|
id: 1,
|
|
name: 'ground',
|
|
type: 'tilelayer',
|
|
width: w,
|
|
height: h,
|
|
data: ground,
|
|
opacity: 1,
|
|
visible: true,
|
|
x: 0,
|
|
y: 0,
|
|
},
|
|
{
|
|
id: 2,
|
|
name: 'obstacles',
|
|
type: 'tilelayer',
|
|
width: w,
|
|
height: h,
|
|
data: obstacles,
|
|
opacity: 1,
|
|
visible: true,
|
|
x: 0,
|
|
y: 0,
|
|
properties: [{ name: 'collides', type: 'bool', value: true }],
|
|
},
|
|
{
|
|
id: 3,
|
|
name: 'objects',
|
|
type: 'objectgroup',
|
|
objects,
|
|
opacity: 1,
|
|
visible: true,
|
|
x: 0,
|
|
y: 0,
|
|
},
|
|
],
|
|
nextlayerid: 4,
|
|
nextobjectid: objects.length + 1,
|
|
orientation: 'orthogonal',
|
|
renderorder: 'right-down',
|
|
tiledversion: '1.12.2',
|
|
tileheight: TILE,
|
|
tilewidth: TILE,
|
|
type: 'map',
|
|
version: '1.10',
|
|
tilesets: [
|
|
{
|
|
...TILESET,
|
|
// embed relative path for Phaser
|
|
},
|
|
],
|
|
};
|
|
|
|
const jsonPath = path.join(outDir, `${name}.json`);
|
|
fs.writeFileSync(jsonPath, JSON.stringify(map, null, 2));
|
|
console.log('wrote', jsonPath);
|
|
|
|
// Minimal TMX for Tiled CLI export verification
|
|
const tmx = `<?xml version="1.0" encoding="UTF-8"?>
|
|
<map version="1.10" tiledversion="1.12.2" orientation="orthogonal" renderorder="right-down" width="${w}" height="${h}" tilewidth="16" tileheight="16" infinite="0" nextlayerid="4" nextobjectid="${objects.length + 1}">
|
|
<tileset firstgid="1" source="village.tsx"/>
|
|
<layer id="1" name="ground" width="${w}" height="${h}">
|
|
<data encoding="csv">
|
|
${ground.join(',')}
|
|
</data>
|
|
</layer>
|
|
<layer id="2" name="obstacles" width="${w}" height="${h}">
|
|
<properties>
|
|
<property name="collides" type="bool" value="true"/>
|
|
</properties>
|
|
<data encoding="csv">
|
|
${obstacles.join(',')}
|
|
</data>
|
|
</layer>
|
|
<objectgroup id="3" name="objects">
|
|
${objects
|
|
.map(
|
|
(o) =>
|
|
` <object id="${o.id}" name="${o.name}" type="${o.type}" x="${o.x}" y="${o.y}" width="${o.width}" height="${o.height}"/>`,
|
|
)
|
|
.join('\n')}
|
|
</objectgroup>
|
|
</map>
|
|
`;
|
|
fs.writeFileSync(path.join(tmxDir, `${name}.tmx`), tmx);
|
|
return map;
|
|
}
|
|
|
|
// TSX tileset for Tiled
|
|
fs.writeFileSync(
|
|
path.join(tmxDir, 'village.tsx'),
|
|
`<?xml version="1.0" encoding="UTF-8"?>
|
|
<tileset version="1.10" tiledversion="1.12.2" name="village" tilewidth="16" tileheight="16" tilecount="128" columns="16">
|
|
<image source="../public/assets/tilesets/village.png" width="256" height="128"/>
|
|
</tileset>
|
|
`,
|
|
);
|
|
|
|
// --- Maps ---
|
|
|
|
// 1. House 12x8
|
|
makeMap('house', 12, 8, (m) => {
|
|
m.fillG(0, 0, 11, 7, 16); // wood floor
|
|
m.borderO(11);
|
|
m.setO(2, 2, 18); // bed
|
|
m.setO(3, 2, 18);
|
|
m.setO(9, 2, 28); // calendar
|
|
m.setO(5, 4, 22); // table
|
|
m.setO(1, 5, 23); // chair
|
|
// clear door at bottom
|
|
m.setO(5, 7, 0);
|
|
m.setO(6, 7, 0);
|
|
m.setG(5, 7, 17);
|
|
m.setG(6, 7, 17);
|
|
m.spawn(6, 5);
|
|
m.door('to_plaza', 5, 7, 'PlazaScene', 'from_house');
|
|
m.door('to_plaza2', 6, 7, 'PlazaScene', 'from_house');
|
|
m.interact('bed', 2, 2, 'bed');
|
|
m.interact('calendar', 9, 2, 'calendar');
|
|
});
|
|
|
|
// 2. Plaza 30x20 hub
|
|
makeMap('plaza', 30, 20, (m) => {
|
|
m.fillG(0, 0, 29, 19, 1);
|
|
// path cross
|
|
m.fillG(13, 0, 16, 19, 3);
|
|
m.fillG(0, 8, 29, 11, 3);
|
|
// flower beds
|
|
m.fillO(10, 6, 12, 7, 12 + 0); // use flower tile 7
|
|
m.setO(10, 6, 7);
|
|
m.setO(11, 6, 7);
|
|
m.setO(12, 6, 7);
|
|
m.setO(10, 7, 7);
|
|
m.setO(11, 7, 7);
|
|
m.setO(12, 7, 7);
|
|
// board
|
|
m.setO(15, 5, 29);
|
|
// tree + birds
|
|
m.setO(20, 4, 10);
|
|
m.setO(20, 5, 9);
|
|
m.setO(21, 4, 10);
|
|
// mailbox
|
|
m.setO(4, 10, 30);
|
|
// houses facades as doors targets
|
|
m.setO(5, 2, 13);
|
|
m.setO(6, 2, 13);
|
|
m.setO(5, 3, 12);
|
|
m.setO(6, 3, 14); // door visual
|
|
m.setO(22, 2, 13);
|
|
m.setO(23, 2, 13);
|
|
m.setO(22, 3, 12);
|
|
m.setO(23, 3, 14);
|
|
m.setO(8, 14, 13);
|
|
m.setO(9, 14, 13);
|
|
m.setO(8, 15, 12);
|
|
m.setO(9, 15, 14);
|
|
// walls edge soft
|
|
for (let x = 0; x < 30; x++) {
|
|
m.setO(x, 0, 35);
|
|
m.setO(x, 19, 35);
|
|
}
|
|
// openings
|
|
m.setO(14, 0, 0);
|
|
m.setO(15, 0, 0);
|
|
m.setO(14, 19, 0);
|
|
m.setO(15, 19, 0);
|
|
m.setO(0, 9, 0);
|
|
m.setO(0, 10, 0);
|
|
m.setO(29, 9, 0);
|
|
m.setO(29, 10, 0);
|
|
|
|
m.spawn(15, 12);
|
|
m.npc('afu', 15, 6);
|
|
m.npc('dabao', 5, 11);
|
|
m.npc('twinbirds', 20, 3);
|
|
m.npc('extra1', 18, 14);
|
|
m.npc('extra4', 10, 12);
|
|
|
|
m.door('from_house', 6, 4, 'HouseScene', 'spawn'); // visual marker only when entering - actual door below
|
|
// Fix: doors as interact targets
|
|
// Re-define doors properly
|
|
m.objects.length = m.objects.filter((o) => o.type !== 'door').length; // no, just add
|
|
});
|
|
|
|
// Fix plaza - rebuild cleanly
|
|
function rebuildPlaza() {
|
|
return makeMap('plaza', 30, 20, (m) => {
|
|
m.fillG(0, 0, 29, 19, 1);
|
|
m.fillG(13, 0, 16, 19, 3);
|
|
m.fillG(0, 8, 29, 11, 3);
|
|
// flower bed tiles
|
|
for (const [x, y] of [
|
|
[10, 6],
|
|
[11, 6],
|
|
[12, 6],
|
|
[10, 7],
|
|
[11, 7],
|
|
[12, 7],
|
|
]) {
|
|
m.setO(x, y, 7);
|
|
}
|
|
m.setO(15, 5, 29); // board
|
|
m.setO(20, 4, 10);
|
|
m.setO(20, 5, 9);
|
|
m.setO(4, 10, 30); // mailbox
|
|
// house doors on north
|
|
m.setO(5, 2, 13);
|
|
m.setO(6, 2, 13);
|
|
m.setO(5, 3, 12);
|
|
m.setO(6, 3, 14);
|
|
m.setO(22, 2, 13);
|
|
m.setO(23, 2, 13);
|
|
m.setO(22, 3, 12);
|
|
m.setO(23, 3, 14);
|
|
// clinic south-west
|
|
m.setO(3, 15, 12);
|
|
m.setO(4, 15, 14);
|
|
// bakery east-ish
|
|
m.setO(25, 8, 12);
|
|
m.setO(25, 9, 14);
|
|
// shop west
|
|
m.setO(2, 8, 12);
|
|
m.setO(2, 9, 14);
|
|
// ribbon posts
|
|
m.setO(12, 10, 33);
|
|
m.setO(17, 10, 33);
|
|
m.setO(12, 13, 33);
|
|
m.setO(17, 13, 33);
|
|
|
|
m.spawn(15, 12);
|
|
// named entry spawns as objects
|
|
m.objects.push({
|
|
id: 100,
|
|
name: 'from_house',
|
|
type: 'spawn',
|
|
x: 6 * 16,
|
|
y: 5 * 16,
|
|
width: 16,
|
|
height: 16,
|
|
});
|
|
m.objects.push({
|
|
id: 101,
|
|
name: 'from_bakery',
|
|
type: 'spawn',
|
|
x: 24 * 16,
|
|
y: 9 * 16,
|
|
width: 16,
|
|
height: 16,
|
|
});
|
|
m.objects.push({
|
|
id: 102,
|
|
name: 'from_shop',
|
|
type: 'spawn',
|
|
x: 3 * 16,
|
|
y: 9 * 16,
|
|
width: 16,
|
|
height: 16,
|
|
});
|
|
m.objects.push({
|
|
id: 103,
|
|
name: 'from_clinic',
|
|
type: 'spawn',
|
|
x: 4 * 16,
|
|
y: 14 * 16,
|
|
width: 16,
|
|
height: 16,
|
|
});
|
|
m.objects.push({
|
|
id: 104,
|
|
name: 'from_lake',
|
|
type: 'spawn',
|
|
x: 15 * 16,
|
|
y: 17 * 16,
|
|
width: 16,
|
|
height: 16,
|
|
});
|
|
m.objects.push({
|
|
id: 105,
|
|
name: 'from_field',
|
|
type: 'spawn',
|
|
x: 15 * 16,
|
|
y: 2 * 16,
|
|
width: 16,
|
|
height: 16,
|
|
});
|
|
m.objects.push({
|
|
id: 106,
|
|
name: 'from_well',
|
|
type: 'spawn',
|
|
x: 27 * 16,
|
|
y: 10 * 16,
|
|
width: 16,
|
|
height: 16,
|
|
});
|
|
m.objects.push({
|
|
id: 107,
|
|
name: 'from_fog',
|
|
type: 'spawn',
|
|
x: 2 * 16,
|
|
y: 16 * 16,
|
|
width: 16,
|
|
height: 16,
|
|
});
|
|
|
|
m.npc('afu', 15, 6);
|
|
m.npc('dabao', 5, 11);
|
|
m.npc('twinbirds', 20, 3);
|
|
m.npc('extra1', 18, 14);
|
|
m.npc('extra4', 10, 12);
|
|
|
|
m.door('house', 6, 3, 'HouseScene', 'spawn');
|
|
m.door('bakery', 25, 9, 'BakeryScene', 'spawn');
|
|
m.door('shop', 2, 9, 'ShopScene', 'spawn');
|
|
m.door('clinic', 4, 15, 'ClinicScene', 'spawn');
|
|
m.door('lake', 15, 19, 'LakeScene', 'spawn');
|
|
m.door('field', 15, 0, 'FieldScene', 'spawn');
|
|
m.door('well', 29, 10, 'WellScene', 'spawn');
|
|
m.door('fog', 0, 16, 'FogScene', 'spawn');
|
|
|
|
m.interact('board', 15, 5, 'board');
|
|
m.interact('flowers', 11, 6, 'flowers');
|
|
m.interact('mailbox', 4, 10, 'mailbox');
|
|
m.interact('ribbon1', 12, 10, 'ribbon');
|
|
m.interact('ribbon2', 17, 10, 'ribbon');
|
|
m.interact('ribbon3', 12, 13, 'ribbon');
|
|
m.interact('ribbon4', 17, 13, 'ribbon');
|
|
});
|
|
}
|
|
rebuildPlaza();
|
|
|
|
// 3. Bakery 15x10
|
|
makeMap('bakery', 15, 10, (m) => {
|
|
m.fillG(0, 0, 14, 9, 16);
|
|
m.borderO(12);
|
|
m.fillO(2, 2, 6, 3, 19); // counter
|
|
m.setO(12, 2, 20); // oven
|
|
m.setO(10, 2, 42); // recipe paper
|
|
m.setO(4, 6, 22);
|
|
m.setO(5, 7, 0);
|
|
m.setO(6, 9, 0);
|
|
m.setO(7, 9, 0);
|
|
m.spawn(7, 7);
|
|
m.npc('yuanyuan', 4, 4);
|
|
m.door('to_plaza', 7, 9, 'PlazaScene', 'from_bakery');
|
|
m.interact('recipe', 10, 2, 'recipe');
|
|
m.interact('counter', 4, 3, 'bread');
|
|
m.interact('knead', 3, 3, 'knead');
|
|
});
|
|
|
|
// 4. Shop 15x10
|
|
makeMap('shop', 15, 10, (m) => {
|
|
m.fillG(0, 0, 14, 9, 17);
|
|
m.borderO(12);
|
|
for (let x = 2; x <= 12; x++) {
|
|
m.setO(x, 2, 21);
|
|
m.setO(x, 4, 21);
|
|
}
|
|
m.setO(7, 9, 0);
|
|
m.setO(8, 9, 0);
|
|
m.spawn(7, 7);
|
|
m.npc('mimi', 7, 5);
|
|
m.door('to_plaza', 7, 9, 'PlazaScene', 'from_shop');
|
|
m.interact('shelf', 5, 2, 'shelf');
|
|
});
|
|
|
|
// 5. Clinic 12x8
|
|
makeMap('clinic', 12, 8, (m) => {
|
|
m.fillG(0, 0, 11, 7, 17);
|
|
m.borderO(12);
|
|
m.setO(3, 2, 22);
|
|
m.setO(4, 2, 43); // form
|
|
m.setO(8, 3, 18);
|
|
m.setO(5, 7, 0);
|
|
m.setO(6, 7, 0);
|
|
m.spawn(6, 5);
|
|
m.npc('fu', 3, 3);
|
|
m.door('to_plaza', 6, 7, 'PlazaScene', 'from_clinic');
|
|
m.interact('form', 4, 2, 'form');
|
|
});
|
|
|
|
// 6. Lake 24x16
|
|
makeMap('lake', 24, 16, (m) => {
|
|
m.fillG(0, 0, 23, 15, 1);
|
|
m.fillG(0, 8, 23, 15, 5); // water
|
|
m.fillG(0, 8, 23, 8, 6);
|
|
m.fillO(8, 4, 10, 5, 23); // bench area chairs
|
|
m.setO(9, 4, 23);
|
|
m.setO(12, 6, 31); // picnic
|
|
m.setO(13, 6, 31);
|
|
// path from north
|
|
m.fillG(11, 0, 12, 7, 3);
|
|
m.setO(11, 0, 0);
|
|
m.setO(12, 0, 0);
|
|
m.spawn(11, 2);
|
|
m.npc('gui', 9, 5);
|
|
m.npc('extra3', 18, 4);
|
|
m.door('to_plaza', 11, 0, 'PlazaScene', 'from_lake');
|
|
m.interact('picnic', 12, 6, 'picnic');
|
|
m.interact('bench', 9, 4, 'bench');
|
|
});
|
|
|
|
// 7. Field 20x14
|
|
makeMap('field', 20, 14, (m) => {
|
|
m.fillG(0, 0, 19, 13, 1);
|
|
m.fillG(9, 10, 10, 13, 3);
|
|
for (const [x, y] of [
|
|
[3, 3],
|
|
[5, 4],
|
|
[7, 3],
|
|
[12, 5],
|
|
[14, 3],
|
|
[4, 7],
|
|
[15, 7],
|
|
[8, 6],
|
|
]) {
|
|
m.setO(x, y, 8); // berry
|
|
}
|
|
m.setO(10, 2, 32); // pot
|
|
m.spawn(10, 11);
|
|
m.npc('extra2', 6, 8);
|
|
m.door('to_plaza', 10, 13, 'PlazaScene', 'from_field');
|
|
m.interact('berry1', 3, 3, 'berry');
|
|
m.interact('berry2', 5, 4, 'berry');
|
|
m.interact('berry3', 7, 3, 'berry');
|
|
m.interact('berry4', 12, 5, 'berry');
|
|
m.interact('berry5', 14, 3, 'berry');
|
|
m.interact('pot', 10, 2, 'pot');
|
|
});
|
|
|
|
// 8. Well 14x10
|
|
makeMap('well', 14, 10, (m) => {
|
|
m.fillG(0, 0, 13, 9, 1);
|
|
m.fillG(0, 4, 3, 5, 3);
|
|
m.setO(7, 4, 24); // well
|
|
m.setO(6, 4, 24);
|
|
m.setO(7, 5, 24);
|
|
m.setO(6, 5, 24);
|
|
m.spawn(2, 5);
|
|
m.npc('extra5', 10, 7);
|
|
m.door('to_plaza', 0, 5, 'PlazaScene', 'from_well');
|
|
m.interact('well', 7, 4, 'well');
|
|
});
|
|
|
|
// 9. Fog 20x8
|
|
makeMap('fog', 20, 8, (m) => {
|
|
m.fillG(0, 0, 19, 7, 1);
|
|
m.fillG(0, 3, 5, 4, 3);
|
|
for (let x = 12; x < 20; x++) {
|
|
for (let y = 0; y < 8; y++) m.setO(x, y, 25);
|
|
}
|
|
m.spawn(3, 4);
|
|
m.door('to_plaza', 0, 4, 'PlazaScene', 'from_fog');
|
|
m.interact('fogwall', 12, 4, 'fogwall');
|
|
});
|
|
|
|
// 10. White layer corridor 20x6 + ward via objects
|
|
makeMap('white', 20, 14, (m) => {
|
|
m.fillG(0, 0, 19, 13, 27);
|
|
m.fillO(0, 0, 19, 0, 26);
|
|
m.fillO(0, 5, 19, 5, 26);
|
|
m.fillO(0, 0, 0, 5, 26);
|
|
m.fillO(19, 0, 19, 5, 26);
|
|
// ward below
|
|
m.fillG(5, 6, 14, 13, 27);
|
|
m.fillO(5, 6, 14, 6, 26);
|
|
m.fillO(5, 13, 14, 13, 26);
|
|
m.fillO(5, 6, 5, 13, 26);
|
|
m.fillO(14, 6, 14, 13, 26);
|
|
m.setO(10, 5, 0); // opening
|
|
m.setO(9, 9, 18); // bed
|
|
m.setO(11, 8, 43);
|
|
m.spawn(2, 3);
|
|
m.interact('record', 11, 8, 'record');
|
|
m.door('to_ward', 10, 5, 'WhiteScene', 'ward');
|
|
m.objects.push({
|
|
id: 200,
|
|
name: 'ward',
|
|
type: 'spawn',
|
|
x: 10 * 16,
|
|
y: 8 * 16,
|
|
width: 16,
|
|
height: 16,
|
|
});
|
|
});
|
|
|
|
console.log('All 10 maps generated.');
|