Move to Kaplay

This commit is contained in:
MeowcaTheoRange 2024-06-01 01:31:08 -05:00
parent 5b2aa4dc8b
commit 30ac08e50f
7 changed files with 7184 additions and 127 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,114 +1,160 @@
import "./leaflet.js"; // window.L import kaplay from "./modules/kaplay.js";
const options = {
lang: "en_US",
offs: 0,
viewportPadding: 20,
boundsPadding: 0.1,
}
const defaultPolyStyling = {
color: "#000000",
opacity: 1,
fill: true,
fillOpacity: 0.25,
weight: 3
};
function moveBounds(polys, xoff = 0, yoff = xoff) { const map = document.querySelector("map");
return polys.map(([x, y]) => [y + yoff, x + xoff]);
}
// Get tile data class KaplayMap {
kp;
opts = {
minZoomLevel: 0,
maxZoomLevel: 3,
};
async function getTileData(floor) { #zoomLevel = 0;
let tileDataReq = await fetch(`/data/${options.lang}/map/${floor}`); #scaleTween = null;
let tileData;
if (tileDataReq.ok)
tileData = await tileDataReq.json();
return tileData.map((room) => startMousePos = null;
L.polygon(moveBounds(room.poly, options.offs), defaultPolyStyling) startCamPos = null;
prevCamPos = null;
moveVelocity = null;
moveFriction = 0.25;
moveDead = 1;
#moveTween = null;
constructor(kp, opts) {
this.kp = kp;
this.opts = {
...this.opts,
...opts,
};
// Zooming
this.kp.onScroll((delta) => {
const scrollDist = -delta.y / 120;
this.zoomTo(this.zoomLevel + scrollDist, this.kp.mousePos());
});
// Dragging
this.kp.onUpdate(() => {
const curCamPos = this.kp.camPos();
const camScale = 1 / this.kp.camScale().y;
// ||| Completely unintelligible to the average person |||
// vvv Sorry y'all xwx vvv
if (this.kp.isMousePressed()) {
this.startMousePos = this.kp.mousePos();
this.startCamPos = this.kp.camPos();
} else if (this.kp.isMouseReleased() && this.prevCamPos != null) {
this.moveVelocity = this.prevCamPos.sub(curCamPos).scale(1 / camScale);
}
if (this.kp.isMouseDown()) {
this.prevCamPos = this.kp.camPos();
this.kp.camPos(
this.startCamPos.sub(
this.kp.mousePos().sub(this.startMousePos).scale(camScale)
)
); );
} } else if (this.moveVelocity?.x != 0 && this.moveVelocity?.y != 0)
this.kp.camPos(curCamPos.sub(this.moveVelocity?.scale(camScale) ?? 0));
// Get floor data // ^^^ Completely unintelligible to the average person ^^^
// ||| Sorry y'all xwx |||
async function getFloorData() { if (this.moveVelocity == null) return;
let floorDataReq = await fetch(`/data/${options.lang}/map/`);
let floorData;
if (floorDataReq.ok)
floorData = await floorDataReq.json();
// Add to Leaflet if (
this.moveVelocity.x <= this.moveDead &&
this.moveVelocity.x >= -this.moveDead
)
this.moveVelocity.x = 0;
if (
this.moveVelocity.y <= this.moveDead &&
this.moveVelocity.y >= -this.moveDead
)
this.moveVelocity.y = 0;
const floors = await Promise.all(floorData.map(async (data) => { this.moveVelocity = this.moveVelocity.scale(1 - this.moveFriction);
const tileData = await getTileData(data.id); });
}
const floorPoly = L.polygon(moveBounds(data.poly, options.offs), defaultPolyStyling) get zoomLevel() {
return this.#zoomLevel;
}
return L.featureGroup([ set zoomLevel(newZoom) {
floorPoly, const cameraZoom = this.kp.camScale().y;
...tileData
]);
}));
return { let addLinear = newZoom;
layers: floorData,
floors: floors if (addLinear < this.opts.minZoomLevel) addLinear = this.opts.minZoomLevel;
if (addLinear > this.opts.maxZoomLevel) addLinear = this.opts.maxZoomLevel;
let linearToLog = Math.pow(2, addLinear);
this.#zoomLevel = addLinear;
if (this.#scaleTween != null) {
this.#scaleTween.finish();
}
this.#scaleTween = this.kp.tween(
cameraZoom,
linearToLog,
0.25,
this.kp.camScale,
this.kp.easings.easeOutQuad
);
this.#scaleTween.then(() => {
this.#scaleTween = null;
});
}
zoomTo(newZoom, position) {
const curCamPos = this.kp.camPos();
const camScale = 1 / this.kp.camScale().y;
const diff = this.kp.center().sub(position).scale(camScale);
this.zoomLevel = newZoom;
let newZoomLog = 1 / Math.pow(2, newZoom);
const newDiff = this.kp.center().sub(position).scale(newZoomLog);
if (newZoom < this.opts.minZoomLevel) return;
if (newZoom > this.opts.maxZoomLevel) return;
if (this.#moveTween != null) {
this.#moveTween.finish();
}
this.#moveTween = this.kp.tween(
curCamPos,
curCamPos.sub(diff).add(newDiff),
0.25,
this.kp.camPos,
this.kp.easings.easeOutQuad
);
this.#moveTween.then(() => {
this.#moveTween = null;
});
} }
} }
// Create map const kp = kaplay({
canvas: map,
focus: true,
loadingScreen: false,
crisp: false,
debug: false,
global: false,
maxFPS: 120,
background: "404040",
});
async function createMap() { const kaplaymap = new KaplayMap(kp, {});
const data = await getFloorData();
let map = L.map('leaflet-map', { const bean = kp.loadBean();
center: [0, 0],
zoom: 2,
crs: L.CRS.Simple
});
const mainLayer = L.tileLayer('', { kp.add([kp.sprite("bean"), kp.pos(kp.center())]);
maxZoom: 4,
minZoom: 1,
attribution: 'Test data'
}).addTo(map);
const floor = data.floors[0].addTo(map);
const layerBounds = floor.getBounds();
const blb = layerBounds.pad(options.boundsPadding);
map.setMaxBounds(blb);
map.fitBounds(layerBounds, { padding: [options.viewportPadding, options.viewportPadding] });
const entries = Object.fromEntries(data.floors.map((floor, i) => [
`${data.layers[i].name}`,
floor
]));
let layerControl = L.control.layers(entries).addTo(map);
return {
floors: data.floors,
map,
mainLayer
};
}
async function mainFunction() {
const { floors, map, mainLayer } = await createMap();
map.on('baselayerchange', ({ layer, name }) => {
const layerBounds = layer.getBounds();
const blb = layerBounds.pad(options.boundsPadding);
map.setMaxBounds(blb);
map.fitBounds(layerBounds, { padding: [options.viewportPadding, options.viewportPadding] });
});
}
mainFunction();

7
assets/styles/style.css Normal file
View file

@ -0,0 +1,7 @@
body, html {
margin: 0;
height: 100vh;
width: 100vw;
box-sizing: border-box;
overflow: hidden;
}

View file

@ -1,16 +0,0 @@
body, html {
margin: 0;
height: 100vh;
width: 100vw;
box-sizing: border-box;
overflow: hidden;
}
#leaflet-map {
background-color: #404040;
display: inline-block;
box-sizing: border-box;
height: 100%;
width: 100%;
}

View file

@ -8,17 +8,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" href="/assets/styles/style.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin=""
/>
<link
rel="stylesheet"
href="/assets/styles/styles.css"
/> />
</head> </head>
<body> <body>
<div id="leaflet-map"></div> <canvas id="map"></canvas>
<script src="/assets/scripts/script.js" type="module"></script> <script src="/assets/scripts/script.js" type="module"></script>
</body> </body>
</html> </html>

View file

@ -39,6 +39,37 @@ app.get('/data/:lang/events', async (req, res) => {
return res.send(merged); return res.send(merged);
}) })
app.get('/data/:lang/events/:layer', async (req, res) => {
// Get events
let eventsReq = await fetch(new URL("events/events.json", config.data_url));
let events;
if (eventsReq.ok)
events = await eventsReq.json();
else
return res.status(400).send("Bad Request");
// Get localization
let l10nReq = await fetch(new URL(`localization/${req.params.lang}.json`, config.data_url));
let l10n;
if (l10nReq.ok)
l10n = await l10nReq.json();
else
return res.status(404).send("Localization not found!");
const clippedEvents = events.filter((event) => event.where.layer == req.params.layer);
// Merge events and localization
const merged = events.map(event => {
const localizationKey = l10n.__events[event.id];
return {
...event,
...localizationKey
};
});
return res.send(merged);
})
app.get('/data/:lang/map', async (req, res) => { app.get('/data/:lang/map', async (req, res) => {
// Get layers // Get layers
let layersReq = await fetch(new URL("map/layers.json", config.data_url)); let layersReq = await fetch(new URL("map/layers.json", config.data_url));