avocado-old/packages/topdown/tiles.js

118 lines
2.5 KiB
JavaScript
Raw Normal View History

2019-03-27 01:05:29 -05:00
import * as I from 'immutable';
2019-03-25 19:03:34 -05:00
import {compose} from '@avocado/core';
import {Rectangle, Vector} from '@avocado/math';
import {EventEmitter} from '@avocado/mixins';
2019-03-25 19:03:34 -05:00
const decorate = compose(
EventEmitter,
2019-03-25 19:03:34 -05:00
Vector.Mixin('size', 'width', 'height', {
default: [0, 0],
}),
);
export class Tiles extends decorate(class {}) {
2019-03-25 19:03:34 -05:00
2019-03-27 01:05:29 -05:00
constructor() {
super();
this.data = I.List();
2019-03-27 01:05:29 -05:00
this._state = I.Map();
}
2019-04-05 15:16:55 -05:00
patchState(patch) {
if (patch.width) {
this.width = patch.width;
2019-03-27 22:27:58 -05:00
}
2019-04-05 15:16:55 -05:00
if (patch.height) {
this.height = patch.height;
2019-03-27 01:05:29 -05:00
}
2019-04-05 15:16:55 -05:00
if (patch.data) {
const oldData = this.data;
2019-04-05 15:16:55 -05:00
for (const i in patch.data) {
const index = parseInt(i);
2019-04-05 15:16:55 -05:00
this.data = this.data.set(index, patch.data[i]);
}
if (oldData !== this.data) {
this.emit('dataChanged');
}
2019-03-27 01:05:29 -05:00
}
}
2019-03-25 19:03:34 -05:00
fromJSON(json) {
if (json.size) {
this.size = json.size;
}
if (json.data) {
this.data = I.fromJS(json.data);
2019-03-25 19:03:34 -05:00
}
return this;
}
get rectangle() {
return Rectangle.compose([0, 0], this.size);
}
2019-03-25 20:49:16 -05:00
setTileAt(x, y, tile) {
const oldTile = this.tileAt(x, y);
if (oldTile === tile) {
return;
}
2019-03-25 20:49:16 -05:00
const index = y * this.width + x;
if (index < 0 || index >= this.data.size) {
2019-03-25 20:49:16 -05:00
return;
}
this.data = this.data.set(index, tile);
this.emit('dataChanged');
2019-03-25 20:49:16 -05:00
}
2019-03-25 19:03:34 -05:00
slice(rectangle) {
const tilesRectangle = this.rectangle;
2019-03-25 20:49:42 -05:00
// Get intersection.
2019-03-25 19:03:34 -05:00
if (!Rectangle.intersects(rectangle, tilesRectangle)) {
return [];
}
2019-03-25 20:49:42 -05:00
let [x, y, sliceWidth, sliceHeight] = Rectangle.intersection(
rectangle,
tilesRectangle,
);
// No muls in the loop.
let sliceRow = y * sliceWidth;
const dataWidth = this.width;
let dataRow = y * dataWidth;
// Copy slice.
const slice = new Array(sliceWidth * sliceHeight);
for (let j = 0; j < sliceHeight; ++j) {
for (let i = 0; i < sliceWidth; ++i) {
slice[sliceRow + x] = this.data.get(dataRow + x);
2019-03-25 19:03:34 -05:00
x++;
}
2019-03-25 20:49:42 -05:00
sliceRow += sliceWidth;
dataRow += dataWidth;
x -= sliceWidth;
2019-03-25 19:03:34 -05:00
}
return slice;
}
2019-03-27 01:05:29 -05:00
get state() {
return this._state;
}
tick(elapsed) {
2019-03-27 22:27:58 -05:00
this._state = this._state.set('width', this.width);
this._state = this._state.set('height', this.height);
2019-03-27 01:05:29 -05:00
this._state = this._state.set('data', this.data);
}
2019-03-25 19:03:34 -05:00
tileAt(x, y) {
return this.data.get(y * this.width + x);
2019-03-25 19:03:34 -05:00
}
toJSON() {
2019-03-25 20:50:11 -05:00
return {
size: [...this.size],
data: [...this.data.toJS()],
2019-03-25 20:50:11 -05:00
};
2019-03-25 19:03:34 -05:00
}
}