perf: private

This commit is contained in:
cha0s 2022-03-30 04:09:16 -05:00
parent 4d18c9223a
commit cf91c75630
40 changed files with 1439 additions and 1439 deletions

View File

@ -14,29 +14,29 @@ const STATIC_INTERVAL = 0.25;
export default (flecks) => class Behaved extends decorate(Trait) {
#accumulator = 0;
$$accumulator = 0;
#collectives = [];
$$collectives = [];
#context = {};
$$context = {};
#currentRoutine = '';
$$currentRoutine = '';
#daemons = {};
$$daemons = {};
#routines = {};
$$routines = {};
constructor() {
super();
({
currentRoutine: this.#currentRoutine,
currentRoutine: this.$$currentRoutine,
} = this.constructor.defaultState());
const {Script} = flecks.get('$avocado/resource.resources');
this.#context = Script.createContext();
this.$$context = Script.createContext();
}
get context() {
return this.#context;
return this.$$context;
}
static defaultParams() {
@ -58,9 +58,9 @@ export default (flecks) => class Behaved extends decorate(Trait) {
destroy() {
super.destroy();
this.#context = {};
this.#currentRoutine = undefined;
this.#routines = undefined;
this.$$context = {};
this.$$currentRoutine = undefined;
this.$$routines = undefined;
}
listeners() {
@ -89,15 +89,15 @@ export default (flecks) => class Behaved extends decorate(Trait) {
async load(json) {
await super.load(json);
const {Script} = flecks.get('$avocado/resource.resources');
this.#context = Script.createContext({
this.$$context = Script.createContext({
entity: this.entity,
});
const daemons = {
...this.entity.invokeHookReduced('daemons'),
...this.params.daemons,
};
this.#daemons = Object.values(await this.constructor.loadScripts(daemons, this.#context));
this.#routines = await this.constructor.loadScripts(this.params.routines, this.#context);
this.$$daemons = Object.values(await this.constructor.loadScripts(daemons, this.$$context));
this.$$routines = await this.constructor.loadScripts(this.params.routines, this.$$context);
this.updateCurrentRoutine(this.state.currentRoutine);
super.isBehaving = 'web' !== process.env.FLECKS_CORE_BUILD_TARGET;
}
@ -114,23 +114,23 @@ export default (flecks) => class Behaved extends decorate(Trait) {
tick(elapsed) {
if (this.entity.isBehaving) {
this.#accumulator += elapsed;
if (this.#accumulator >= STATIC_INTERVAL) {
for (let i = 0; i < this.#daemons.length; ++i) {
this.#daemons[i].tick(elapsed);
this.$$accumulator += elapsed;
if (this.$$accumulator >= STATIC_INTERVAL) {
for (let i = 0; i < this.$$daemons.length; ++i) {
this.$$daemons[i].tick(elapsed);
}
this.#accumulator -= STATIC_INTERVAL;
this.$$accumulator -= STATIC_INTERVAL;
}
if (this.#currentRoutine) {
this.#currentRoutine.tick(elapsed);
if (this.$$currentRoutine) {
this.$$currentRoutine.tick(elapsed);
}
}
}
updateCurrentRoutine(currentRoutine) {
this.#currentRoutine = this.#routines[currentRoutine];
if (this.#currentRoutine) {
this.#currentRoutine.reset();
this.$$currentRoutine = this.$$routines[currentRoutine];
if (this.$$currentRoutine) {
this.$$currentRoutine.reset();
}
super.currentRoutine = currentRoutine;
}

View File

@ -1,8 +1,8 @@
export default (Trait, flecks) => class DialogInitiator extends Trait {
#open = [];
$$open = [];
#dialogs = [];
$$dialogs = [];
acceptPacket(packet) {
if ('OpenDialog' === packet.constructor.type) {
@ -11,7 +11,7 @@ export default (Trait, flecks) => class DialogInitiator extends Trait {
}
cleanPackets() {
this.#dialogs = [];
this.$$dialogs = [];
}
hooks() {
@ -21,8 +21,8 @@ export default (Trait, flecks) => class DialogInitiator extends Trait {
acceptAction: ({action, value}) => {
acceptAction({action, value});
if ('Interact' === action && value) {
if (this.#open.length > 0) {
this.#open[0].skip();
if (this.$$open.length > 0) {
this.$$open[0].skip();
return false;
}
}
@ -65,17 +65,17 @@ export default (Trait, flecks) => class DialogInitiator extends Trait {
},
},
});
this.#open.push(dialog);
this.$$open.push(dialog);
dialog.once('destroying', () => {
const index = this.#open.indexOf(dialog);
const index = this.$$open.indexOf(dialog);
if (-1 !== index) {
this.#open.splice(index, 1);
this.$$open.splice(index, 1);
}
});
this.entity.list.addEntity(dialog);
}
else {
this.#dialogs.push({
this.$$dialogs.push({
text,
});
this.markAsDirty();
@ -88,7 +88,7 @@ export default (Trait, flecks) => class DialogInitiator extends Trait {
packetsFor(informed) {
return super.packetsFor(informed).concat(
informed === this.entity
? this.#dialogs.map((dialog) => ['OpenDialog', dialog])
? this.$$dialogs.map((dialog) => ['OpenDialog', dialog])
: [],
);
}

View File

@ -2,15 +2,15 @@ export default (flecks) => {
const {Trait} = flecks.fleck('@avocado/traits');
return class Dialog extends Trait {
#dialog;
$$dialog;
#letters = [];
$$letters = [];
#nextLetter = 0;
$$nextLetter = 0;
#thisLetter = 0;
$$thisLetter = 0;
#words = [];
$$words = [];
static defaultParams() {
return {
@ -41,14 +41,14 @@ export default (flecks) => {
const {text} = this.entity;
if (text) {
({
letters: this.#letters,
words: this.#words,
letters: this.$$letters,
words: this.$$words,
} = await flecks.get('$avocado/dialog.parser')(
`<rate frequency={${this.params.rate}}>${text}</rate>`,
));
if (this.#letters.length > 0) {
if (this.$$letters.length > 0) {
this.showThisLetter();
this.#words.forEach((word) => {
this.$$words.forEach((word) => {
// eslint-disable-next-line no-param-reassign
word.parentNode = this.entity.node;
});
@ -61,38 +61,38 @@ export default (flecks) => {
return {
skip: () => {
if (this.#nextLetter === Infinity) {
if (this.$$nextLetter === Infinity) {
this.entity.destroy();
return;
}
for (let i = 0; i < this.#letters.length; ++i) {
this.#letters[i].opacity = 1;
for (let i = 0; i < this.$$letters.length; ++i) {
this.$$letters[i].opacity = 1;
}
this.#nextLetter = Infinity;
this.$$nextLetter = Infinity;
},
};
}
showThisLetter() {
const letter = this.#letters[this.#thisLetter];
this.#nextLetter += letter.rate;
const letter = this.$$letters[this.$$thisLetter];
this.$$nextLetter += letter.rate;
letter.opacity = 1;
}
tick(elapsed) {
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
this.#nextLetter -= elapsed;
if (this.#nextLetter <= 0) {
this.#thisLetter += 1;
if (this.#thisLetter >= this.#letters.length) {
this.#nextLetter = Infinity;
this.$$nextLetter -= elapsed;
if (this.$$nextLetter <= 0) {
this.$$thisLetter += 1;
if (this.$$thisLetter >= this.$$letters.length) {
this.$$nextLetter = Infinity;
return;
}
this.showThisLetter();
}
for (let i = 0; i < this.#words.length; ++i) {
this.#words[i].tick(elapsed);
for (let i = 0; i < this.$$words.length; ++i) {
this.$$words[i].tick(elapsed);
}
}
}

View File

@ -10,17 +10,17 @@ export default (flecks) => {
);
return class EntityList extends decorate(JsonResource) {
#afterDestructionTickers = [];
$$afterDestructionTickers = [];
#entities = {};
$$entities = {};
#entityTickers = [];
$$entityTickers = [];
#flatEntities = [];
$$flatEntities = [];
#informedEntities = new Map();
$$informedEntities = new Map();
#quadTree = new QuadTree();
$$quadTree = new QuadTree();
async acceptPacket(packet) {
await super.acceptPacket(packet);
@ -38,13 +38,13 @@ export default (flecks) => {
async addEntity(entity) {
const uuid = entity.instanceUuid;
// Already exists?
if (this.#entities[uuid]) {
if (this.$$entities[uuid]) {
return;
}
this.#entities[uuid] = entity;
this.#flatEntities.push(entity);
this.$$entities[uuid] = entity;
this.$$flatEntities.push(entity);
if (entity.hasTickers()) {
this.#entityTickers.push(entity.tick);
this.$$entityTickers.push(entity.tick);
}
// eslint-disable-next-line no-param-reassign
entity.list = this;
@ -52,7 +52,7 @@ export default (flecks) => {
entity.once('destroying', () => this.onEntityDestroying(entity));
this.emit('entityAdded', entity);
if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
this.#informedEntities.set(entity, []);
this.$$informedEntities.set(entity, []);
}
this.startSynchronizing(entity);
}
@ -63,20 +63,20 @@ export default (flecks) => {
destroyEntities() {
const promises = [];
for (let i = 0; i < this.#flatEntities.length; i++) {
promises.push(this.#flatEntities[i].destroy());
this.#flatEntities[i]?.tick(Infinity);
for (let i = 0; i < this.$$flatEntities.length; i++) {
promises.push(this.$$flatEntities[i].destroy());
this.$$flatEntities[i]?.tick(Infinity);
}
return Promise.all(promises);
}
get entities() {
return this.#entities;
return this.$$entities;
}
findEntity(uuid) {
return uuid in this.#entities
? this.#entities[uuid]
return uuid in this.$$entities
? this.$$entities[uuid]
: undefined;
}
@ -100,7 +100,7 @@ export default (flecks) => {
const tickers = entity.invokeHookFlat('afterDestructionTickers');
for (let i = 0; i < tickers.length; i++) {
const ticker = tickers[i];
this.#afterDestructionTickers.push(ticker);
this.$$afterDestructionTickers.push(ticker);
}
}
@ -109,7 +109,7 @@ export default (flecks) => {
const {Entity} = flecks.get('$avocado/resource.resources');
// Visible entities.
const {areaToInform} = informed;
const previousVisibleEntities = this.#informedEntities.get(informed);
const previousVisibleEntities = this.$$informedEntities.get(informed);
const visibleEntities = this.visibleEntities(areaToInform);
for (let i = 0; i < visibleEntities.length; i++) {
const entity = visibleEntities[i];
@ -136,7 +136,7 @@ export default (flecks) => {
}
}
// Send updates.
this.#informedEntities.set(informed, visibleEntities);
this.$$informedEntities.set(informed, visibleEntities);
// Send destroys.
for (let i = 0; i < previousVisibleEntities.length; i++) {
const entity = previousVisibleEntities[i];
@ -149,33 +149,33 @@ export default (flecks) => {
}
get quadTree() {
return this.#quadTree;
return this.$$quadTree;
}
removeEntity(entity) {
const uuid = entity.instanceUuid;
if (!(uuid in this.#entities)) {
if (!(uuid in this.$$entities)) {
return;
}
this.stopSynchronizing(entity);
if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
this.#informedEntities.delete(entity);
this.$$informedEntities.delete(entity);
}
// eslint-disable-next-line no-param-reassign
entity.list = null;
entity.emit('removedFromList', this);
delete this.#entities[uuid];
this.#flatEntities.splice(this.#flatEntities.indexOf(entity), 1);
const index = this.#entityTickers.indexOf(entity.tick);
delete this.$$entities[uuid];
this.$$flatEntities.splice(this.$$flatEntities.indexOf(entity), 1);
const index = this.$$entityTickers.indexOf(entity.tick);
if (-1 !== index) {
this.#entityTickers.splice(index, 1);
this.$$entityTickers.splice(index, 1);
}
this.emit('entityRemoved', entity);
}
tick(elapsed) {
// Run after destruction tickers.
if (this.#afterDestructionTickers.length > 0) {
if (this.$$afterDestructionTickers.length > 0) {
this.tickAfterDestructionTickers(elapsed);
}
// Run normal tickers.
@ -184,30 +184,30 @@ export default (flecks) => {
tickAfterDestructionTickers(elapsed) {
const finishedTickers = [];
for (let i = 0; i < this.#afterDestructionTickers.length; ++i) {
const ticker = this.#afterDestructionTickers[i];
for (let i = 0; i < this.$$afterDestructionTickers.length; ++i) {
const ticker = this.$$afterDestructionTickers[i];
if (ticker(elapsed)) {
finishedTickers.push(ticker);
}
}
for (let i = 0; i < finishedTickers.length; ++i) {
const ticker = finishedTickers[i];
const index = this.#afterDestructionTickers.indexOf(ticker);
this.#afterDestructionTickers.splice(index, 1);
const index = this.$$afterDestructionTickers.indexOf(ticker);
this.$$afterDestructionTickers.splice(index, 1);
}
}
tickEntities(elapsed) {
for (let i = 0; i < this.#entityTickers.length; i++) {
this.#entityTickers[i](elapsed);
for (let i = 0; i < this.$$entityTickers.length; i++) {
this.$$entityTickers[i](elapsed);
}
}
toJSON() {
const {Entity} = flecks.get('$avocado/resource.resources');
const json = [];
for (let i = 0; i < this.#flatEntities.length; i++) {
const entity = this.#flatEntities[i];
for (let i = 0; i < this.$$flatEntities.length; i++) {
const entity = this.$$flatEntities[i];
json.push(Entity.withoutDefaults(entity.toJSON()));
}
return json;
@ -217,13 +217,13 @@ export default (flecks) => {
const {areaToInform} = informed;
const visibleEntities = this.visibleEntities(areaToInform);
// Mark as notified.
this.#informedEntities.set(informed, visibleEntities);
this.$$informedEntities.set(informed, visibleEntities);
return visibleEntities.map((entity) => entity.toNetwork(informed));
}
visibleEntities(query) {
const entities = [];
const quadTree = this.#quadTree;
const quadTree = this.$$quadTree;
const entries = Array.from(quadTree.query(query));
for (let i = 0; i < entries.length; i++) {
const [entity] = entries[i];

View File

@ -24,25 +24,25 @@ export default (flecks) => {
);
return class Entity extends decorate(JsonResource) {
#hooks = {};
$$hooks = {};
#isDestroying = false;
$$isDestroying = false;
#markedAsDirty = true;
$$markedAsDirty = true;
#originalJson;
$$originalJson;
#tickingPromisesTickers = [];
$$tickingPromisesTickers = [];
#traits = {};
$$traits = {};
#traitsFlat = [];
$$traitsFlat = [];
#traitTickers = [];
$$traitTickers = [];
#traitRenderTickers = [];
$$traitRenderTickers = [];
#traitsAcceptingPackets = [];
$$traitsAcceptingPackets = [];
constructor() {
super();
@ -66,11 +66,11 @@ export default (flecks) => {
addTickingPromise(tickingPromise) {
const ticker = tickingPromise.tick.bind(tickingPromise);
this.#tickingPromisesTickers.push(ticker);
this.$$tickingPromisesTickers.push(ticker);
return tickingPromise.then(() => {
const index = this.#tickingPromisesTickers.indexOf(ticker);
const index = this.$$tickingPromisesTickers.indexOf(ticker);
if (-1 !== index) {
this.#tickingPromisesTickers.splice(index, 1);
this.$$tickingPromisesTickers.splice(index, 1);
}
});
}
@ -83,11 +83,11 @@ export default (flecks) => {
return undefined;
}
if (this.is(type)) {
await this.#traits[type].load({
await this.$$traits[type].load({
entity: this,
...json,
});
this.emit('traitAdded', type, this.#traits[type]);
this.emit('traitAdded', type, this.$$traits[type]);
return undefined;
}
// Ensure dependencies.
@ -124,23 +124,23 @@ export default (flecks) => {
const hooks = Object.entries(trait.hooks());
for (let i = 0; i < hooks.length; i++) {
const [key, fn] = hooks[i];
this.#hooks[key] = this.#hooks[key] || [];
this.#hooks[key].push({
this.$$hooks[key] = this.$$hooks[key] || [];
this.$$hooks[key].push({
fn,
type,
});
}
// Track trait.
this.#traits[type] = trait;
this.#traitsFlat.push(trait);
this.$$traits[type] = trait;
this.$$traitsFlat.push(trait);
if ('tick' in trait) {
this.#traitTickers.push(trait.tick);
this.$$traitTickers.push(trait.tick);
}
if ('renderTick' in trait) {
this.#traitRenderTickers.push(trait.renderTick);
this.$$traitRenderTickers.push(trait.renderTick);
}
if ('acceptPacket' in trait) {
this.#traitsAcceptingPackets.push(trait);
this.$$traitsAcceptingPackets.push(trait);
}
this.startSynchronizing(trait);
this.emit('traitAdded', type, trait);
@ -179,13 +179,13 @@ export default (flecks) => {
}
cleanPackets() {
if (!this.#markedAsDirty) {
if (!this.$$markedAsDirty) {
return;
}
for (let i = 0; i < this.#traitsFlat.length; i++) {
this.#traitsFlat[i].cleanPackets();
for (let i = 0; i < this.$$traitsFlat.length; i++) {
this.$$traitsFlat[i].cleanPackets();
}
this.#markedAsDirty = false;
this.$$markedAsDirty = false;
}
// TODO: behavior decorator
@ -202,10 +202,10 @@ export default (flecks) => {
}
async destroy() {
if (this.#isDestroying) {
if (this.$$isDestroying) {
return;
}
this.#isDestroying = true;
this.$$isDestroying = true;
if (module.hot) {
hotEntities.delete(this);
}
@ -225,15 +225,15 @@ export default (flecks) => {
}
hasTickers() {
return this.#traitTickers.length;
return this.$$traitTickers.length;
}
invokeHook(hook, ...args) {
const results = {};
if (!(hook in this.#hooks)) {
if (!(hook in this.$$hooks)) {
return results;
}
const values = Object.values(this.#hooks[hook]);
const values = Object.values(this.$$hooks[hook]);
for (let i = 0; i < values.length; i++) {
const {fn, type} = values[i];
results[type] = fastApply(null, fn, args);
@ -251,26 +251,26 @@ export default (flecks) => {
}
is(type) {
return type in this.#traits;
return type in this.$$traits;
}
async load(json = {}) {
await super.load(json);
const {instanceUuid, traits = {}} = json;
if (!this.#originalJson) {
this.#originalJson = json;
if (!this.$$originalJson) {
this.$$originalJson = json;
}
this.instanceUuid = instanceUuid || this.numericUid;
await this.addTraits(traits);
}
markAsDirty() {
this.#markedAsDirty = true;
this.$$markedAsDirty = true;
}
packetsFor(informed) {
const packets = [];
const traits = Object.values(this.#traits);
const traits = Object.values(this.$$traits);
for (let i = 0; i < traits.length; i++) {
const trait = traits[i];
const traitPackets = trait.packetsFor(informed);
@ -291,8 +291,8 @@ export default (flecks) => {
}
renderTick(elapsed) {
for (let i = 0; i < this.#traitRenderTickers.length; i++) {
this.#traitRenderTickers[i](elapsed);
for (let i = 0; i < this.$$traitRenderTickers.length; i++) {
this.$$traitRenderTickers[i](elapsed);
}
}
@ -307,7 +307,7 @@ export default (flecks) => {
return;
}
// Destroy instance.
const instance = this.#traits[type];
const instance = this.$$traits[type];
this.stopSynchronizing(instance);
// Remove methods, hooks, and properties.
const methods = instance.methods();
@ -318,8 +318,8 @@ export default (flecks) => {
const hooks = Object.keys(instance.hooks());
for (let i = 0; i < hooks.length; i++) {
const hook = hooks[i];
const implementation = this.#hooks[hook].find(({type: hookType}) => hookType === type);
this.#hooks[hook].splice(this.#hooks[hook].indexOf(implementation), 1);
const implementation = this.$$hooks[hook].find(({type: hookType}) => hookType === type);
this.$$hooks[hook].splice(this.$$hooks[hook].indexOf(implementation), 1);
}
const {[type]: Trait} = flecks.get('$avocado/traits.traits');
const properties = enumerateTraitAccessorKeys(Trait.prototype);
@ -335,17 +335,17 @@ export default (flecks) => {
}
instance.destroy();
// Remove instance.
delete this.#traits[type];
this.#traitsFlat.splice(this.#traitsFlat.indexOf(instance), 1);
delete this.$$traits[type];
this.$$traitsFlat.splice(this.$$traitsFlat.indexOf(instance), 1);
if ('tick' in instance) {
this.#traitTickers.splice(this.#traitTickers.indexOf(instance.tick), 1);
this.$$traitTickers.splice(this.$$traitTickers.indexOf(instance.tick), 1);
}
if ('renderTick' in instance) {
this.#traitRenderTickers.splice(this.#traitRenderTickers.indexOf(instance.renderTick), 1);
this.$$traitRenderTickers.splice(this.$$traitRenderTickers.indexOf(instance.renderTick), 1);
}
const acceptPacketIndex = this.#traitsAcceptingPackets.indexOf(instance);
const acceptPacketIndex = this.$$traitsAcceptingPackets.indexOf(instance);
if (-1 !== acceptPacketIndex) {
this.#traitsAcceptingPackets.splice(acceptPacketIndex, 1);
this.$$traitsAcceptingPackets.splice(acceptPacketIndex, 1);
}
// Unloop.
instance.entity = undefined;
@ -362,11 +362,11 @@ export default (flecks) => {
tick(elapsed) {
this.elapsed = elapsed;
this.uptime += elapsed;
for (let i = 0; i < this.#traitTickers.length; i++) {
this.#traitTickers[i](elapsed);
for (let i = 0; i < this.$$traitTickers.length; i++) {
this.$$traitTickers[i](elapsed);
}
for (let i = 0; i < this.#tickingPromisesTickers.length; i++) {
this.#tickingPromisesTickers[i](elapsed);
for (let i = 0; i < this.$$tickingPromisesTickers.length; i++) {
this.$$tickingPromisesTickers[i](elapsed);
}
}
@ -375,12 +375,12 @@ export default (flecks) => {
if (this.uri) {
const pristine = {};
const json = {};
const traits = Object.entries(this.#traits);
const traits = Object.entries(this.$$traits);
for (let i = 0; i < traits.length; i++) {
const [type, trait] = traits[i];
pristine.traits = pristine.traits || {};
pristine.traits[type] = trait.constructor.withDefaults(
this.#originalJson ? this.#originalJson.traits[type] : {},
this.$$originalJson ? this.$$originalJson.traits[type] : {},
);
json.traits = json.traits || {};
json.traits[type] = trait.toJSON();
@ -392,7 +392,7 @@ export default (flecks) => {
}
else {
output = {};
const traits = Object.entries(this.#traits);
const traits = Object.entries(this.$$traits);
for (let i = 0; i < traits.length; i++) {
const [type, trait] = traits[i];
output.traits = {};
@ -409,11 +409,11 @@ export default (flecks) => {
const json = {
traits: {},
};
const traits = Object.entries(this.#traits);
const traits = Object.entries(this.$$traits);
for (let i = 0; i < traits.length; i++) {
const [type, trait] = traits[i];
pristine.traits[type] = trait.constructor.withDefaults(
this.#originalJson ? this.#originalJson.traits[type] : {},
this.$$originalJson ? this.$$originalJson.traits[type] : {},
);
json.traits[type] = trait.toNetwork(informed);
}
@ -432,15 +432,15 @@ export default (flecks) => {
}
trait(type) {
return this.#traits[type];
return this.$$traits[type];
}
get traits() {
return this.#traits;
return this.$$traits;
}
traitTypes() {
return Object.keys(this.#traits);
return Object.keys(this.$$traits);
}
static withDefaults(json = {}) {

View File

@ -13,13 +13,13 @@ const decorate = compose(
export default (flecks) => class Alive extends decorate(Trait) {
#deathCheck;
$$deathCheck;
#hasDied = false;
$$hasDied = false;
#isDying = false;
$$isDying = false;
#packets = [];
$$packets = [];
acceptPacket(packet) {
switch (packet.constructor.type) {
@ -36,7 +36,7 @@ export default (flecks) => class Alive extends decorate(Trait) {
cleanPackets() {
super.cleanPackets();
this.#packets = [];
this.$$packets = [];
}
static defaultParams() {
@ -80,14 +80,14 @@ export default (flecks) => class Alive extends decorate(Trait) {
}
},
));
this.#hasDied = true;
this.$$hasDied = true;
this.entity.destroy();
}
hooks() {
return {
destroy: () => () => (this.#isDying ? this.#hasDied : true),
destroy: () => () => (this.$$isDying ? this.$$hasDied : true),
};
}
@ -105,7 +105,7 @@ export default (flecks) => class Alive extends decorate(Trait) {
return {
startedDying: () => {
this.#packets.push(['Died']);
this.$$packets.push(['Died']);
},
tookHarm: (harm) => {
@ -118,7 +118,7 @@ export default (flecks) => class Alive extends decorate(Trait) {
async load(json) {
await super.load(json);
const {Script} = flecks.get('$avocado/resource.resources');
this.#deathCheck = await Script.load(this.params.deathCheck, this.entity.contextOrDefault);
this.$$deathCheck = await Script.load(this.params.deathCheck, this.entity.contextOrDefault);
}
get maxLife() {
@ -134,17 +134,17 @@ export default (flecks) => class Alive extends decorate(Trait) {
return {
die: () => {
if (!this.#isDying) {
this.#isDying = this.die();
if (!this.$$isDying) {
this.$$isDying = this.die();
}
return this.#isDying;
return this.$$isDying;
},
};
}
packetsFor() {
const packets = this.#packets.concat();
const packets = this.$$packets.concat();
const {life, maxLife} = this.stateDifferences();
if (life || maxLife) {
packets.push([
@ -160,8 +160,8 @@ export default (flecks) => class Alive extends decorate(Trait) {
tick() {
if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
if (!this.#isDying) {
this.#deathCheck.evaluate(({value: died}) => {
if (!this.$$isDying) {
this.$$deathCheck.evaluate(({value: died}) => {
if (died) {
this.entity.die();
}

View File

@ -16,7 +16,7 @@ const decorate = compose(
export default () => class DomNode extends decorate(Trait) {
#scheduledRuleApplication = true;
$$scheduledRuleApplication = true;
static defaultParams() {
return {
@ -51,31 +51,31 @@ export default () => class DomNode extends decorate(Trait) {
return {
opacityChanged: () => {
this.#scheduledRuleApplication = true;
this.$$scheduledRuleApplication = true;
},
positionChanged: () => {
this.#scheduledRuleApplication = true;
this.$$scheduledRuleApplication = true;
},
rotationChanged: () => {
this.#scheduledRuleApplication = true;
this.$$scheduledRuleApplication = true;
},
textChanged: () => {
this.#scheduledRuleApplication = true;
this.$$scheduledRuleApplication = true;
},
visibleScaleChanged: () => {
this.#scheduledRuleApplication = true;
this.$$scheduledRuleApplication = true;
},
domScaleXChanged: () => {
this.#scheduledRuleApplication = true;
this.$$scheduledRuleApplication = true;
},
domScaleYChanged: () => {
this.#scheduledRuleApplication = true;
this.$$scheduledRuleApplication = true;
},
parentNodeChanged: (oldParentNode, newParentNode) => {
@ -114,8 +114,8 @@ export default () => class DomNode extends decorate(Trait) {
}
tick() {
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET && this.#scheduledRuleApplication) {
this.#scheduledRuleApplication = false;
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET && this.$$scheduledRuleApplication) {
this.$$scheduledRuleApplication = false;
this.applyStyleRules();
}
}

View File

@ -2,12 +2,12 @@ import {Trait} from '@avocado/traits';
export default () => class DomText extends Trait {
#text;
$$text;
constructor() {
super();
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
this.#text = window.document.createElement('span');
this.$$text = window.document.createElement('span');
}
}
@ -48,30 +48,30 @@ export default () => class DomText extends Trait {
async load(json) {
await super.load(json);
if (!this.#text) {
if (!this.$$text) {
return;
}
const {text} = this.entity;
this.#text.innerText = text;
this.#text.style.position = 'relative';
this.$$text.innerText = text;
this.$$text.style.position = 'relative';
const {fontSize} = this.params;
if (fontSize) {
this.#text.style.fontSize = `${fontSize}px`;
this.$$text.style.fontSize = `${fontSize}px`;
if (this.params.centered) {
this.#text.style.left = `-${(fontSize / 2) * text.length}px`;
this.#text.style.top = `-${(fontSize / 2)}px`;
this.$$text.style.left = `-${(fontSize / 2) * text.length}px`;
this.$$text.style.top = `-${(fontSize / 2)}px`;
}
}
this.entity.node.appendChild(this.#text);
this.entity.node.appendChild(this.$$text);
}
onColorChanged() {
if (!this.#text) {
if (!this.$$text) {
return;
}
if (this.entity.is('Colorized')) {
const {red, green, blue} = this.entity;
this.#text.style.color = `rgb(${red}, ${green}, ${blue})`;
this.$$text.style.color = `rgb(${red}, ${green}, ${blue})`;
}
}

View File

@ -16,11 +16,11 @@ const decorate = compose(
export default () => class Mobile extends decorate(Trait) {
#appliedMovement = [0, 0];
$$appliedMovement = [0, 0];
#movement = [0, 0, 0, 0];
$$movement = [0, 0, 0, 0];
#rememberedActionMovement = [0, 0];
$$rememberedActionMovement = [0, 0];
acceptPacket(packet) {
switch (packet.constructor.type) {
@ -51,16 +51,16 @@ export default () => class Mobile extends decorate(Trait) {
acceptAction: ({action, value}) => {
switch (action) {
case 'MoveUp':
this.#movement[0] = value;
this.$$movement[0] = value;
break;
case 'MoveRight':
this.#movement[1] = value;
this.$$movement[1] = value;
break;
case 'MoveDown':
this.#movement[2] = value;
this.$$movement[2] = value;
break;
case 'MoveLeft':
this.#movement[3] = value;
this.$$movement[3] = value;
break;
default:
return;
@ -68,14 +68,14 @@ export default () => class Mobile extends decorate(Trait) {
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
return;
}
this.#rememberedActionMovement = [
this.#movement[1] - this.#movement[3],
this.#movement[2] - this.#movement[0],
this.$$rememberedActionMovement = [
this.$$movement[1] - this.$$movement[3],
this.$$movement[2] - this.$$movement[0],
];
if (!this.entity.isAcceptingInput) {
return;
}
this.setActionMovement(this.#rememberedActionMovement);
this.setActionMovement(this.$$rememberedActionMovement);
},
};
@ -83,18 +83,18 @@ export default () => class Mobile extends decorate(Trait) {
hotJSON() {
return {
appliedMovement: this.#appliedMovement,
movement: this.#movement,
appliedMovement: this.$$appliedMovement,
movement: this.$$movement,
};
}
async load(json) {
await super.load(json);
if (json.appliedMovement) {
this.#appliedMovement = json.appliedMovement;
this.$$appliedMovement = json.appliedMovement;
}
if (json.movement) {
this.#movement = json.movement;
this.$$movement = json.movement;
}
}
@ -106,7 +106,7 @@ export default () => class Mobile extends decorate(Trait) {
this.setActionMovement([0, 0]);
}
else {
this.setActionMovement(this.#rememberedActionMovement);
this.setActionMovement(this.$$rememberedActionMovement);
}
},
@ -117,7 +117,7 @@ export default () => class Mobile extends decorate(Trait) {
return {
applyMovement: (vector) => {
this.#appliedMovement = Vector.add(this.#appliedMovement, vector);
this.$$appliedMovement = Vector.add(this.$$appliedMovement, vector);
},
forceMovement: (movement) => {
@ -215,19 +215,19 @@ export default () => class Mobile extends decorate(Trait) {
if (this.entity.isMobile && !Vector.isZero(this.actionMovement)) {
this.entity.requestMovement(this.actionMovement);
}
if (Vector.isZero(this.#appliedMovement)) {
if (Vector.isZero(this.$$appliedMovement)) {
return;
}
if (this.entity.is('Physical')) {
this.entity.applyImpulse(this.#appliedMovement);
this.entity.applyImpulse(this.$$appliedMovement);
}
else {
this.entity.forceMovement(Vector.scale(
this.#appliedMovement,
this.$$appliedMovement,
elapsed,
));
}
this.#appliedMovement = [0, 0];
this.$$appliedMovement = [0, 0];
}
};

View File

@ -6,12 +6,12 @@ const decorate = compose(
export default () => class Perishable extends decorate(Trait) {
#ttl = 0;
$$ttl = 0;
constructor() {
super();
({
ttl: this.#ttl,
ttl: this.$$ttl,
} = this.constructor.defaultParams());
}
@ -23,12 +23,12 @@ export default () => class Perishable extends decorate(Trait) {
async load(json) {
await super.load(json);
this.#ttl = this.params.ttl;
this.$$ttl = this.params.ttl;
}
tick(elapsed) {
this.#ttl -= elapsed;
if (this.#ttl <= 0) {
this.$$ttl -= elapsed;
if (this.$$ttl <= 0) {
this.entity.destroy();
}
}

View File

@ -11,16 +11,16 @@ const decorate = compose(
export default (flecks) => class Spawner extends decorate(Trait) {
#children;
$$children;
#childrenListeners;
$$childrenListeners;
#spawnJSONs;
$$spawnJSONs;
constructor() {
super();
this.#children = [];
this.#childrenListeners = new Map();
this.$$children = [];
this.$$childrenListeners = new Map();
}
// eslint-disable-next-line class-methods-use-this
@ -121,8 +121,8 @@ export default (flecks) => class Spawner extends decorate(Trait) {
destroy() {
super.destroy();
while (this.#children.length > 0) {
const child = this.#children.pop();
while (this.$$children.length > 0) {
const child = this.$$children.pop();
if (child) {
this.removeChild(child);
}
@ -153,7 +153,7 @@ export default (flecks) => class Spawner extends decorate(Trait) {
}
maySpawn() {
if (this.maxSpawns > 0 && this.maxSpawns <= this.#children.length) {
if (this.maxSpawns > 0 && this.maxSpawns <= this.$$children.length) {
return false;
}
if (!this.destinationEntityList()) {
@ -168,7 +168,7 @@ export default (flecks) => class Spawner extends decorate(Trait) {
killAllChildren: () => {
// Juggle children since this may cause splices and mess up the array.
const promises = [];
const children = this.#children.slice(0);
const children = this.$$children.slice(0);
for (let i = 0; i < children.length; i++) {
const child = children[i];
promises.push(
@ -223,15 +223,15 @@ export default (flecks) => class Spawner extends decorate(Trait) {
return undefined;
}
// Add null to children to prevent race.
const childIndex = this.#children.length;
this.#children.push(null);
const childIndex = this.$$children.length;
this.$$children.push(null);
const list = this.destinationEntityList();
const {Entity} = flecks.get('$avocado/resource.resources');
const child = await Entity.load(json);
this.#children[childIndex] = child;
this.$$children[childIndex] = child;
// Listen for destroy event.
const listener = this.removeChild.bind(this, child);
this.#childrenListeners.set(child, listener);
this.$$childrenListeners.set(child, listener);
child.once('destroying', listener);
// Add child to list.
list.addEntity(child);
@ -266,12 +266,12 @@ export default (flecks) => class Spawner extends decorate(Trait) {
}
removeChild(child) {
const index = this.#children.indexOf(child);
const index = this.$$children.indexOf(child);
if (-1 !== index) {
this.#children.splice(index, 1);
const listener = this.#childrenListeners.get(child);
this.$$children.splice(index, 1);
const listener = this.$$childrenListeners.get(child);
child.off('destroying', listener);
this.#childrenListeners.delete(child);
this.$$childrenListeners.delete(child);
}
}

View File

@ -5,21 +5,21 @@ import Image from './image';
export default class Atlas extends JsonResource {
#image;
$$image;
#size = [0, 0];
$$size = [0, 0];
#subimages = [];
$$subimages = [];
destroy() {
this.#subimages.forEach((subimage) => {
this.$$subimages.forEach((subimage) => {
subimage.destroy();
});
this.#subimages = [];
this.$$subimages = [];
}
get image() {
return this.#image;
return this.$$image;
}
async load(json = {}) {
@ -29,19 +29,19 @@ export default class Atlas extends JsonResource {
if (!imageUri) {
return;
}
this.#image = await Image.load(imageUri);
this.$$image = await Image.load(imageUri);
switch (type) {
case 'grid': {
const {size} = json;
if (Vector.isNull(size)) {
return;
}
const grid = Vector.div(this.#image.size, size);
const grid = Vector.div(this.$$image.size, size);
const rectangle = Rectangle.compose([0, 0], size);
for (let j = 0; j < grid[1]; ++j) {
for (let i = 0; i < grid[0]; ++i) {
const subimage = this.#image.subimage(rectangle);
this.#subimages.push(subimage);
const subimage = this.$$image.subimage(rectangle);
this.$$subimages.push(subimage);
rectangle[0] += size[0];
}
rectangle[0] = 0;
@ -54,7 +54,7 @@ export default class Atlas extends JsonResource {
}
subimage(index) {
return this.#subimages[index];
return this.$$subimages[index];
}
}

View File

@ -7,7 +7,7 @@ import Renderable from './renderable';
export default class Container extends Renderable {
#filterMap = {};
$$filterMap = {};
constructor() {
super();
@ -91,10 +91,10 @@ export default class Container extends Renderable {
default:
}
if (filter) {
if (!this.#filterMap[id]) {
this.#filterMap[id] = {};
if (!this.$$filterMap[id]) {
this.$$filterMap[id] = {};
}
this.#filterMap[id][type] = filter;
this.$$filterMap[id][type] = filter;
if (!this.container.filters) {
this.container.filters = [];
}
@ -164,7 +164,7 @@ export default class Container extends Renderable {
return;
}
this.container.filters = [];
this.#filterMap = {};
this.$$filterMap = {};
}
removeChild(child) {
@ -188,13 +188,13 @@ export default class Container extends Renderable {
if (this.container.isFake) {
return;
}
if (this.#filterMap[id]?.[type]) {
if (this.$$filterMap[id]?.[type]) {
const {filters} = this.container;
const index = filters.indexOf(this.#filterMap[id][type]);
const index = filters.indexOf(this.$$filterMap[id][type]);
if (-1 !== index) {
filters.splice(index, 1);
}
delete this.#filterMap[id][type];
delete this.$$filterMap[id][type];
}
}

View File

@ -34,7 +34,7 @@ export default class Primitives extends Renderable {
drawCircle(position, radius, lineStyle, fillStyle) {
if (!this.primitives.isFake) {
this.#wrapStyle('drawCircle', '3rd', lineStyle, fillStyle, () => {
this.$$wrapStyle('drawCircle', '3rd', lineStyle, fillStyle, () => {
this.primitives.drawCircle(position[0], position[1], radius);
});
}
@ -42,7 +42,7 @@ export default class Primitives extends Renderable {
drawLine(p1, p2, lineStyle, fillStyle) {
if (!this.primitives.isFake) {
this.#wrapStyle('drawLine', '3rd', lineStyle, fillStyle, () => {
this.$$wrapStyle('drawLine', '3rd', lineStyle, fillStyle, () => {
this.primitives.moveTo(p1[0] + 0.5, p1[1] + 0.5);
this.primitives.lineTo(p2[0] + 0.5, p2[1] + 0.5);
});
@ -58,7 +58,7 @@ export default class Primitives extends Renderable {
];
const p1 = Vector.add(p, [0.5, 0.5]);
const p2 = Vector.add(p, Vector.sub(Vector.add(v, shift), sign));
this.#wrapStyle('drawLine', '3rd', lineStyle, fillStyle, () => {
this.$$wrapStyle('drawLine', '3rd', lineStyle, fillStyle, () => {
this.primitives.moveTo(p1[0], p1[1]);
this.primitives.lineTo(p2[0], p2[1]);
});
@ -71,14 +71,14 @@ export default class Primitives extends Renderable {
const [x, y] = vertices[i];
ps.push(x, y);
}
this.#wrapStyle('drawLine', '2nd', lineStyle, fillStyle, () => {
this.$$wrapStyle('drawLine', '2nd', lineStyle, fillStyle, () => {
this.primitives.drawPolygon(ps);
});
}
drawRectangle(rectangle, lineStyle, fillStyle) {
if (!this.primitives.isFake) {
this.#wrapStyle('drawLine', '2nd', lineStyle, fillStyle, () => {
this.$$wrapStyle('drawLine', '2nd', lineStyle, fillStyle, () => {
this.primitives.drawRect(
rectangle[0],
rectangle[1],
@ -93,7 +93,7 @@ export default class Primitives extends Renderable {
return this.primitives;
}
#wrapStyle(method, where, lineStyle, fillStyle, fn) {
$$wrapStyle(method, where, lineStyle, fillStyle, fn) {
if (!lineStyle) {
throw new TypeError(`Primitives::${method} expects lineStyle as ${where} parameter`);
}

View File

@ -16,17 +16,17 @@ export default (flecks) => {
return class Pictured extends decorate(Trait) {
#currentImage = '';
$$currentImage = '';
#images = {};
$$images = {};
#sprites = {};
$$sprites = {};
constructor() {
super();
this.$$cachedAabbs = {};
({
currentImage: this.#currentImage,
currentImage: this.$$currentImage,
} = this.constructor.defaultState());
}
@ -50,15 +50,15 @@ export default (flecks) => {
destroy() {
super.destroy();
if (this.#sprites) {
const sprites = Object.entries(this.#sprites);
if (this.$$sprites) {
const sprites = Object.entries(this.$$sprites);
for (let i = 0; i < sprites.length; i++) {
const [key, sprite] = sprites[i];
this.hideImage(key);
sprite.image.destroy();
sprite.destroy();
}
this.#sprites = undefined;
this.$$sprites = undefined;
}
}
@ -66,10 +66,10 @@ export default (flecks) => {
if (!this.entity.container) {
return;
}
if (!this.#sprites) {
if (!this.$$sprites) {
return;
}
const sprite = this.#sprites[key];
const sprite = this.$$sprites[key];
if (!sprite) {
return;
}
@ -80,14 +80,14 @@ export default (flecks) => {
return {
visibleAabbs: () => {
const key = this.#currentImage;
const key = this.$$currentImage;
if (this.$$cachedAabbs[key]) {
return this.$$cachedAabbs[key];
}
if (!this.#images[key]) {
if (!this.$$images[key]) {
return [0, 0, 0, 0];
}
const {size} = this.#images[key];
const {size} = this.$$images[key];
if (Vector.isZero(size)) {
return [0, 0, 0, 0];
}
@ -112,7 +112,7 @@ export default (flecks) => {
return {
currentImageChanged: (oldKey, currentImage) => {
this.#currentImage = currentImage;
this.$$currentImage = currentImage;
this.entity.scheduleBoundingBoxUpdate();
this.hideImage(oldKey);
this.showImage(currentImage);
@ -123,8 +123,8 @@ export default (flecks) => {
},
traitAdded: () => {
Object.keys(this.#sprites).forEach((key) => {
this[`${key === this.#currentImage ? 'show' : 'hide'}Image`](key);
Object.keys(this.$$sprites).forEach((key) => {
this[`${key === this.$$currentImage ? 'show' : 'hide'}Image`](key);
});
this.setSpriteScale();
this.entity.forceBoundingBoxUpdate();
@ -145,19 +145,19 @@ export default (flecks) => {
})
.filter(([, {uri}]) => !!uri),
);
this.#currentImage = this.state.currentImage;
this.#images = await mapValuesAsync(images, ({uri}) => Image.load(uri));
this.#sprites = await mapValuesAsync(this.#images, async (image) => new Sprite(image));
Object.keys(this.#sprites).forEach((key) => {
this.$$currentImage = this.state.currentImage;
this.$$images = await mapValuesAsync(images, ({uri}) => Image.load(uri));
this.$$sprites = await mapValuesAsync(this.$$images, async (image) => new Sprite(image));
Object.keys(this.$$sprites).forEach((key) => {
// eslint-disable-next-line no-param-reassign
this.#sprites[key].position = this.offsetFor(key);
this.$$sprites[key].position = this.offsetFor(key);
});
}
methods() {
return {
image: (key) => this.#sprites[key]?.image,
image: (key) => this.$$sprites[key]?.image,
};
}
@ -170,11 +170,11 @@ export default (flecks) => {
}
setSpriteScale() {
if (!this.#sprites) {
if (!this.$$sprites) {
return;
}
const {visibleScale} = this.entity;
const sprites = Object.values(this.#sprites);
const sprites = Object.values(this.$$sprites);
for (let i = 0; i < sprites.length; i++) {
sprites[i].scale = visibleScale;
}
@ -184,10 +184,10 @@ export default (flecks) => {
if (!this.entity.container) {
return;
}
if (!this.#sprites) {
if (!this.$$sprites) {
return;
}
const sprite = this.#sprites[key];
const sprite = this.$$sprites[key];
if (!sprite) {
return;
}

View File

@ -6,9 +6,9 @@ export default (flecks) => {
return class Primitive extends Trait {
#primitives;
$$primitives;
#scheduledDraw = true;
$$scheduledDraw = true;
static defaultParams() {
return {
@ -23,9 +23,9 @@ export default (flecks) => {
}
destroy() {
if (this.#primitives) {
this.#primitives.destroy();
this.#primitives = undefined;
if (this.$$primitives) {
this.$$primitives.destroy();
this.$$primitives = undefined;
}
}
@ -33,12 +33,12 @@ export default (flecks) => {
if (!this.entity.container) {
return;
}
if (this.#primitives) {
this.#primitives.clear();
if (this.$$primitives) {
this.$$primitives.clear();
}
else {
this.#primitives = new Primitives();
this.entity.addRasterChild(this.#primitives);
this.$$primitives = new Primitives();
this.entity.addRasterChild(this.$$primitives);
}
const colorization = this.entity.is('Colorized')
? {rgba: [this.entity.red, this.entity.green, this.entity.blue, 1]}
@ -57,7 +57,7 @@ export default (flecks) => {
rgba: [0, 0, 0, 0],
...colorization,
};
this.#primitives.drawCircle(
this.$$primitives.drawCircle(
primitive.position || [0, 0],
primitive.radius,
Primitives.lineStyle(new Color(...line.rgba), line.thickness),
@ -71,27 +71,27 @@ export default (flecks) => {
return {
blueChanged: () => {
this.#scheduledDraw = true;
this.$$scheduledDraw = true;
},
greenChanged: () => {
this.#scheduledDraw = true;
this.$$scheduledDraw = true;
},
redChanged: () => {
this.#scheduledDraw = true;
this.$$scheduledDraw = true;
},
traitAdded: () => {
this.#scheduledDraw = true;
this.$$scheduledDraw = true;
},
};
}
renderTick() {
if (this.#scheduledDraw) {
this.#scheduledDraw = false;
if (this.$$scheduledDraw) {
this.$$scheduledDraw = false;
this.drawPrimitives();
}
}

View File

@ -5,7 +5,7 @@ export default (flecks) => {
return class RasterText extends Trait {
#text;
$$text;
static defaultParams() {
return {
@ -22,18 +22,18 @@ export default (flecks) => {
destroy() {
super.destroy();
this.entity.removeRasterChild(this.#text);
this.entity.removeRasterChild(this.$$text);
}
loadText() {
if (!this.entity.container) {
return;
}
if (!this.#text) {
this.#text = new Text(this.entity.text, this.params.textStyle);
this.#text.zIndex = 1000;
if (!this.$$text) {
this.$$text = new Text(this.entity.text, this.params.textStyle);
this.$$text.zIndex = 1000;
}
this.entity.addRasterChild(this.#text);
this.entity.addRasterChild(this.$$text);
}
listeners() {

View File

@ -8,24 +8,24 @@ export default (flecks) => {
return class Rastered extends Trait {
#container;
$$container;
#parent;
$$parent;
#siblings = new Set();
$$siblings = new Set();
#usingAutoZIndex;
$$usingAutoZIndex;
constructor() {
super();
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
this.#container = new Container();
this.#container.on('parentChanged', this.onParentChanged, this);
this.$$container = new Container();
this.$$container.on('parentChanged', this.onParentChanged, this);
}
}
get container() {
return this.#container;
return this.$$container;
}
static defaultParams() {
@ -42,9 +42,9 @@ export default (flecks) => {
destroy() {
super.destroy();
if (this.#container) {
this.#container.off('parentChanged', this.onParentChanged);
this.#container.destroy();
if (this.$$container) {
this.$$container.off('parentChanged', this.onParentChanged);
this.$$container.destroy();
}
}
@ -52,10 +52,10 @@ export default (flecks) => {
return {
isVisibleChanged: () => {
if (!this.#container) {
if (!this.$$container) {
return;
}
this.#container.visible = this.entity.isVisible;
this.$$container.visible = this.entity.isVisible;
},
onYChanged: () => {
@ -63,22 +63,22 @@ export default (flecks) => {
},
opacityChanged: () => {
if (!this.#container) {
if (!this.$$container) {
return;
}
this.#container.alpha = this.entity.opacity;
this.$$container.alpha = this.entity.opacity;
},
rotationChanged: () => {
if (!this.#container) {
if (!this.$$container) {
return;
}
this.#container.rotation = this.entity.rotation;
this.$$container.rotation = this.entity.rotation;
},
visibleScaleChanged: () => {
if (this.#container) {
this.#container.scale = this.entity.visibleScale;
if (this.$$container) {
this.$$container.scale = this.entity.visibleScale;
}
},
@ -92,18 +92,18 @@ export default (flecks) => {
async load(json) {
await super.load(json);
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
if (this.#container) {
this.#container.alpha = this.entity.opacity;
this.#container.rotation = this.entity.rotation;
this.#container.scale = this.entity.visibleScale;
if (this.$$container) {
this.$$container.alpha = this.entity.opacity;
this.$$container.rotation = this.entity.rotation;
this.$$container.scale = this.entity.visibleScale;
}
this.onZIndexChanged(this.entity.zIndex);
this.renderTick();
const {filter} = this.params;
if (filter) {
this.#container.setFilter(filter);
this.$$container.setFilter(filter);
}
this.#container.isVisible = this.state.isVisible;
this.$$container.isVisible = this.state.isVisible;
}
}
@ -115,10 +115,10 @@ export default (flecks) => {
},
addRasterSibling: (child) => {
if (this.#parent) {
this.#parent.addChild(child);
if (this.$$parent) {
this.$$parent.addChild(child);
}
this.#siblings.add(child);
this.$$siblings.add(child);
},
removeRasterChild: (child) => {
@ -126,39 +126,39 @@ export default (flecks) => {
},
removeRasterSibling: (child) => {
if (this.#parent) {
this.#parent.removeChild(child);
if (this.$$parent) {
this.$$parent.removeChild(child);
}
this.#siblings.remove(child);
this.$$siblings.remove(child);
},
};
}
onParentChanged(oldParent, newParent) {
const siblings = Array.from(this.#siblings);
const siblings = Array.from(this.$$siblings);
for (let i = 0; i < siblings.length; i++) {
oldParent?.removeChild(siblings[i]);
newParent?.addChild(siblings[i]);
}
if (newParent) {
this.#parent = newParent;
this.$$parent = newParent;
}
}
onYChanged() {
if (this.#usingAutoZIndex) {
this.#container.zIndex = this.entity.y;
if (this.$$usingAutoZIndex) {
this.$$container.zIndex = this.entity.y;
}
}
onZIndexChanged(zIndex) {
this.#usingAutoZIndex = AUTO_ZINDEX === zIndex;
if (!this.#container) {
this.$$usingAutoZIndex = AUTO_ZINDEX === zIndex;
if (!this.$$container) {
return;
}
if (!this.#usingAutoZIndex) {
this.#container.zIndex = zIndex;
if (!this.$$usingAutoZIndex) {
this.$$container.zIndex = zIndex;
}
else {
this.onYChanged();
@ -171,15 +171,15 @@ export default (flecks) => {
}
synchronizePosition() {
if (!this.#container) {
if (!this.$$container) {
return;
}
this.#container.position = this.entity.position;
this.$$container.position = this.entity.position;
}
synchronizeZIndex() {
if (this.#container && this.#usingAutoZIndex) {
this.#container.zIndex = this.entity.y;
if (this.$$container && this.$$usingAutoZIndex) {
this.$$container.zIndex = this.entity.y;
}
}

View File

@ -27,13 +27,13 @@ export default (flecks) => {
return class Visible extends decorate(Trait) {
#quadTreeAabb = [];
$$quadTreeAabb = [];
#rawVisibleAabb = [0, 0, 0, 0];
$$rawVisibleAabb = [0, 0, 0, 0];
#scheduledBoundingBoxUpdate = true;
$$scheduledBoundingBoxUpdate = true;
#usingAutoZIndex = true;
$$usingAutoZIndex = true;
acceptPacket(packet) {
if ('TraitUpdateVisible' === packet.constructor.type) {
@ -54,7 +54,7 @@ export default (flecks) => {
}
// Expand the AABB so we don't have to update it every single tick.
const expandedAabb = Rectangle.expand(aabb, [32, 32]);
this.#quadTreeAabb = expandedAabb;
this.$$quadTreeAabb = expandedAabb;
list.quadTree.add(this.entity, expandedAabb);
}
@ -83,7 +83,7 @@ export default (flecks) => {
// Collect all bounding boxes.
const visibleAabbs = this.entity.invokeHookFlat('visibleAabbs');
if (0 === visibleAabbs.length) {
this.#rawVisibleAabb = [0, 0, 0, 0];
this.$$rawVisibleAabb = [0, 0, 0, 0];
}
else {
let unifiedBoundingBox = [0, 0, 0, 0];
@ -94,10 +94,10 @@ export default (flecks) => {
visibleAabb,
);
}
this.#rawVisibleAabb = unifiedBoundingBox;
this.$$rawVisibleAabb = unifiedBoundingBox;
}
this.translateVisibleAabb();
this.#scheduledBoundingBoxUpdate = false;
this.$$scheduledBoundingBoxUpdate = false;
}
listeners() {
@ -134,7 +134,7 @@ export default (flecks) => {
},
scheduleBoundingBoxUpdate: () => {
this.#scheduledBoundingBoxUpdate = true;
this.$$scheduledBoundingBoxUpdate = true;
},
};
@ -164,18 +164,18 @@ export default (flecks) => {
return;
}
list.quadTree.remove(this.entity);
this.#quadTreeAabb = [];
this.$$quadTreeAabb = [];
}
tick() {
if (this.#scheduledBoundingBoxUpdate) {
if (this.$$scheduledBoundingBoxUpdate) {
this.forceBoundingBoxUpdate();
}
}
translateVisibleAabb() {
const visibleAabb = Rectangle.translated(
this.#rawVisibleAabb,
this.$$rawVisibleAabb,
this.entity.position,
);
/* eslint-disable prefer-destructuring */
@ -192,8 +192,8 @@ export default (flecks) => {
return;
}
if (
this.#quadTreeAabb.length > 0
&& Rectangle.isInside(this.#quadTreeAabb, this.entity.visibleAabb)
this.$$quadTreeAabb.length > 0
&& Rectangle.isInside(this.$$quadTreeAabb, this.entity.visibleAabb)
) {
return;
}

View File

@ -6,16 +6,16 @@ const decorate = compose(
export default class ActionRegistry extends decorate(Class) {
#listen = {
$$listen = {
joystick: {},
key: {},
button: {},
wheel: {},
};
#stream = [];
$$stream = [];
#transformers = {};
$$transformers = {};
constructor(actions) {
super();
@ -26,23 +26,23 @@ export default class ActionRegistry extends decorate(Class) {
for (let j = 0; j < candidates.length; ++j) {
const {index, type, ...rest} = candidates[j];
if ('joystick' === type) {
if (this.#listen[type][index]) {
this.#listen[type][index].push({action, ...rest});
if (this.$$listen[type][index]) {
this.$$listen[type][index].push({action, ...rest});
}
else {
this.#listen[type][index] = [{action, ...rest}];
this.$$listen[type][index] = [{action, ...rest}];
}
}
else {
this.#listen[type][index] = {action};
this.$$listen[type][index] = {action};
}
}
}
}
drain() {
const stream = this.#stream;
this.#stream = [];
const stream = this.$$stream;
this.$$stream = [];
return stream;
}
@ -69,21 +69,21 @@ export default class ActionRegistry extends decorate(Class) {
}
onInput(type, input, value, transforming) {
if (this.#listen[type][input]) {
if (this.$$listen[type][input]) {
if ('joystick' === type) {
for (let i = 0; i < this.#listen[type][input].length; i++) {
const {action, axis} = this.#listen[type][input][i];
for (let i = 0; i < this.$$listen[type][input].length; i++) {
const {action, axis} = this.$$listen[type][input][i];
if (
(axis > 0 && value > 0)
|| (axis < 0 && value < 0)
) {
this.#stream.push({
this.$$stream.push({
action,
value: this.transform(action, value * axis, 'joystick'),
});
}
else if (0 === value) {
this.#stream.push({
this.$$stream.push({
action,
value: this.transform(action, value, 'joystick'),
});
@ -91,8 +91,8 @@ export default class ActionRegistry extends decorate(Class) {
}
}
else {
const {action} = this.#listen[type][input];
this.#stream.push({
const {action} = this.$$listen[type][input];
this.$$stream.push({
action,
value: this.transform(action, value, transforming),
});
@ -121,7 +121,7 @@ export default class ActionRegistry extends decorate(Class) {
}
setTransformerFor(action, transformer) {
this.#transformers[action] = transformer;
this.$$transformers[action] = transformer;
}
stopListening() {
@ -138,7 +138,7 @@ export default class ActionRegistry extends decorate(Class) {
}
transform(action, value, transforming) {
return this.#transformers[action] ? this.#transformers[action](transforming, value) : value;
return this.$$transformers[action] ? this.$$transformers[action](transforming, value) : value;
}
}

View File

@ -12,12 +12,12 @@ const decorate = compose(
// Input handling.
export default () => class Controllable extends decorate(Trait) {
#actionRegistry;
$$actionRegistry;
#queued = [];
$$queued = [];
get actionRegistry() {
return this.#actionRegistry;
return this.$$actionRegistry;
}
static defaultParams() {
@ -40,7 +40,7 @@ export default () => class Controllable extends decorate(Trait) {
destroy() {
super.destroy();
this.#actionRegistry.stopListening();
this.$$actionRegistry.stopListening();
}
get inputActions() {
@ -49,7 +49,7 @@ export default () => class Controllable extends decorate(Trait) {
async load(json) {
await super.load(json);
this.#actionRegistry = new ActionRegistry(this.params.actions);
this.$$actionRegistry = new ActionRegistry(this.params.actions);
}
methods() {
@ -63,20 +63,20 @@ export default () => class Controllable extends decorate(Trait) {
.every((result) => false !== result)
) {
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
this.#queued.push(actionStream[i]);
this.$$queued.push(actionStream[i]);
}
}
}
},
drainInput: () => {
const drained = this.#queued;
this.#queued = [];
const drained = this.$$queued;
this.$$queued = [];
return drained;
},
listenForInput: (inputNormalizer) => {
this.#actionRegistry.listen(inputNormalizer);
this.$$actionRegistry.listen(inputNormalizer);
},
};
@ -84,7 +84,7 @@ export default () => class Controllable extends decorate(Trait) {
tick() {
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
const drained = this.#actionRegistry.drain();
const drained = this.$$actionRegistry.drain();
this.entity.acceptActionStream(drained);
}
}

View File

@ -5,21 +5,21 @@ import {Trait} from '@avocado/traits';
export default () => class Initiator extends Trait {
#adjustmentThrobber;
$$adjustmentThrobber;
#glowThrobber;
$$glowThrobber;
#ticker = new Ticker(1 / 20);
$$ticker = new Ticker(1 / 20);
#target;
$$target;
constructor() {
super();
this.#ticker.on('tick', this.determineTarget, this);
this.$$ticker.on('tick', this.determineTarget, this);
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
this.#adjustmentThrobber = {brightness: 1.5};
this.#adjustmentThrobber.lfo = new LfoResult(
this.#adjustmentThrobber,
this.$$adjustmentThrobber = {brightness: 1.5};
this.$$adjustmentThrobber.lfo = new LfoResult(
this.$$adjustmentThrobber,
{
brightness: {
frequency: 0.75,
@ -29,9 +29,9 @@ export default () => class Initiator extends Trait {
},
},
);
this.#glowThrobber = {outerStrength: 0.125};
this.#glowThrobber.lfo = new LfoResult(
this.#glowThrobber,
this.$$glowThrobber = {outerStrength: 0.125};
this.$$glowThrobber.lfo = new LfoResult(
this.$$glowThrobber,
{
outerStrength: {
frequency: 0.75,
@ -72,9 +72,9 @@ export default () => class Initiator extends Trait {
interactives.push(entities[i]);
}
}
const oldTarget = this.#target;
const oldTarget = this.$$target;
if (interactives.length > 0) {
[this.#target] = interactives
[this.$$target] = interactives
.filter((interactive) => Rectangle.isTouching(query, interactive.position))
.filter((interactive) => interactive.isInteractive)
.map((interactive) => [interactive.distanceFrom({position: incident}), interactive])
@ -82,10 +82,10 @@ export default () => class Initiator extends Trait {
.map(([, interactive]) => interactive);
}
else {
this.#target = undefined;
this.$$target = undefined;
}
if (oldTarget !== this.#target) {
this.targetChanged(oldTarget, this.#target);
if (oldTarget !== this.$$target) {
this.targetChanged(oldTarget, this.$$target);
}
}
@ -95,8 +95,8 @@ export default () => class Initiator extends Trait {
acceptAction: ({action, value}) => {
if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
if ('Interact' === action && value) {
if (this.#target) {
this.#target.interact(this.entity);
if (this.$$target) {
this.$$target.interact(this.entity);
}
}
}
@ -110,10 +110,10 @@ export default () => class Initiator extends Trait {
oldTarget?.container?.removeFilter('interactive', 'adjustment');
oldTarget?.container?.removeFilter('interactive', 'glow');
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
this.#adjustmentThrobber.lfo.properties.brightness.location = 0;
this.#adjustmentThrobber.lfo.tick(0);
this.#glowThrobber.lfo.properties.outerStrength.location = 0;
this.#glowThrobber.lfo.tick(0);
this.$$adjustmentThrobber.lfo.properties.brightness.location = 0;
this.$$adjustmentThrobber.lfo.tick(0);
this.$$glowThrobber.lfo.properties.outerStrength.location = 0;
this.$$glowThrobber.lfo.tick(0);
}
}
@ -123,19 +123,19 @@ export default () => class Initiator extends Trait {
}
tick(elapsed) {
this.#ticker.tick(elapsed);
this.$$ticker.tick(elapsed);
}
tickAdjustment(elapsed) {
const {brightness, lfo} = this.#adjustmentThrobber;
const {brightness, lfo} = this.$$adjustmentThrobber;
lfo.tick(elapsed);
this.#target?.container?.addFilter('interactive', 'adjustment', {brightness});
this.$$target?.container?.addFilter('interactive', 'adjustment', {brightness});
}
tickGlow(elapsed) {
const {outerStrength, lfo} = this.#glowThrobber;
const {outerStrength, lfo} = this.$$glowThrobber;
lfo.tick(elapsed);
this.#target?.container?.addFilter('interactive', 'glow', {color: 0, outerStrength});
this.$$target?.container?.addFilter('interactive', 'glow', {color: 0, outerStrength});
}
};

View File

@ -7,7 +7,7 @@ const decorate = compose(
export default (flecks) => class Interactive extends decorate(Trait) {
#actions;
$$actions;
acceptPacket(packet) {
if ('TraitInteractive' === packet.constructor.type) {

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
export default (EntityList) => class PhysicsEntityList extends EntityList {
#world;
$$world;
constructor() {
super();
@ -10,7 +10,7 @@ export default (EntityList) => class PhysicsEntityList extends EntityList {
onEntityAdded(entity) {
// eslint-disable-next-line no-param-reassign
entity.world = this.#world;
entity.world = this.$$world;
}
// eslint-disable-next-line class-methods-use-this
@ -27,7 +27,7 @@ export default (EntityList) => class PhysicsEntityList extends EntityList {
entity.world = world;
}
}
this.#world = world;
this.$$world = world;
}
};

View File

@ -6,11 +6,11 @@ import PolygonShape from '@avocado/physics/shape/polygon';
export default (Tiles) => class PhysicsTiles extends Tiles {
#bodies = [];
$$bodies = [];
#impassable = {};
$$impassable = {};
#world;
$$world;
constructor() {
super();
@ -18,27 +18,27 @@ export default (Tiles) => class PhysicsTiles extends Tiles {
}
addBodies() {
if (!this.#world) {
if (!this.$$world) {
return;
}
const hulls = this.indexHulls(this.#impassable);
const hulls = this.indexHulls(this.$$impassable);
for (let i = 0; i < hulls.length; ++i) {
const scaled = [];
for (let j = 0; j < hulls[i].length; ++j) {
scaled.push(Vector.mul(hulls[i][j], this.tileSize));
}
const [vertices, position] = Vertice.localize(scaled);
const body = this.#world.createBody(new PolygonShape({position, vertices}));
const body = this.$$world.createBody(new PolygonShape({position, vertices}));
body.static = true;
this.#bodies.push(body);
this.#world.addBody(body);
this.$$bodies.push(body);
this.$$world.addBody(body);
}
}
async load(json = {}) {
await super.load(json);
const {impassable = []} = json;
this.#impassable = new Set(impassable);
this.$$impassable = new Set(impassable);
}
onTilesUpdate() {
@ -47,17 +47,17 @@ export default (Tiles) => class PhysicsTiles extends Tiles {
}
removeBodies() {
if (this.#bodies.length > 0 && this.#world) {
for (let i = 0; i < this.#bodies.length; i++) {
this.#world.removeBody(this.#bodies[i]);
if (this.$$bodies.length > 0 && this.$$world) {
for (let i = 0; i < this.$$bodies.length; i++) {
this.$$world.removeBody(this.$$bodies[i]);
}
this.#bodies = [];
this.$$bodies = [];
}
}
set world(world) {
this.removeBodies();
this.#world = world;
this.$$world = world;
this.addBodies();
}

View File

@ -4,14 +4,14 @@ import Shape from './shape';
export default class PolygonShape extends Shape {
#cachedTranslatedVertices;
$$cachedTranslatedVertices;
#vertices;
$$vertices;
constructor(shape) {
super(shape);
this.#cachedTranslatedVertices = [];
this.#vertices = [];
this.$$cachedTranslatedVertices = [];
this.$$vertices = [];
this.on([
'parentOriginChanged',
'parentRotationChanged',
@ -40,13 +40,13 @@ export default class PolygonShape extends Shape {
}
get aabb() {
if (0 === this.#vertices.length) {
if (0 === this.$$vertices.length) {
return [0, 0, 0, 0];
}
const min = [Infinity, Infinity];
const max = [-Infinity, -Infinity];
for (let i = 0; i < this.#cachedTranslatedVertices.length; i++) {
const vertice = this.#cachedTranslatedVertices[i];
for (let i = 0; i < this.$$cachedTranslatedVertices.length; i++) {
const vertice = this.$$cachedTranslatedVertices[i];
min[0] = vertice[0] < min[0] ? vertice[0] : min[0];
min[1] = vertice[1] < min[1] ? vertice[1] : min[1];
max[0] = vertice[0] > max[0] ? vertice[0] : max[0];
@ -65,18 +65,18 @@ export default class PolygonShape extends Shape {
const rotation = this.rotation + parentRotation;
const parentScale = this.parent ? this.parent.scale : 1;
const scale = this.scale * parentScale;
this.#cachedTranslatedVertices = this.#vertices.map((vertice) => (
this.$$cachedTranslatedVertices = this.$$vertices.map((vertice) => (
Vertice.translate(vertice, origin, rotation, scale)
));
this.emit('aabbChanged');
}
get vertices() {
return this.#cachedTranslatedVertices;
return this.$$cachedTranslatedVertices;
}
set vertices(vertices) {
this.#vertices = [...vertices];
this.$$vertices = [...vertices];
this.emit('verticesChanged');
}

View File

@ -9,22 +9,22 @@ const decorate = compose(
export default (flecks) => class Collider extends decorate(Trait) {
#collidesWithGroups = [];
$$collidesWithGroups = [];
#collisionGroup = '';
$$collisionGroup = '';
#doesNotCollideWith = [];
$$doesNotCollideWith = [];
#isCollidingWith = [];
$$isCollidingWith = [];
#isSensor = false;
$$isSensor = false;
constructor() {
super();
({
collidesWithGroups: this.#collidesWithGroups,
collisionGroup: this.#collisionGroup,
isSensor: this.#isSensor,
collidesWithGroups: this.$$collidesWithGroups,
collisionGroup: this.$$collisionGroup,
isSensor: this.$$isSensor,
} = this.constructor.defaultParams());
}
@ -107,21 +107,21 @@ export default (flecks) => class Collider extends decorate(Trait) {
}
get collisionGroup() {
return this.#collisionGroup;
return this.$$collisionGroup;
}
get collidesWithGroups() {
return this.#collidesWithGroups;
return this.$$collidesWithGroups;
}
indexOfCollidingEntity(entity) {
return this.#isCollidingWith.findIndex(
return this.$$isCollidingWith.findIndex(
({entity: collisionEntity}) => entity === collisionEntity,
);
}
get isCollidingWith() {
return this.#isCollidingWith;
return this.$$isCollidingWith;
}
isCollidingWithEntity(entity) {
@ -129,7 +129,7 @@ export default (flecks) => class Collider extends decorate(Trait) {
}
get isSensor() {
return this.#isSensor;
return this.$$isSensor;
}
async load(json) {
@ -139,9 +139,9 @@ export default (flecks) => class Collider extends decorate(Trait) {
collisionGroup,
isSensor,
} = this.params;
this.#collidesWithGroups = collidesWithGroups;
this.#collisionGroup = collisionGroup;
this.#isSensor = isSensor;
this.$$collidesWithGroups = collidesWithGroups;
this.$$collisionGroup = collisionGroup;
this.$$isSensor = isSensor;
}
async pushCollisionTickingPromise(codeOrUri, other, incident) {
@ -154,11 +154,11 @@ export default (flecks) => class Collider extends decorate(Trait) {
}
releaseAllCollisions() {
for (let i = 0; i < this.#isCollidingWith.length; i++) {
const {entity} = this.#isCollidingWith[i];
for (let i = 0; i < this.$$isCollidingWith.length; i++) {
const {entity} = this.$$isCollidingWith[i];
entity.emit('collisionEnd', this.entity);
}
this.#isCollidingWith = [];
this.$$isCollidingWith = [];
}
// eslint-disable-next-line class-methods-use-this
@ -176,7 +176,7 @@ export default (flecks) => class Collider extends decorate(Trait) {
collisionEnd: (other, incident) => {
const index = this.indexOfCollidingEntity(other);
if (-1 !== index) {
this.#isCollidingWith.splice(index, 1);
this.$$isCollidingWith.splice(index, 1);
if (this.params.collisionEndScript) {
this.pushCollisionTickingPromise(this.params.collisionEndScript, other, incident);
}
@ -186,7 +186,7 @@ export default (flecks) => class Collider extends decorate(Trait) {
collisionStart: (other, incident) => {
const index = this.indexOfCollidingEntity(other);
if (-1 === index) {
this.#isCollidingWith.push({
this.$$isCollidingWith.push({
entity: other,
incident,
});
@ -210,25 +210,25 @@ export default (flecks) => class Collider extends decorate(Trait) {
if (!this.entity.isColliding || !entity.isColliding) {
return false;
}
if (-1 !== this.#doesNotCollideWith.indexOf(entity)) {
if (-1 !== this.$$doesNotCollideWith.indexOf(entity)) {
return false;
}
const {collisionGroup} = entity;
return -1 !== this.#collidesWithGroups.indexOf(collisionGroup);
return -1 !== this.$$collidesWithGroups.indexOf(collisionGroup);
},
doesNotCollideWith: (entity) => !this.entity.collidesWith(entity),
setDoesCollideWith: (entity) => {
const index = this.#doesNotCollideWith.indexOf(entity);
const index = this.$$doesNotCollideWith.indexOf(entity);
if (-1 !== index) {
this.#doesNotCollideWith.splice(index, 1);
this.$$doesNotCollideWith.splice(index, 1);
}
},
setDoesNotCollideWith: (entity) => {
if (-1 === this.#doesNotCollideWith.indexOf(entity)) {
this.#doesNotCollideWith.push(entity);
if (-1 === this.$$doesNotCollideWith.indexOf(entity)) {
this.$$doesNotCollideWith.push(entity);
}
},
};

View File

@ -7,39 +7,39 @@ const decorate = compose(
export default (flecks) => class Emitted extends decorate(Trait) {
#alphaStart;
$$alphaStart;
#alphaEnd;
$$alphaEnd;
#force;
$$force;
#mass;
$$mass;
#position;
$$position;
#rotationStart;
$$rotationStart;
#rotationAdd;
$$rotationAdd;
#ttl;
$$ttl;
#velocityAngle;
$$velocityAngle;
#velocityMagnitude;
$$velocityMagnitude;
constructor(...args) {
super(...args);
const params = this.constructor.defaultParams();
this.#alphaStart = new Range(params.alpha.start);
this.#alphaEnd = new Range(params.alpha.end);
this.#force = new Vector.Range(params.force);
this.#mass = params.mass;
this.#position = null;
this.#rotationStart = new Range(params.rotation.start);
this.#rotationAdd = new Range(params.rotation.add);
this.#ttl = new Range(params.ttl);
this.#velocityAngle = new Range(params.velocity.angle);
this.#velocityMagnitude = new Range(params.velocity.magnitude);
this.$$alphaStart = new Range(params.alpha.start);
this.$$alphaEnd = new Range(params.alpha.end);
this.$$force = new Vector.Range(params.force);
this.$$mass = params.mass;
this.$$position = null;
this.$$rotationStart = new Range(params.rotation.start);
this.$$rotationAdd = new Range(params.rotation.add);
this.$$ttl = new Range(params.ttl);
this.$$velocityAngle = new Range(params.velocity.angle);
this.$$velocityMagnitude = new Range(params.velocity.magnitude);
}
static behaviorTypes() {
@ -85,21 +85,21 @@ export default (flecks) => class Emitted extends decorate(Trait) {
async load(json) {
await super.load(json);
this.#alphaStart = new Range(this.params.alpha.start);
this.#alphaEnd = new Range(this.params.alpha.end);
this.#force = new Vector.Range(this.params.force);
this.#mass = this.params.mass;
this.$$alphaStart = new Range(this.params.alpha.start);
this.$$alphaEnd = new Range(this.params.alpha.end);
this.$$force = new Vector.Range(this.params.force);
this.$$mass = this.params.mass;
if (null !== this.params.position) {
this.#position = new Vector.Range(this.params.position);
this.$$position = new Vector.Range(this.params.position);
}
else {
this.#position = null;
this.$$position = null;
}
this.#rotationStart = new Range(this.params.rotation.start);
this.#rotationAdd = new Range(this.params.rotation.add);
this.#ttl = new Range(this.params.ttl);
this.#velocityAngle = new Range(this.params.velocity.angle);
this.#velocityMagnitude = new Range(this.params.velocity.magnitude);
this.$$rotationStart = new Range(this.params.rotation.start);
this.$$rotationAdd = new Range(this.params.rotation.add);
this.$$ttl = new Range(this.params.ttl);
this.$$velocityAngle = new Range(this.params.velocity.angle);
this.$$velocityMagnitude = new Range(this.params.velocity.magnitude);
}
listeners() {
@ -121,25 +121,25 @@ export default (flecks) => class Emitted extends decorate(Trait) {
return {
particle: () => {
const position = null === this.#position ? null : this.#position.value();
const force = this.#force.value();
const position = null === this.$$position ? null : this.$$position.value();
const force = this.$$force.value();
const particle = {
alpha: {
start: this.#alphaStart.value(),
end: this.#alphaEnd.value(),
start: this.$$alphaStart.value(),
end: this.$$alphaEnd.value(),
},
force,
listed: this.params.listed,
mass: this.#mass,
mass: this.$$mass,
position,
rotation: {
start: this.#rotationStart.value(),
add: this.#rotationAdd.value(),
start: this.$$rotationStart.value(),
add: this.$$rotationAdd.value(),
},
ttl: this.#ttl.value(),
ttl: this.$$ttl.value(),
velocity: {
angle: this.#velocityAngle.value(),
magnitude: this.#velocityMagnitude.value(),
angle: this.$$velocityAngle.value(),
magnitude: this.$$velocityMagnitude.value(),
},
};
if (this.params.scale) {

View File

@ -12,30 +12,30 @@ const decorate = compose(
export default (flecks) => class Emitter extends decorate(Trait) {
#emissions = [];
$$emissions = [];
#emitter = new Proton.Emitter();
$$emitter = new Proton.Emitter();
#emitting = [];
$$emitting = [];
#onParticleDead;
$$onParticleDead;
#onParticleUpdate;
$$onParticleUpdate;
#particles = {};
$$particles = {};
#proton = new Proton();
$$proton = new Proton();
#streams = [];
$$streams = [];
constructor() {
super();
this.#proton.addEmitter(this.#emitter);
this.#onParticleDead = this.onParticleDead.bind(this);
this.#onParticleUpdate = this.onParticleUpdate.bind(this);
this.#emitter.bindEvent = true;
this.#emitter.addEventListener('PARTICLE_DEAD', this.#onParticleDead);
this.#emitter.addEventListener('PARTICLE_UPDATE', this.#onParticleUpdate);
this.$$proton.addEmitter(this.$$emitter);
this.$$onParticleDead = this.onParticleDead.bind(this);
this.$$onParticleUpdate = this.onParticleUpdate.bind(this);
this.$$emitter.bindEvent = true;
this.$$emitter.addEventListener('PARTICLE_DEAD', this.$$onParticleDead);
this.$$emitter.addEventListener('PARTICLE_UPDATE', this.$$onParticleUpdate);
}
acceptPacket(packet) {
@ -48,7 +48,7 @@ export default (flecks) => class Emitter extends decorate(Trait) {
cleanPackets() {
super.cleanPackets();
this.#emitting = [];
this.$$emitting = [];
}
static defaultParams() {
@ -77,20 +77,20 @@ export default (flecks) => class Emitter extends decorate(Trait) {
const [key, particle] = paramParticles[i];
particles[key] = merge(particles[key] || {}, particle);
}
this.#particles = particles;
this.$$particles = particles;
}
hooks() {
const hooks = {};
hooks.afterDestructionTickers = () => (elapsed) => {
if (0 === this.#emitter.particles.length) {
this.#emitter.destroy();
if (0 === this.$$emitter.particles.length) {
this.$$emitter.destroy();
return true;
}
this.tick(elapsed);
return false;
};
hooks.destroy = () => () => 0 === this.#streams.length;
hooks.destroy = () => () => 0 === this.$$streams.length;
return hooks;
}
@ -152,7 +152,7 @@ export default (flecks) => class Emitter extends decorate(Trait) {
),
);
}
const protonParticle = this.#emitter.createParticle(
const protonParticle = this.$$emitter.createParticle(
initializers,
behaviors,
);
@ -166,7 +166,7 @@ export default (flecks) => class Emitter extends decorate(Trait) {
this.entity.list.addEntity(entity);
}
// Prime.
this.#onParticleUpdate(protonParticle);
this.$$onParticleUpdate(protonParticle);
return entity;
},
@ -188,7 +188,7 @@ export default (flecks) => class Emitter extends decorate(Trait) {
json,
);
if (transmit && 'web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
this.#emitting.push(augmentedJson);
this.$$emitting.push(augmentedJson);
this.markAsDirty();
}
const stream = K.stream((emitter) => {
@ -209,9 +209,9 @@ export default (flecks) => class Emitter extends decorate(Trait) {
count -= 1;
if (count > 0) {
const removeEmission = () => {
const index = this.#emissions.indexOf(ticker);
const index = this.$$emissions.indexOf(ticker);
if (-1 !== index) {
this.#emissions.splice(index, 1);
this.$$emissions.splice(index, 1);
}
emitter.end();
};
@ -222,27 +222,27 @@ export default (flecks) => class Emitter extends decorate(Trait) {
removeEmission();
}
});
this.#emissions.push(ticker);
this.$$emissions.push(ticker);
}
}
});
this.#streams.push(stream);
this.$$streams.push(stream);
stream.onEnd(() => {
const index = this.#streams.indexOf(stream);
this.#streams.splice(index, 1);
const index = this.$$streams.indexOf(stream);
this.$$streams.splice(index, 1);
});
return stream;
},
emitParticle: (key, json = {}) => {
const particleJson = this.#particles[key];
const particleJson = this.$$particles[key];
if (!particleJson) {
return undefined;
}
return this.entity.emitParticleJson(merge(particleJson, json));
},
jsonForParticle: (key, json = {}) => merge(this.#particles[key] || {}, json),
jsonForParticle: (key, json = {}) => merge(this.$$particles[key] || {}, json),
};
}
@ -271,15 +271,15 @@ export default (flecks) => class Emitter extends decorate(Trait) {
}
packetsFor() {
return this.#emitting.length > 0
? [['EmitParticles', this.#emitting]]
return this.$$emitting.length > 0
? [['EmitParticles', this.$$emitting]]
: [];
}
tick(elapsed) {
this.#emitter.update(elapsed);
for (let i = 0; i < this.#emissions.length; i++) {
this.#emissions[i].tick(elapsed);
this.$$emitter.update(elapsed);
for (let i = 0; i < this.$$emissions.length; i++) {
this.$$emissions[i].tick(elapsed);
}
}

View File

@ -12,28 +12,28 @@ const decorate = compose(
export default () => class Physical extends decorate(Trait) {
#body;
$$body;
#bodyView;
$$bodyView;
#world;
$$world;
addToWorld() {
const world = this.#world;
const world = this.$$world;
if (world) {
const body = world.createBody(this.entity.shape);
body.friction = this.entity.friction;
world.associateBodyWithEntity(body, this.entity);
body.setCollisionForEntity(this.entity);
world.addBody(body);
this.#body = body;
this.$$body = body;
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
if (this.entity.is('Visible') && this.params.isDebugging) {
this.#bodyView = new BodyView(body);
this.#bodyView.position = Vector.scale(this.entity.position, -1);
this.#bodyView.visible = true;
this.#bodyView.zIndex = 101;
this.entity.addRasterChild(this.#bodyView);
this.$$bodyView = new BodyView(body);
this.$$bodyView.position = Vector.scale(this.entity.position, -1);
this.$$bodyView.visible = true;
this.$$bodyView.zIndex = 101;
this.entity.addRasterChild(this.$$bodyView);
}
}
}
@ -63,7 +63,7 @@ export default () => class Physical extends decorate(Trait) {
}
get body() {
return this.#body;
return this.$$body;
}
static defaultParams() {
@ -101,19 +101,19 @@ export default () => class Physical extends decorate(Trait) {
},
frictionChanged: () => {
if (this.#body) {
this.#body.friction = this.entity.friction;
if (this.$$body) {
this.$$body.friction = this.entity.friction;
}
},
positionChanged: () => {
if (this.#body) {
this.#body.position = this.entity.position;
if (this.$$body) {
this.$$body.position = this.entity.position;
}
},
removedFromRoom: () => {
if (this.#body) {
if (this.$$body) {
this.removeFromWorld();
}
},
@ -125,14 +125,14 @@ export default () => class Physical extends decorate(Trait) {
return {
applyForce: (force) => {
if (this.#world && this.#body) {
this.#body.applyForce(force);
if (this.$$world && this.$$body) {
this.$$body.applyForce(force);
}
},
applyImpulse: (impulse) => {
if (this.#world && this.#body) {
this.#body.applyImpulse(impulse);
if (this.$$world && this.$$body) {
this.$$body.applyImpulse(impulse);
}
},
@ -140,25 +140,25 @@ export default () => class Physical extends decorate(Trait) {
}
removeFromWorld() {
if (this.#world && this.#body) {
this.#world.removeBody(this.#body);
if (this.$$world && this.$$body) {
this.$$world.removeBody(this.$$body);
}
this.#body = undefined;
if (this.#bodyView) {
this.$$body = undefined;
if (this.$$bodyView) {
if (this.entity.is('Visible')) {
this.entity.removeRasterChild(this.#bodyView);
this.entity.removeRasterChild(this.$$bodyView);
}
this.#bodyView.destroy();
this.$$bodyView.destroy();
}
this.#bodyView = undefined;
this.$$bodyView = undefined;
}
set world(world) {
if (this.#world === world) {
if (this.$$world === world) {
return;
}
this.removeFromWorld();
this.#world = world;
this.$$world = world;
this.addToWorld();
}

View File

@ -9,9 +9,9 @@ const decorate = compose(
export default () => class Shaped extends decorate(Trait) {
#shape;
$$shape;
#shapeView;
$$shapeView;
static defaultParams() {
return {
@ -26,11 +26,11 @@ export default () => class Shaped extends decorate(Trait) {
destroy() {
super.destroy();
this.#shape.destroy();
if (this.#shapeView) {
this.entity.removeRasterChild(this.#shapeView);
this.#shapeView.destroy();
this.#shapeView = undefined;
this.$$shape.destroy();
if (this.$$shapeView) {
this.entity.removeRasterChild(this.$$shapeView);
this.$$shapeView.destroy();
this.$$shapeView = undefined;
}
}
@ -40,11 +40,11 @@ export default () => class Shaped extends decorate(Trait) {
traitAdded: () => {
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
if (this.entity.is('Visible') && this.params.isDebugging) {
if (!this.#shapeView) {
this.#shapeView = new ShapeView(this.entity.shape);
this.#shapeView.visible = false;
this.#shapeView.zIndex = 100;
this.entity.addRasterChild(this.#shapeView);
if (!this.$$shapeView) {
this.$$shapeView = new ShapeView(this.entity.shape);
this.$$shapeView.visible = false;
this.$$shapeView.zIndex = 100;
this.entity.addRasterChild(this.$$shapeView);
}
}
}
@ -55,11 +55,11 @@ export default () => class Shaped extends decorate(Trait) {
async load(json) {
await super.load(json);
this.#shape = shapeFromJSON(this.params.shape);
this.$$shape = shapeFromJSON(this.params.shape);
}
get shape() {
return this.#shape;
return this.$$shape;
}
};

View File

@ -3,37 +3,37 @@ class Cancellation extends Error {}
export default class Serializer {
#pending = new Map();
$$pending = new Map();
#promises = new Map();
$$promises = new Map();
create(id, creator) {
const promise = creator.then(async (resource) => {
if (!this.#pending.has(id)) {
if (!this.$$pending.has(id)) {
await resource.destroy();
throw new Cancellation();
}
this.#pending.delete(id);
this.$$pending.delete(id);
return resource;
}).catch((error) => {
if (!(error instanceof Cancellation)) {
throw error;
}
});
this.#pending.set(id, () => this.#pending.delete(id));
this.#promises.set(id, promise);
this.$$pending.set(id, () => this.$$pending.delete(id));
this.$$promises.set(id, promise);
return promise;
}
destroy(id) {
// Cancel...
this.#pending.get(id)?.();
this.#pending.delete(id);
this.#promises.delete(id);
this.$$pending.get(id)?.();
this.$$pending.delete(id);
this.$$promises.delete(id);
}
later(id, fn) {
const promise = this.#promises.get(id);
const promise = this.$$promises.get(id);
if (!promise) {
return Promise.resolve();
}

View File

@ -51,18 +51,18 @@ if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
export default class Sound extends JsonResource {
#audio;
$$audio;
async load(json = {}) {
await super.load(json);
const {volume = 1} = json;
const src = json.src || json.uri.replace('.sound.json', '.wav');
if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
this.#audio = new FakeAudio();
this.$$audio = new FakeAudio();
return;
}
if (cache.has(src)) {
this.#audio = await cache.get(src);
this.$$audio = await cache.get(src);
return;
}
const promise = new Promise((resolve, reject) => {
@ -83,16 +83,16 @@ export default class Sound extends JsonResource {
}).catch(reject);
});
cache.set(src, promise);
this.#audio = await promise;
this.$$audio = await promise;
}
pause() {
this.#audio.pause();
this.$$audio.pause();
}
play() {
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
play(this.#audio, this.uri);
play(this.$$audio, this.uri);
}
}

View File

@ -7,9 +7,9 @@ const debug = D('@avocado/sound/audible');
export default () => class Audible extends Trait {
#playing = {};
$$playing = {};
#sounds = {};
$$sounds = {};
acceptPacket(packet) {
if ('PlaySound' === packet.constructor.type) {
@ -20,20 +20,20 @@ export default () => class Audible extends Trait {
async addSounds(sounds) {
return Promise.all(
Object.entries(sounds).map(([key, sound]) => {
if (this.#sounds[key]) {
if (this.$$sounds[key]) {
return undefined;
}
this.#sounds[key] = Sound.load(sound).then((sound) => {
this.#sounds[key] = sound;
this.$$sounds[key] = Sound.load(sound).then((sound) => {
this.$$sounds[key] = sound;
});
return this.#sounds[key];
return this.$$sounds[key];
}),
);
}
cleanPackets() {
super.cleanPackets();
this.#playing = {};
this.$$playing = {};
}
static defaultParams() {
@ -44,7 +44,7 @@ export default () => class Audible extends Trait {
destroy() {
super.destroy();
Object.values(this.#sounds).forEach((sound) => {
Object.values(this.$$sounds).forEach((sound) => {
Promise.resolve(sound).then((sound) => {
sound.destroy();
});
@ -69,19 +69,19 @@ export default () => class Audible extends Trait {
methods() {
return {
hasSound: (key) => !!this.#sounds[key],
hasSound: (key) => !!this.$$sounds[key],
playSound: (key) => {
debug('Checking %s', key);
if (!this.entity.hasSound(key)) {
try {
this.#sounds[key] = Sound.load({extends: key})
this.$$sounds[key] = Sound.load({extends: key})
.then((sound) => {
this.#sounds[key] = sound;
this.$$sounds[key] = sound;
return sound;
})
.catch(() => {
delete this.#sounds[key];
delete this.$$sounds[key];
});
this.playSound(key);
}
@ -89,13 +89,13 @@ export default () => class Audible extends Trait {
catch (error) {}
}
if ('web' === process.env.FLECKS_CORE_BUILD_TARGET) {
Promise.resolve(this.#sounds[key]).then((sound) => {
Promise.resolve(this.$$sounds[key]).then((sound) => {
debug('Playing %s', key);
sound.play();
});
}
else {
this.#playing[key] = true;
this.$$playing[key] = true;
this.markAsDirty();
}
},
@ -116,7 +116,7 @@ export default () => class Audible extends Trait {
}
packetsFor() {
return Object.keys(this.#playing).map((key) => ['PlaySound', {sound: key}]);
return Object.keys(this.$$playing).map((key) => ['PlaySound', {sound: key}]);
}
};

View File

@ -17,20 +17,20 @@ const decorate = compose(
export default (flecks) => class Animated extends decorate(Trait) {
#animations = {};
$$animations = {};
#animationViews = {};
$$animationViews = {};
#cachedAabbs = {};
$$cachedAabbs = {};
#currentAnimation = '';
$$currentAnimation = '';
#forceUpdate = false;
$$forceUpdate = false;
constructor() {
super();
({
currentAnimation: this.#currentAnimation,
currentAnimation: this.$$currentAnimation,
} = this.constructor.defaultParams());
}
@ -43,7 +43,7 @@ export default (flecks) => class Animated extends decorate(Trait) {
}
get animation() {
return this.#animations[this.#currentAnimation];
return this.$$animations[this.$$currentAnimation];
}
static defaultParams() {
@ -67,28 +67,28 @@ export default (flecks) => class Animated extends decorate(Trait) {
destroy() {
super.destroy();
if (this.#animationViews) {
const animationViews = Object.entries(this.#animationViews);
if (this.$$animationViews) {
const animationViews = Object.entries(this.$$animationViews);
for (let i = 0; i < animationViews.length; i++) {
const [key, animationView] = animationViews[i];
this.hideAnimation(key);
animationView.destroy();
}
this.#animationViews = undefined;
this.$$animationViews = undefined;
}
const animations = Object.values(this.#animations);
const animations = Object.values(this.$$animations);
for (let i = 0; i < animations.length; i++) {
animations[i].destroy();
}
this.#animations = {};
this.#cachedAabbs = {};
this.$$animations = {};
this.$$cachedAabbs = {};
}
hideAnimation(key) {
if (!this.#animationViews) {
if (!this.$$animationViews) {
return;
}
const animationView = this.#animationViews[key];
const animationView = this.$$animationViews[key];
if (!animationView) {
return;
}
@ -102,14 +102,14 @@ export default (flecks) => class Animated extends decorate(Trait) {
return {
visibleAabbs: () => {
const key = this.#currentAnimation;
if (key in this.#cachedAabbs) {
return this.#cachedAabbs[key];
const key = this.$$currentAnimation;
if (key in this.$$cachedAabbs) {
return this.$$cachedAabbs[key];
}
if (!(key in this.#animations)) {
if (!(key in this.$$animations)) {
return [0, 0, 0, 0];
}
const {frameSize} = this.#animations[key];
const {frameSize} = this.$$animations[key];
const scaledSize = Vector.mul(frameSize, this.entity.visibleScale);
const viewPosition = Vector.sub(
this.offsetFor(key),
@ -120,7 +120,7 @@ export default (flecks) => class Animated extends decorate(Trait) {
rectangle,
Vector.sub(scaledSize, frameSize),
);
this.#cachedAabbs[key] = expanded;
this.$$cachedAabbs[key] = expanded;
return expanded;
},
@ -138,16 +138,16 @@ export default (flecks) => class Animated extends decorate(Trait) {
return {
currentAnimationChanged: (oldKey, currentAnimation) => {
this.#currentAnimation = currentAnimation;
this.$$currentAnimation = currentAnimation;
// Reset old animation.
if (oldKey in this.#animations) {
const oldAnimation = this.#animations[oldKey];
if (oldKey in this.$$animations) {
const oldAnimation = this.$$animations[oldKey];
oldAnimation.reset();
}
// Bounding box update.
this.entity.scheduleBoundingBoxUpdate();
// Only client/graphics.
if (!this.#animationViews) {
if (!this.$$animationViews) {
return;
}
// Swap the animation.
@ -157,7 +157,7 @@ export default (flecks) => class Animated extends decorate(Trait) {
directionChanged: () => {
// All animations track direction.
const animations = Object.values(this.#animations);
const animations = Object.values(this.$$animations);
for (let i = 0; i < animations.length; i++) {
animations[i].direction = this.entity.direction;
}
@ -169,8 +169,8 @@ export default (flecks) => class Animated extends decorate(Trait) {
traitAdded: () => {
this.setSpriteScale();
Object.entries(this.#animations).forEach(([key, animation]) => {
const method = key === this.#currentAnimation
Object.entries(this.$$animations).forEach(([key, animation]) => {
const method = key === this.$$currentAnimation
? 'showAnimation'
: 'hideAnimation';
this[method](key);
@ -183,7 +183,7 @@ export default (flecks) => class Animated extends decorate(Trait) {
},
visibleScaleChanged: () => {
this.#cachedAabbs = {};
this.$$cachedAabbs = {};
this.setSpriteScale();
},
@ -206,18 +206,18 @@ export default (flecks) => class Animated extends decorate(Trait) {
// eslint-disable-next-line no-param-reassign
animationView.position = this.offsetFor(key);
});
this.#animations = animations;
this.#animationViews = animationViews;
this.$$animations = animations;
this.$$animationViews = animationViews;
}
this.#currentAnimation = this.state.currentAnimation;
this.$$currentAnimation = this.state.currentAnimation;
}
methods() {
return {
setAnimationRate: (rate) => {
if (this.#animations[this.#currentAnimation].frameRate !== rate) {
this.#animations[this.#currentAnimation].frameRate = rate;
this.#forceUpdate = true;
if (this.$$animations[this.$$currentAnimation].frameRate !== rate) {
this.$$animations[this.$$currentAnimation].frameRate = rate;
this.$$forceUpdate = true;
}
},
};
@ -232,8 +232,8 @@ export default (flecks) => class Animated extends decorate(Trait) {
packetsFor() {
const {currentAnimation, isAnimating} = this.stateDifferences();
if (this.#forceUpdate || currentAnimation || isAnimating) {
this.#forceUpdate = false;
if (this.$$forceUpdate || currentAnimation || isAnimating) {
this.$$forceUpdate = false;
return [[
'TraitUpdateAnimated',
{
@ -247,20 +247,20 @@ export default (flecks) => class Animated extends decorate(Trait) {
}
setSpriteScale() {
if (!this.#animationViews) {
if (!this.$$animationViews) {
return;
}
const animationViews = Object.values(this.#animationViews);
const animationViews = Object.values(this.$$animationViews);
for (let i = 0; i < animationViews.length; i++) {
animationViews[i].scale = this.entity.visibleScale;
}
}
showAnimation(key) {
if (!this.#animationViews) {
if (!this.$$animationViews) {
return;
}
const animationView = this.#animationViews[key];
const animationView = this.$$animationViews[key];
if (!animationView) {
return;
}
@ -275,11 +275,11 @@ export default (flecks) => class Animated extends decorate(Trait) {
return;
}
// Only tick current animation.
const currentAnimation = this.#currentAnimation;
if (!(currentAnimation in this.#animations)) {
const currentAnimation = this.$$currentAnimation;
if (!(currentAnimation in this.$$animations)) {
return;
}
const animation = this.#animations[currentAnimation];
const animation = this.$$animations[currentAnimation];
const jitterAmount = this.jitterFor(currentAnimation);
if (jitterAmount > 0) {
const jitter = Math.random() * jitterAmount;

View File

@ -2,7 +2,7 @@ import {Trait} from '@avocado/traits';
export default () => class Evolving extends Trait {
#evolving;
$$evolving;
static defaultParams() {
return {
@ -15,11 +15,11 @@ export default () => class Evolving extends Trait {
if (0 === Object.keys(this.params.lfo).length) {
return;
}
this.#evolving = this.entity.lfo(this.params.lfo);
this.$$evolving = this.entity.lfo(this.params.lfo);
}
tick(elapsed) {
this.#evolving.tick(elapsed);
this.$$evolving.tick(elapsed);
}
};

View File

@ -35,23 +35,23 @@ export default (flecks) => {
);
return class Tiles extends decorate(JsonResource) {
#atlas = new Atlas();
$$atlas = new Atlas();
#data = new Uint16Array();
$$data = new Uint16Array();
#hasUpdates = false;
$$hasUpdates = false;
#packets = [];
$$packets = [];
#s13nId = 0;
$$s13nId = 0;
#tileImageUri;
$$tileImageUri;
#tileSize = [0, 0];
$$tileSize = [0, 0];
#updates = [];
$$updates = [];
#zIndex = 0;
$$zIndex = 0;
acceptPacket(packet) {
if ('TilesUpdate' === packet.constructor.type) {
@ -62,12 +62,12 @@ export default (flecks) => {
}
cleanPackets() {
this.#packets = [];
this.#updates = [];
this.$$packets = [];
this.$$updates = [];
}
destroy() {
this.#atlas.destroy();
this.$$atlas.destroy();
}
static indexHulls(indices, data, size) {
@ -132,7 +132,7 @@ export default (flecks) => {
}
indexHulls(indices) {
return this.constructor.indexHulls(indices, this.#data, this.area);
return this.constructor.indexHulls(indices, this.$$data, this.area);
}
async load(json) {
@ -149,37 +149,37 @@ export default (flecks) => {
}
if (data) {
const {buffer, byteOffset, length} = inflate(Buffer.from(data, 'base64'));
this.#data = new Uint16Array(buffer, byteOffset, length / 2);
this.$$data = new Uint16Array(buffer, byteOffset, length / 2);
}
else if (area) {
this.#data = new Uint16Array(Vector.area(area));
this.$$data = new Uint16Array(Vector.area(area));
}
if (tileImageUri && tileSize) {
this.#tileSize = tileSize;
this.#tileImageUri = tileImageUri;
await this.#atlas.load({
this.$$tileSize = tileSize;
this.$$tileImageUri = tileImageUri;
await this.$$atlas.load({
imageUri: tileImageUri,
type: 'grid',
size: tileSize,
});
}
if (s13nId) {
this.#s13nId = s13nId;
this.$$s13nId = s13nId;
}
if (zIndex > 0) {
this.#zIndex = zIndex;
this.$$zIndex = zIndex;
}
}
packetsFor() {
if (0 === this.#updates.length) {
if (0 === this.$$updates.length) {
return [];
}
if (0 === this.#packets.length) {
if (0 === this.$$packets.length) {
// TODO: merge?
for (let i = 0; i < this.#updates.length; i++) {
const [position, size, tiles] = this.#updates[i];
this.#packets.push([
for (let i = 0; i < this.$$updates.length; i++) {
const [position, size, tiles] = this.$$updates[i];
this.$$packets.push([
'TilesUpdate',
{
position,
@ -189,7 +189,7 @@ export default (flecks) => {
]);
}
}
return this.#packets;
return this.$$packets;
}
get rectangle() {
@ -197,19 +197,19 @@ export default (flecks) => {
}
get s13nId() {
return this.#s13nId;
return this.$$s13nId;
}
setTileAt([x, y], tile) {
const [w, h] = this.area;
const index = y * w + x;
if (x < 0 || x >= w || y < 0 || y >= h || this.#data[index] === tile) {
if (x < 0 || x >= w || y < 0 || y >= h || this.$$data[index] === tile) {
return;
}
this.#data[index] = tile;
this.$$data[index] = tile;
if ('web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
this.#updates.push([[x, y], [1, 1], [tile]]);
this.#hasUpdates = true;
this.$$updates.push([[x, y], [1, 1], [tile]]);
this.$$hasUpdates = true;
}
}
@ -225,7 +225,7 @@ export default (flecks) => {
let j = 0;
for (let l = 0; l < h; ++l) {
for (let k = 0; k < w; ++k) {
slice[j] = x < 0 || x >= fw || y < 0 || y >= fh ? 0 : this.#data[i];
slice[j] = x < 0 || x >= fw || y < 0 || y >= fh ? 0 : this.$$data[i];
x += 1;
i += 1;
j += 1;
@ -254,7 +254,7 @@ export default (flecks) => {
for (let yy = 0; yy < h; ++yy) {
for (let xx = 0; xx < w; ++xx) {
if (sx >= 0 && sx < fw && sy >= 0 && sy < fh) {
this.#data[i] = tiles[j];
this.$$data[i] = tiles[j];
isDirty = true;
}
i += 1;
@ -267,49 +267,49 @@ export default (flecks) => {
sy += 1;
}
if (isDirty && 'web' !== process.env.FLECKS_CORE_BUILD_TARGET) {
this.#updates.push([[x, y], [w, h], tiles]);
this.#hasUpdates = true;
this.$$updates.push([[x, y], [w, h], tiles]);
this.$$hasUpdates = true;
}
}
subimage(index) {
return this.#atlas.subimage(index);
return this.$$atlas.subimage(index);
}
tick() {
if (this.#hasUpdates) {
if (this.$$hasUpdates) {
this.emit('update');
}
this.#hasUpdates = false;
this.$$hasUpdates = false;
}
tileAt([x, y]) {
const [w, h] = this.area;
return x < 0 || x >= w || y < 0 || y >= h ? undefined : this.#data[y * w + x];
return x < 0 || x >= w || y < 0 || y >= h ? undefined : this.$$data[y * w + x];
}
get tileSize() {
return this.#tileSize;
return this.$$tileSize;
}
toNetwork() {
return {
...this.toJSON(),
s13nId: this.#s13nId,
s13nId: this.$$s13nId,
};
}
toJSON() {
return {
area: this.area,
data: deflate(this.#data).toString('base64'),
tileSize: this.#tileSize,
...(this.#tileImageUri ? {tileImageUri: this.#tileImageUri} : []),
data: deflate(this.$$data).toString('base64'),
tileSize: this.$$tileSize,
...(this.$$tileImageUri ? {tileImageUri: this.$$tileImageUri} : []),
};
}
get zIndex() {
return this.#zIndex;
return this.$$zIndex;
}
};

View File

@ -4,7 +4,7 @@ import Camera from '../camera';
export default (flecks) => class Followed extends Trait {
#camera = new Camera();
$$camera = new Camera();
static defaultParams() {
return {
@ -19,12 +19,12 @@ export default (flecks) => class Followed extends Trait {
}
get camera() {
return this.#camera;
return this.$$camera;
}
hotJSON() {
return {
camera: this.#camera,
camera: this.$$camera,
};
}
@ -42,9 +42,9 @@ export default (flecks) => class Followed extends Trait {
await super.load(json);
// @hot
if (json.camera) {
this.#camera = json.camera;
this.$$camera = json.camera;
}
this.#camera.viewSize = this.params.viewSize;
this.$$camera.viewSize = this.params.viewSize;
this.updatePosition();
this.onRoomSizeChanged();
}
@ -52,12 +52,12 @@ export default (flecks) => class Followed extends Trait {
onRoomSizeChanged() {
const {room} = this.entity;
if (room) {
this.#camera.areaSize = room.size;
this.$$camera.areaSize = room.size;
}
}
renderTick(elapsed) {
this.#camera.tick(elapsed);
this.$$camera.tick(elapsed);
}
tick() {
@ -65,7 +65,7 @@ export default (flecks) => class Followed extends Trait {
}
updatePosition() {
this.#camera.position = this.entity.position;
this.$$camera.position = this.entity.position;
}
};

View File

@ -2,18 +2,18 @@ import {JsonResource} from '@avocado/resource';
export default class Trait extends JsonResource {
#markedAsDirty = true;
$$markedAsDirty = true;
#memoizedListeners = undefined;
$$memoizedListeners = undefined;
#previousState = {};
$$previousState = {};
constructor() {
super();
const {constructor} = this;
this.params = constructor.defaultParams();
this.state = constructor.defaultState();
this.#previousState = JSON.parse(JSON.stringify(this.state));
this.$$previousState = JSON.parse(JSON.stringify(this.state));
if (this.tick) {
this.tick = this.tick.bind(this);
}
@ -26,7 +26,7 @@ export default class Trait extends JsonResource {
acceptPacket(packet) {}
cleanPackets() {
if (!this.#markedAsDirty) {
if (!this.$$markedAsDirty) {
return;
}
this.markAsClean();
@ -60,7 +60,7 @@ export default class Trait extends JsonResource {
}
destroy() {
this.#memoizedListeners = undefined;
this.$$memoizedListeners = undefined;
}
// eslint-disable-next-line class-methods-use-this
@ -78,28 +78,28 @@ export default class Trait extends JsonResource {
const {constructor} = this;
this.params = constructor.defaultParamsWith(params);
this.state = constructor.defaultStateWith(state);
this.#previousState = JSON.parse(JSON.stringify(this.state));
this.$$previousState = JSON.parse(JSON.stringify(this.state));
}
markAsClean() {
const state = Object.entries(this.state);
for (let i = 0; i < state.length; i++) {
const [key, value] = state[i];
this.#previousState[key] = value;
this.$$previousState[key] = value;
}
this.#markedAsDirty = false;
this.$$markedAsDirty = false;
}
markAsDirty() {
this.#markedAsDirty = true;
this.$$markedAsDirty = true;
this.entity.markAsDirty();
}
memoizedListeners() {
if (!this.#memoizedListeners) {
this.#memoizedListeners = this.listeners();
if (!this.$$memoizedListeners) {
this.$$memoizedListeners = this.listeners();
}
return this.#memoizedListeners;
return this.$$memoizedListeners;
}
// eslint-disable-next-line class-methods-use-this
@ -126,9 +126,9 @@ export default class Trait extends JsonResource {
const state = Object.entries(this.state);
for (let i = 0; i < state.length; i++) {
const [key, value] = state[i];
if (value !== this.#previousState[key]) {
if (value !== this.$$previousState[key]) {
differences[key] = {
old: this.#previousState[key],
old: this.$$previousState[key],
value,
};
}