import {compose} from '@avocado/core'; import {hasGraphics, Image} from '@avocado/graphics'; import {Rectangle, Vector} from '@avocado/math'; import {Resource} from '@avocado/resource'; const decorate = compose( Vector.Mixin('tileSize', 'tileWidth', 'tileHeight', { default: [0, 0], }), ); export class Tileset extends decorate(Resource) { constructor() { super(); this._image = undefined; this.subimages = []; } destroy() { this.subimages.forEach((sprite) => { sprite.destroy(); }); this.subimages = []; } fromJSON(json) { let promise; if (json.tileSize) { this.tileSize = json.tileSize; } if (hasGraphics && json.imageUri) { promise = Image.load(json.imageUri).then((image) => { this.image = image; }); } return Promise.resolve(promise).then(() => { return this; }); } get image() { return this._image; } set image(image) { this._image = image this.recalculateSubimages(); } recalculateSubimages() { const image = this._image; const tileSize = this.tileSize; if (!image || Vector.isZero(tileSize)) { return; } this.destroy(); const grid = Vector.div(image.size, tileSize); const rectangle = Rectangle.compose([0, 0], tileSize); for (let j = 0; j < grid[1]; ++j) { for (let i = 0; i < grid[0]; ++i) { const subimage = image.subimage(rectangle); this.subimages.push(subimage); rectangle[0] += tileSize[0]; } rectangle[0] = 0; rectangle[1] += tileSize[1]; } } subimage(index) { return this.subimages[index]; } get tileSize() { return super.tileSize; } set tileSize(tileSize) { super.tileSize = tileSize; this.recalculateSubimages(); } toJSON() { return { tileSize: this.tileSize, imageUri: this.image.uri, } } }