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';
|
|
|
|
|
|
|
|
const decorate = compose(
|
|
|
|
Vector.Mixin('size', 'width', 'height', {
|
|
|
|
default: [0, 0],
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
|
|
|
|
class TilesBase {
|
|
|
|
|
2019-03-27 01:05:29 -05:00
|
|
|
constructor() {
|
|
|
|
this._sizeState = I.List();
|
|
|
|
this._state = I.Map();
|
|
|
|
}
|
|
|
|
|
|
|
|
acceptStateChange(change) {
|
|
|
|
if (change.size) {
|
|
|
|
this.size = change.size;
|
|
|
|
}
|
|
|
|
if (change.data) {
|
|
|
|
this.data = change.data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-25 19:03:34 -05:00
|
|
|
fromJSON(json) {
|
|
|
|
if (json.size) {
|
|
|
|
this.size = json.size;
|
|
|
|
}
|
|
|
|
if (json.data) {
|
|
|
|
this.data = json.data;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
get rectangle() {
|
|
|
|
return Rectangle.compose([0, 0], this.size);
|
|
|
|
}
|
|
|
|
|
2019-03-25 20:49:16 -05:00
|
|
|
setTileAt(x, y, tile) {
|
|
|
|
const index = y * this.width + x;
|
|
|
|
if (index < 0 || index >= this.data.length) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.data[index] = tile;
|
|
|
|
}
|
|
|
|
|
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[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) {
|
|
|
|
this._sizeState = this._sizeState.set(0, this.width);
|
|
|
|
this._sizeState = this._sizeState.set(1, this.height);
|
|
|
|
this._state = this._state.set('size', this._sizeState);
|
|
|
|
this._state = this._state.set('data', this.data);
|
|
|
|
}
|
|
|
|
|
2019-03-25 19:03:34 -05:00
|
|
|
tileAt(x, y) {
|
2019-03-25 20:49:57 -05:00
|
|
|
return this.data[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],
|
|
|
|
};
|
2019-03-25 19:03:34 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
export class Tiles extends decorate(TilesBase) {}
|