mirror of
https://github.com/Such-Software/wownerogue.git
synced 2026-10-18 06:41:27 +02:00
A browser-based roguelike synchronized with crypto block timing. A run is a race against the next block: reach the exit before the block lands, or the house wins. The same codebase runs the solo dungeon, the social Tavern, and operator-selected PvP and race rulesets, with separate free and paid leaderboards. Self-hostable under the MIT License. See README.md to run it, docs/ARCHITECTURE.md for the design, and docs/DEPLOY.md to operate an instance.
75 lines
2.9 KiB
JavaScript
75 lines
2.9 KiB
JavaScript
// TilesetAtlas: loads a tileset image and serves individual tiles to either a 2D canvas
|
|
// (TileRenderer) or PixiJS (FancyRenderer). Source-agnostic: any pack's sheet loads through it.
|
|
(function (root) {
|
|
'use strict';
|
|
|
|
function TilesetAtlas(url, opts) {
|
|
opts = opts || {};
|
|
this.url = url;
|
|
this.tile = opts.tile || 16;
|
|
this.spacing = opts.spacing != null ? opts.spacing : 1;
|
|
this.margin = opts.margin || 0;
|
|
this.ready = false;
|
|
this.cols = 0;
|
|
this.rows = 0;
|
|
this._cbs = [];
|
|
|
|
var self = this;
|
|
this.img = new Image();
|
|
this.img.onload = function () {
|
|
self.ready = true;
|
|
var stride = self.tile + self.spacing;
|
|
self.cols = Math.floor((self.img.width - self.margin + self.spacing) / stride);
|
|
self.rows = Math.floor((self.img.height - self.margin + self.spacing) / stride);
|
|
var cbs = self._cbs; self._cbs = [];
|
|
cbs.forEach(function (cb) { try { cb(self); } catch (_) { /* ignore */ } });
|
|
};
|
|
this.img.onerror = function () { self.ready = false; };
|
|
this.img.src = url;
|
|
}
|
|
|
|
TilesetAtlas.prototype.onReady = function (cb) {
|
|
if (this.ready) cb(this); else this._cbs.push(cb);
|
|
};
|
|
|
|
// Source pixel of tile (col,row).
|
|
TilesetAtlas.prototype.px = function (col, row) {
|
|
var stride = this.tile + this.spacing;
|
|
return { x: this.margin + col * stride, y: this.margin + row * stride };
|
|
};
|
|
|
|
// Canvas: draw tile (col,row) at (dx,dy) scaled to `size`. Returns false if not ready.
|
|
TilesetAtlas.prototype.draw = function (ctx, col, row, dx, dy, size) {
|
|
if (!this.ready) return false;
|
|
var p = this.px(col, row);
|
|
ctx.imageSmoothingEnabled = false;
|
|
ctx.drawImage(this.img, p.x, p.y, this.tile, this.tile, dx, dy, size, size);
|
|
return true;
|
|
};
|
|
|
|
// Canvas: draw by flat tile index (row-major across the tileset's columns).
|
|
TilesetAtlas.prototype.drawIndex = function (ctx, idx, dx, dy, size) {
|
|
if (idx < 0 || !this.ready) return false;
|
|
return this.draw(ctx, idx % this.cols, Math.floor(idx / this.cols), dx, dy, size);
|
|
};
|
|
|
|
// Pixi: a cached Texture for tile (col,row), sharing one BaseTexture (nearest-neighbour).
|
|
TilesetAtlas.prototype.texture = function (col, row) {
|
|
if (typeof PIXI === 'undefined' || !this.ready) return null;
|
|
if (!this._base) {
|
|
this._base = PIXI.BaseTexture.from(this.img);
|
|
this._base.scaleMode = PIXI.SCALE_MODES.NEAREST;
|
|
this._texCache = {};
|
|
}
|
|
var key = col + ',' + row;
|
|
if (!this._texCache[key]) {
|
|
var p = this.px(col, row);
|
|
this._texCache[key] = new PIXI.Texture(this._base, new PIXI.Rectangle(p.x, p.y, this.tile, this.tile));
|
|
}
|
|
return this._texCache[key];
|
|
};
|
|
|
|
root.RK = root.RK || {};
|
|
root.RK.TilesetAtlas = TilesetAtlas;
|
|
})(window);
|