humus-old/common/traits/magnetic.trait.js
2019-10-07 06:29:40 -05:00

82 lines
1.8 KiB
JavaScript

import {compose, Property} from '@avocado/core';
import {StateProperty, Trait} from '@avocado/entity';
import {Rectangle, Vector} from '@avocado/math';
const decorate = compose(
StateProperty('attraction', {
track: true,
}),
);
export class Magnetic extends decorate(Trait) {
static defaultParams() {
return {
isAttractor: false,
};
}
static defaultState() {
return {
attraction: 0,
};
}
static type() {
return 'magnetic';
}
constructor(entity, params, state) {
super(entity, params, state);
}
get isAttracted() {
return !this.params.isAttractor;
}
get isAttractor() {
return !!this.params.isAttractor;
}
tick(elapsed) {
if (!this.params.isAttractor) {
return;
}
const attraction = this.entity.attraction;
if (0 === attraction) {
return;
}
const layer = this.entity.layer;
if (!layer) {
return;
}
const query = Rectangle.compose(
Vector.sub(this.entity.position, [32, 32]),
[64, 64],
);
const entities = layer.visibleEntities(query);
for (let i = 0; i < entities.length; ++i) {
const entity = entities[i];
if (!entity.is('magnetic') || !entity.isAttracted) {
continue;
}
if (!entity.is('positioned') || !entity.is('mobile')) {
continue;
}
const distance = Vector.distance(
this.entity.position,
entity.position,
);
if (distance > attraction) {
continue;
}
const difference = Vector.sub(this.entity.position, entity.position);
const unit = Vector.normalize(difference);
const rdiff = Math.max(0.4, 1 - (distance / attraction));
const magnitude = 100 * rdiff;
entity.applyMovement(Vector.scale(unit, magnitude));
}
}
}