feat: interactive throbber
This commit is contained in:
parent
0a1bfa0732
commit
98c3fa22ac
|
@ -1,18 +1,48 @@
|
|||
/* eslint-disable no-unused-vars */
|
||||
import {buildInvoke} from '@avocado/behavior';
|
||||
import {Rectangle, Vector} from '@avocado/math';
|
||||
import {Ticker} from '@avocado/timing';
|
||||
import {LfoResult, Ticker} from '@avocado/timing';
|
||||
import {Trait} from '@avocado/traits';
|
||||
|
||||
export default () => class Initiator extends Trait {
|
||||
|
||||
#ticker = new Ticker(0.25);
|
||||
#adjustmentThrobber;
|
||||
|
||||
#glowThrobber;
|
||||
|
||||
#ticker = new Ticker(0.125);
|
||||
|
||||
#target;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.#ticker.on('tick', this.determineTarget, this);
|
||||
if ('client' === process.env.SIDE) {
|
||||
this.#adjustmentThrobber = {brightness: 1.5};
|
||||
this.#adjustmentThrobber.lfo = new LfoResult(
|
||||
this.#adjustmentThrobber,
|
||||
{
|
||||
brightness: {
|
||||
frequency: 0.75,
|
||||
magnitude: 0.5,
|
||||
median: 1.5,
|
||||
modulators: ['Triangle', 'Sine'],
|
||||
},
|
||||
},
|
||||
);
|
||||
this.#glowThrobber = {outerStrength: 0.125};
|
||||
this.#glowThrobber.lfo = new LfoResult(
|
||||
this.#glowThrobber,
|
||||
{
|
||||
outerStrength: {
|
||||
frequency: 0.75,
|
||||
magnitude: 0.25,
|
||||
median: 0.125,
|
||||
modulators: ['Triangle', 'Sine'],
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static dependencies() {
|
||||
|
@ -23,23 +53,28 @@ export default () => class Initiator extends Trait {
|
|||
}
|
||||
|
||||
determineTarget() {
|
||||
const incident = Vector.add(
|
||||
this.entity.position,
|
||||
Vector.directionalProjection(this.entity.direction, [0, 8]),
|
||||
);
|
||||
const interactives = this.entity.list.queryEntities(
|
||||
Rectangle.centerOn(
|
||||
Vector.add(
|
||||
this.entity.position,
|
||||
Vector.directionalProjection(this.entity.direction, [0, 8]),
|
||||
),
|
||||
[16, 16],
|
||||
),
|
||||
Rectangle.centerOn(incident, [16, 16]),
|
||||
buildInvoke(['query', 'is'], ['Interactive']),
|
||||
);
|
||||
const oldTarget = this.#target;
|
||||
if (interactives.length > 0) {
|
||||
// TODO sort distance
|
||||
[this.#target] = interactives;
|
||||
[this.#target] = interactives
|
||||
.map((interactive) => [interactive.distanceFrom({position: incident}), interactive])
|
||||
.sort(([l], [r]) => (l < r ? -1 : 1))
|
||||
.map(([, interactive]) => interactive);
|
||||
}
|
||||
else {
|
||||
this.#target = undefined;
|
||||
}
|
||||
if (oldTarget !== this.#target) {
|
||||
this.targetChanged(oldTarget, this.#target);
|
||||
}
|
||||
}
|
||||
|
||||
hooks() {
|
||||
|
@ -58,8 +93,31 @@ export default () => class Initiator extends Trait {
|
|||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
targetChanged(oldTarget) {
|
||||
oldTarget?.container?.removeFilter('interactive', 'adjustment');
|
||||
oldTarget?.container?.removeFilter('interactive', 'glow');
|
||||
}
|
||||
|
||||
renderTick(elapsed) {
|
||||
this.tickAdjustment(elapsed);
|
||||
this.tickGlow(elapsed);
|
||||
}
|
||||
|
||||
tick(elapsed) {
|
||||
this.#ticker.tick(elapsed);
|
||||
}
|
||||
|
||||
tickAdjustment(elapsed) {
|
||||
const {brightness, lfo} = this.#adjustmentThrobber;
|
||||
lfo.tick(elapsed);
|
||||
this.#target?.container?.addFilter('interactive', 'adjustment', {brightness});
|
||||
}
|
||||
|
||||
tickGlow(elapsed) {
|
||||
const {outerStrength, lfo} = this.#glowThrobber;
|
||||
lfo.tick(elapsed);
|
||||
this.#target?.container?.addFilter('interactive', 'glow', {color: 0, outerStrength});
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -4,9 +4,14 @@ import {
|
|||
compile,
|
||||
Context,
|
||||
} from '@avocado/behavior';
|
||||
import {Trait} from '@avocado/traits';
|
||||
import {StateProperty, Trait} from '@avocado/traits';
|
||||
import {compose} from '@latus/core';
|
||||
|
||||
export default (latus) => class Interactive extends Trait {
|
||||
const decorate = compose(
|
||||
StateProperty('isInteractive'),
|
||||
);
|
||||
|
||||
export default (latus) => class Interactive extends decorate(Trait) {
|
||||
|
||||
#actions;
|
||||
|
||||
|
@ -16,6 +21,12 @@ export default (latus) => class Interactive extends Trait {
|
|||
};
|
||||
}
|
||||
|
||||
static defaultState() {
|
||||
return {
|
||||
isInteractive: true,
|
||||
};
|
||||
}
|
||||
|
||||
async load(json) {
|
||||
await super.load(json);
|
||||
this.#actions = new Actions(compile(this.params.actions, latus));
|
||||
|
@ -25,6 +36,9 @@ export default (latus) => class Interactive extends Trait {
|
|||
return {
|
||||
|
||||
interact: (initiator) => {
|
||||
if (!super.isInteractive) {
|
||||
return;
|
||||
}
|
||||
const context = new Context(
|
||||
{
|
||||
entity: this.entity,
|
||||
|
|
Loading…
Reference in New Issue
Block a user