125 lines
2.5 KiB
JavaScript
125 lines
2.5 KiB
JavaScript
import {Trait} from '@avocado/entity';
|
|
import {Vector} from '@avocado/math';
|
|
|
|
export default class Layered extends Trait {
|
|
|
|
static behaviorTypes() {
|
|
return {
|
|
layer: {
|
|
type: 'layer',
|
|
label: 'Layer',
|
|
},
|
|
removeFromLayer: {
|
|
type: 'void',
|
|
label: 'Remove from layer.',
|
|
},
|
|
setIntoLayer: {
|
|
type: 'void',
|
|
label: 'Set into layer $1.',
|
|
args: [
|
|
['layer', {
|
|
type: 'layer',
|
|
}],
|
|
],
|
|
},
|
|
};
|
|
}
|
|
|
|
static type() {
|
|
return 'layered';
|
|
}
|
|
|
|
constructor(entity, params, state) {
|
|
super(entity, params, state);
|
|
this.entity.layer = null;
|
|
this._tile = [0, 0];
|
|
this._tileOffset = [0, 0];
|
|
this.setCurrentTileFromLayer();
|
|
}
|
|
|
|
destroy() {
|
|
this.entity.removeFromLayer();
|
|
}
|
|
|
|
get tile() {
|
|
return this._tile;
|
|
}
|
|
|
|
get tileOffset() {
|
|
return this._tileOffset;
|
|
}
|
|
|
|
onLayerTilesetChanged() {
|
|
this.setCurrentTileFromLayer();
|
|
}
|
|
|
|
setCurrentTileFromLayer() {
|
|
const layer = this.entity.layer;
|
|
if (!layer) {
|
|
return;
|
|
}
|
|
if (!this.entity.is('positioned')) {
|
|
return;
|
|
}
|
|
const tileset = layer.tileset;
|
|
if (!tileset) {
|
|
return;
|
|
}
|
|
const oldTile = Vector.copy(this._tile);
|
|
this._tile = Vector.div(
|
|
this.entity.position,
|
|
tileset.tileSize,
|
|
);
|
|
if (!Vector.equals(oldTile, this._tile)) {
|
|
this.entity.emit('tileChanged', oldTile, this._tile);
|
|
}
|
|
const oldTileOffset = Vector.copy(this._tileOffset);
|
|
this._tileOffset = Vector.mod(
|
|
this.entity.position,
|
|
tileset.tileSize,
|
|
);
|
|
if (!Vector.equals(oldTileOffset, this._tileOffset)) {
|
|
this.entity.emit('tileOffsetChanged', oldTileOffset, this._tileOffset);
|
|
}
|
|
}
|
|
|
|
listeners() {
|
|
return {
|
|
|
|
positionChanged: () => {
|
|
this.setCurrentTileFromLayer();
|
|
},
|
|
|
|
traitAdded: () => {
|
|
this.setCurrentTileFromLayer();
|
|
},
|
|
|
|
}
|
|
}
|
|
|
|
methods() {
|
|
return {
|
|
|
|
removeFromLayer: () => {
|
|
const layer = this.entity.layer;
|
|
if (!layer) {
|
|
return;
|
|
}
|
|
layer.off('tilesetChanged', this.onLayerTilesetChanged);
|
|
this.entity.layer = null;
|
|
this.entity.emit('removedFromLayer', layer);
|
|
},
|
|
|
|
setIntoLayer: (layer) => {
|
|
this.entity.layer = layer;
|
|
layer.on('tilesetChanged', this.onLayerTilesetChanged, this);
|
|
this.setCurrentTileFromLayer();
|
|
this.entity.emit('addedToLayer');
|
|
},
|
|
|
|
};
|
|
}
|
|
|
|
}
|
|
|