99 lines
4.2 KiB
JavaScript
99 lines
4.2 KiB
JavaScript
import level01 from './level01.js';
|
|
import level02 from './level02.js';
|
|
import level03 from './level03.js';
|
|
import level04 from './level04.js';
|
|
import level05 from './level05.js';
|
|
import level06 from './level06.js';
|
|
import level07 from './level07.js';
|
|
import level08 from './level08.js';
|
|
import level09 from './level09.js';
|
|
import level10 from './level10.js';
|
|
import level11 from './level11.js';
|
|
import level12 from './level12.js';
|
|
import level13 from './level13.js';
|
|
import level14 from './level14.js';
|
|
import level15 from './level15.js';
|
|
import level16 from './level16.js';
|
|
import level17 from './level17.js';
|
|
import level18 from './level18.js';
|
|
import level19 from './level19.js';
|
|
import level20 from './level20.js';
|
|
|
|
// Campaigns group levels into themed "maps" for the level select screen.
|
|
// Each campaign gets its own background art (bgKey), menu theme music
|
|
// (musicKey), and in-level look (data/themes.js), so adding a new campaign
|
|
// is: create its levels, add a bg image + manifest entry, add an entry to
|
|
// THEMES, add a row here. Node positions are in 960x540 design units (NOT multiplied by
|
|
// WORLD_SCALE - the scene scales them), and the path is rendered as a line
|
|
// through them in order. `positions` may be omitted to auto-place the
|
|
// campaign's levels: a 2-lane circuit (top lane right->left, bottom lane
|
|
// left->right, finish flag bottom-right) that comfortably fits up to ~12
|
|
// levels (see positioning.js). Give explicit `positions` only when you want
|
|
// a custom layout - the auto-layout keeps every node in the open band of
|
|
// the background art (y roughly 268-412) and clear of the title plate and
|
|
// bottom chrome.
|
|
export const CAMPAIGNS = [
|
|
{
|
|
id: 'campaign01',
|
|
name: 'Evergreen Lake',
|
|
bgKey: 'campaign01_bg',
|
|
levels: [level01, level02, level03, level04, level05, level06, level07, level08, level09, level10],
|
|
},
|
|
{
|
|
id: 'campaign02',
|
|
name: 'Underprivileged Community',
|
|
bgKey: 'campaign02_bg',
|
|
// Menu music for this campaign's map in LevelSelect (util/music.js
|
|
// playMenuTrack); undefined = the main title theme.
|
|
musicKey: 'urban_trap_theme',
|
|
// Its old levels (level04-06) moved into campaign01 while it grew toward
|
|
// 10; now full at 10 (level11-level20). level12 is a real designed level
|
|
// (built via editor/levelBuilder.js's section pipeline, not hand-drawn in
|
|
// the browser editor - review/playtest before shipping); level13-level20
|
|
// are placeholder stubs (flat filler terrain, "Coming Soon" name/desc) to
|
|
// reserve their slots on the map - replace each in editor.html as it gets
|
|
// designed for real.
|
|
levels: [level11, level12, level13, level14, level15, level16, level17, level18, level19, level20],
|
|
// Custom layout (see positioning.js / the module comment above) so this
|
|
// campaign's map doesn't read as a reskin of campaign01's 2-lane loop: a
|
|
// 3-row serpentine (row1 left->right, row2 right->left, row3 left->right)
|
|
// instead of campaign01's top/bottom lane pair. Same 960x540 design-unit
|
|
// space; rows sit at y=220/320/420 (vs campaign01's 268/412 two-lane
|
|
// band) and x stays within 100-750 on every row so the flag's nudge past
|
|
// the last node (see LevelSelectScene._buildCampaign) lands in-bounds
|
|
// without needing to flip direction.
|
|
positions: [
|
|
{ x: 100, y: 220 }, // level11
|
|
{ x: 317, y: 220 }, // level12
|
|
{ x: 533, y: 220 }, // level13
|
|
{ x: 750, y: 220 }, // level14
|
|
{ x: 750, y: 320 }, // level15
|
|
{ x: 425, y: 320 }, // level16
|
|
{ x: 100, y: 320 }, // level17
|
|
{ x: 100, y: 420 }, // level18
|
|
{ x: 425, y: 420 }, // level19
|
|
{ x: 750, y: 420 }, // level20
|
|
],
|
|
},
|
|
];
|
|
|
|
export const LEVELS = CAMPAIGNS.flatMap((c) => c.levels);
|
|
|
|
export function getLevelById(id) {
|
|
return LEVELS.find((level) => level.id === id);
|
|
}
|
|
|
|
export function getCampaignById(id) {
|
|
return CAMPAIGNS.find((c) => c.id === id);
|
|
}
|
|
|
|
export function getCampaignOfLevel(levelId) {
|
|
return CAMPAIGNS.find((c) => c.levels.some((l) => l.id === levelId)) || null;
|
|
}
|
|
|
|
export function getNextLevelId(id) {
|
|
const index = LEVELS.findIndex((level) => level.id === id);
|
|
if (index === -1 || index === LEVELS.length - 1) return null;
|
|
return LEVELS[index + 1].id;
|
|
}
|