Add the Johto and Kanto atlas to the Map tab
Checks / web (push) Failing after 17s
Private ROM checks / private-rom (push) Failing after 14m39s

The Map tab draws the region's Town Map from the ROM with the player's
landmark, the visited flypoints as Fly destinations and the landmarks
whose maps are ported. Kanto opens with the Fly map's Indigo Plateau
rule. Landmark positions and flypoints are compared with the pinned
PRET source.

Closes #36

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
samyandClaude Opus 5.5 committed 2026-10-03 20:34:29 +02:00
1 parent cdee576818
commit 29248172bd
13 files changed
+536 -30

No files matched your search

+62 -1
View File
@@ -1,4 +1,5 @@
import { drawTownMap } from "./game/rendering/town-map";
import { drawAtlas, drawTownMap } from "./game/rendering/town-map";
import type { AtlasRegion } from "./game/world/atlas";
import {
drawCardPic,
drawTrainerCardBadges,
@@ -1127,6 +1128,64 @@ function showPokedexTab() {
});
}
let atlasKey = "";
let atlasRegion: AtlasRegion | undefined;
/** The Map tab's region atlas, from the loaded game's live state. */
function showAtlas() {
if (tabs.active() !== "map") return;
const world = ready() ? runtime.world : undefined;
const panel = get("atlas");
panel.hidden = !world;
if (!world) {
atlasKey = "";
return;
}
const view = world.atlas(atlasRegion);
const key = JSON.stringify([view, world.avatar]);
if (key === atlasKey) return;
atlasKey = key;
const names = { johto: "Johto", kanto: "Kanto" } as const;
get("atlas-title").textContent = names[view.region];
get("atlas-regions").replaceChildren(
...(view.regions.length > 1 ? view.regions : []).map((region) => {
const button = document.createElement("button");
button.type = "button";
button.textContent = names[region];
button.setAttribute("aria-pressed", String(region === view.region));
button.addEventListener("click", () => {
atlasRegion = region;
showAtlas();
});
return button;
}),
);
const canvas = get<HTMLCanvasElement>("atlas-map");
drawAtlas(canvas, world, view);
const here = view.landmarks.find((landmark) => landmark.landmark === view.player);
canvas.setAttribute("aria-label", `${names[view.region]} map${here ? `, you are in ${here.name}` : ""}`);
get("atlas-here").textContent = here
? `You are in ${here.name}.`
: `You are outside ${names[view.region]}.`;
const items = (list: string[], empty: string) =>
(list.length ? list : [empty]).map((text) => {
const item = document.createElement("li");
item.textContent = text;
return item;
});
get("atlas-fly").replaceChildren(
...items(
view.landmarks.filter((landmark) => landmark.flypoint?.visited).map((landmark) => landmark.name),
"None yet",
),
);
get("atlas-open").replaceChildren(
...items(
view.landmarks.filter((landmark) => landmark.open).map((landmark) => landmark.name),
"None",
),
);
}
let optionsKey = "";
/** _Option's screen: each option with its setting, and the ▶ cursor. */
function showOptions(world: GameWorld) {
@@ -1512,6 +1571,7 @@ const tabs = bindTabs(
},
(id) => {
if (id === "pokedex") showPokedexTab();
if (id === "map") showAtlas();
},
);
@@ -1554,6 +1614,7 @@ function update() {
get<HTMLButtonElement>("dialogue-next").disabled =
busy || session.state !== "playing";
showPokedexTab();
showAtlas();
}
async function save() {