Home Reference Source

src/tileset.js

import { Model } from './model';

/**
 * The class to use tileset image
 * @example
 * const image = loader.get('my-tileset'); // see Loader documentation
 * let tileset = new Tileset(0, 0, 32, 32, image);
 *
 * // render the first tile of tileset
 * tileset.render(1);
 */
export class Tileset extends Model {

    /**
     * @param {number} x
     * @param {number} y
     * @param {number} tileWidth
     * @param {number} tileHeight
     * @param {Image} image
     */
    constructor(x, y, tileWidth, tileHeight, image) {
        super(x, y, tileWidth, tileHeight);

        /** @type {number} */
        this.tileWidth = tileWidth;

        /** @type {number} */
        this.tileHeight = tileHeight;

        /** @type {Image} */
        this.image = image;

        /** @type {number} */
        this.columns = this.image.width / this.tileWidth;

        /** @type {number} */
        this.rows = this.image.height / this.tileHeight;

        /** @type {number} */
        this.tiles = this.columns * this.rows;
    }

    /**
     * Get tile x,y positions by id (exemple tile number 23)
     * @private
     * @param {number} id
     * @return {Object}
     * @property {number} x
     * @property {number} y
     */
    getTilePosition(id) {
        id = id > this.tiles ? this.tiles : id;

        const percent = (id * this.tileWidth) / this.image.width;
        let x = 0;
        let y = 0;

        if (Number.isInteger(percent)) {
            x = this.columns -1;
            y = percent - 1;
        } else {
            const unit = Math.trunc(percent);
            const decimal = percent - unit;

            x = Math.round(decimal * this.columns) - 1;
            y = Math.trunc((id * this.tileWidth) / this.image.width);
        }

        return { x: x < 0 ? this.columns : x, y};
    }

    /**
     * Render a tile
     * @param {number} id
     * @param {CanvasRenderingContext2D} [ctx=null]
     */
    renderTile(id, ctx = null) {
        ctx = ctx || this.parent.ctx;

        if (id > 0) {
            let tile = this.getTilePosition(id);

            ctx.save();
            ctx.drawImage(
                this.image,     // image
                tile.x * this.tileWidth,    // pos x
                tile.y * this.tileHeight,   // pos y
                this.tileWidth,     // frame width
                this.tileHeight,    // frame height
                this.x,         // destination x
                this.y,         // destination y
                this.width,     // destination frame width
                this.height     // destination frame height
            );
            ctx.restore();
        }
    }
}