Files
wownerogue/html/js/render/atlas.js
T

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);