sprites
This commit is contained in:
parent
6d2537e3e3
commit
0e8ece2dc0
23 changed files with 2030 additions and 395 deletions
79
js/assets.js
79
js/assets.js
|
|
@ -2,6 +2,83 @@
|
|||
const images = new Map();
|
||||
const imageBoundsCache = new WeakMap();
|
||||
const imageMetrics = new Map();
|
||||
|
||||
const scaledSpriteCache = new Map();
|
||||
const stainOverlayCache = new Map();
|
||||
|
||||
function trimCanvasCache(cache, limit = 420) {
|
||||
while (cache.size > limit) {
|
||||
const first = cache.keys().next().value;
|
||||
if (first === undefined) break;
|
||||
cache.delete(first);
|
||||
}
|
||||
}
|
||||
|
||||
function quantizedCanvasSize(v, step = 16) {
|
||||
return Math.max(1, Math.round(v / step) * step);
|
||||
}
|
||||
|
||||
const SPRITE_CACHE_SCALE = 2.0;
|
||||
|
||||
function getCachedSpriteCanvas(id, img, w, h) {
|
||||
if (!img || !w || !h) return img;
|
||||
const qw = quantizedCanvasSize(w, 16);
|
||||
const qh = quantizedCanvasSize(h, 16);
|
||||
const key = `${id}:${qw}x${qh}`;
|
||||
let canvas = scaledSpriteCache.get(key);
|
||||
if (canvas) return canvas;
|
||||
canvas = document.createElement("canvas");
|
||||
canvas.width = qw;
|
||||
canvas.height = qh;
|
||||
const c = canvas.getContext("2d");
|
||||
c.imageSmoothingEnabled = true;
|
||||
if ("imageSmoothingQuality" in c) c.imageSmoothingQuality = "high";
|
||||
c.clearRect(0, 0, qw, qh);
|
||||
c.drawImage(img, 0, 0, qw, qh);
|
||||
scaledSpriteCache.set(key, canvas);
|
||||
trimCanvasCache(scaledSpriteCache, 520);
|
||||
return canvas;
|
||||
}
|
||||
|
||||
function getCachedStainOverlayCanvas(id, img, w, h, stain = 0, seed = 0.5) {
|
||||
if (!img || stain <= 0.01 || !w || !h) return null;
|
||||
const qw = quantizedCanvasSize(w, 16);
|
||||
const qh = quantizedCanvasSize(h, 16);
|
||||
const bucket = Math.max(1, Math.min(8, Math.ceil(stain * 8)));
|
||||
const seedBucket = Math.round((seed || 0) * 16);
|
||||
const key = `${id}:${qw}x${qh}:s${bucket}:r${seedBucket}`;
|
||||
let canvas = stainOverlayCache.get(key);
|
||||
if (canvas) return canvas;
|
||||
canvas = document.createElement("canvas");
|
||||
canvas.width = qw;
|
||||
canvas.height = qh;
|
||||
const c = canvas.getContext("2d");
|
||||
c.imageSmoothingEnabled = true;
|
||||
if ("imageSmoothingQuality" in c) c.imageSmoothingQuality = "high";
|
||||
c.clearRect(0, 0, qw, qh);
|
||||
c.drawImage(img, 0, 0, qw, qh);
|
||||
c.globalCompositeOperation = "source-in";
|
||||
c.globalAlpha = 0.34 + bucket * 0.075;
|
||||
c.fillStyle = "rgba(28, 92, 22, 0.96)";
|
||||
const s = (seedBucket % 16) / 16;
|
||||
const spots = [
|
||||
[0.40 + s * 0.035, 0.82, 0.14, 0.040, -0.10],
|
||||
[0.59 - s * 0.030, 0.87, 0.15, 0.044, 0.12],
|
||||
[0.50, 0.91, 0.20, 0.036, 0.02],
|
||||
[0.48 + s * 0.020, 0.78, 0.10, 0.030, -0.18],
|
||||
];
|
||||
for (const [sx, sy, rw, rh, rot] of spots) {
|
||||
c.beginPath();
|
||||
c.ellipse(sx * qw, sy * qh, rw * qw, rh * qh, rot, 0, Math.PI * 2);
|
||||
c.fill();
|
||||
}
|
||||
c.globalAlpha = 1;
|
||||
c.globalCompositeOperation = "source-over";
|
||||
stainOverlayCache.set(key, canvas);
|
||||
trimCanvasCache(stainOverlayCache, 360);
|
||||
return canvas;
|
||||
}
|
||||
|
||||
function loadImages() {
|
||||
const assets = [...SPRITES, ...DECOR_ASSETS];
|
||||
let loaded = 0;
|
||||
|
|
@ -53,4 +130,4 @@ function getImageMetrics(idOrImg) {
|
|||
}
|
||||
|
||||
|
||||
window.TarinaiAssets = { images, imageBoundsCache, imageMetrics, loadImages, imageAlphaBounds, getImageMetrics };
|
||||
window.TarinaiAssets = { images, imageBoundsCache, imageMetrics, scaledSpriteCache, stainOverlayCache, loadImages, imageAlphaBounds, getImageMetrics, getCachedSpriteCanvas, getCachedStainOverlayCanvas };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue