rot-js
Version:
A roguelike toolkit in JavaScript
79 lines (78 loc) • 3.2 kB
JavaScript
import Canvas from "./canvas.js";
/**
* @class Tile backend
* @private
*/
export default class Tile extends Canvas {
constructor() {
super();
this._colorCanvas = document.createElement("canvas");
}
draw(data, clearBefore) {
let [x, y, ch, fg, bg] = data;
let tileWidth = this._options.tileWidth;
let tileHeight = this._options.tileHeight;
if (clearBefore) {
if (this._options.tileColorize) {
this._ctx.clearRect(x * tileWidth, y * tileHeight, tileWidth, tileHeight);
}
else {
this._ctx.fillStyle = bg;
this._ctx.fillRect(x * tileWidth, y * tileHeight, tileWidth, tileHeight);
}
}
if (!ch) {
return;
}
let chars = [].concat(ch);
let fgs = [].concat(fg);
let bgs = [].concat(bg);
for (let i = 0; i < chars.length; i++) {
let tile = this._options.tileMap[chars[i]];
if (!tile) {
throw new Error(`Char "${chars[i]}" not found in tileMap`);
}
if (this._options.tileColorize) { // apply colorization
let canvas = this._colorCanvas;
let context = canvas.getContext("2d");
context.globalCompositeOperation = "source-over";
context.clearRect(0, 0, tileWidth, tileHeight);
let fg = fgs[i];
let bg = bgs[i];
context.drawImage(this._options.tileSet, tile[0], tile[1], tileWidth, tileHeight, 0, 0, tileWidth, tileHeight);
if (fg != "transparent") {
context.fillStyle = fg;
context.globalCompositeOperation = "source-atop";
context.fillRect(0, 0, tileWidth, tileHeight);
}
if (bg != "transparent") {
context.fillStyle = bg;
context.globalCompositeOperation = "destination-over";
context.fillRect(0, 0, tileWidth, tileHeight);
}
this._ctx.drawImage(canvas, x * tileWidth, y * tileHeight, tileWidth, tileHeight);
}
else { // no colorizing, easy
this._ctx.drawImage(this._options.tileSet, tile[0], tile[1], tileWidth, tileHeight, x * tileWidth, y * tileHeight, tileWidth, tileHeight);
}
}
}
computeSize(availWidth, availHeight) {
let width = Math.floor(availWidth / this._options.tileWidth);
let height = Math.floor(availHeight / this._options.tileHeight);
return [width, height];
}
computeFontSize() {
throw new Error("Tile backend does not understand font size");
}
_normalizedEventToPosition(x, y) {
return [Math.floor(x / this._options.tileWidth), Math.floor(y / this._options.tileHeight)];
}
_updateSize() {
const opts = this._options;
this._ctx.canvas.width = opts.width * opts.tileWidth;
this._ctx.canvas.height = opts.height * opts.tileHeight;
this._colorCanvas.width = opts.tileWidth;
this._colorCanvas.height = opts.tileHeight;
}
}