Compare commits
No commits in common. "6eac2986710e19ef022c625e342f355353940e8b" and "a872d9ae5f540cf1835b14f5cb988980cc00fd51" have entirely different histories.
6eac298671
...
a872d9ae5f
|
@ -1,5 +1,4 @@
|
||||||
import {encode} from '@/net/packets/index.js';
|
import {encode} from '@/net/packets/index.js';
|
||||||
import {withResolvers} from '@/util/promise.js';
|
|
||||||
|
|
||||||
let connected = false;
|
let connected = false;
|
||||||
let socket;
|
let socket;
|
||||||
|
@ -13,7 +12,7 @@ onmessage = async (event) => {
|
||||||
const url = new URL(`wss://${event.data.host}/ws`)
|
const url = new URL(`wss://${event.data.host}/ws`)
|
||||||
socket = new WebSocket(url.href);
|
socket = new WebSocket(url.href);
|
||||||
socket.binaryType = 'arraybuffer';
|
socket.binaryType = 'arraybuffer';
|
||||||
const {promise, resolve} = withResolvers();
|
const {promise, resolve} = Promise.withResolvers();
|
||||||
socket.addEventListener('open', resolve);
|
socket.addEventListener('open', resolve);
|
||||||
socket.addEventListener('error', () => {
|
socket.addEventListener('error', () => {
|
||||||
postMessage(encode({type: 'ConnectionStatus', payload: 'aborted'}));
|
postMessage(encode({type: 'ConnectionStatus', payload: 'aborted'}));
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import Client from '@/net/client.js';
|
import Client from '@/net/client.js';
|
||||||
import {encode} from '@/net/packets/index.js';
|
import {encode} from '@/net/packets/index.js';
|
||||||
import {CLIENT_PREDICTION} from '@/util/constants.js';
|
import {CLIENT_PREDICTION} from '@/util/constants.js';
|
||||||
import {withResolvers} from '@/util/promise.js';
|
|
||||||
|
|
||||||
export default class RemoteClient extends Client {
|
export default class RemoteClient extends Client {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -31,7 +30,7 @@ export default class RemoteClient extends Client {
|
||||||
const onMessage = (event) => {
|
const onMessage = (event) => {
|
||||||
this.accept(event.data);
|
this.accept(event.data);
|
||||||
}
|
}
|
||||||
const {promise, resolve} = withResolvers();
|
const {promise, resolve} = Promise.withResolvers();
|
||||||
this.socket.addEventListener('open', resolve);
|
this.socket.addEventListener('open', resolve);
|
||||||
this.socket.addEventListener('error', () => {
|
this.socket.addEventListener('error', () => {
|
||||||
this.accept(encode({type: 'ConnectionStatus', payload: 'aborted'}));
|
this.accept(encode({type: 'ConnectionStatus', payload: 'aborted'}));
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
import Component from '@/ecs/component.js';
|
|
||||||
|
|
||||||
export default class Behaving extends Component {
|
|
||||||
instanceFromSchema() {
|
|
||||||
return class BehavingInstance extends super.instanceFromSchema() {
|
|
||||||
$$routineInstances = {};
|
|
||||||
tick(elapsed) {
|
|
||||||
const routine = this.$$routineInstances[this.currentRoutine];
|
|
||||||
if (routine) {
|
|
||||||
routine.tick(elapsed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async load(instance) {
|
|
||||||
// heavy handed...
|
|
||||||
if ('undefined' !== typeof window) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const promises = [];
|
|
||||||
for (const key in instance.routines) {
|
|
||||||
promises.push(
|
|
||||||
this.ecs.readScript(
|
|
||||||
instance.routines[key],
|
|
||||||
{
|
|
||||||
entity: this.ecs.get(instance.entity),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.then((script) => {
|
|
||||||
instance.$$routineInstances[key] = script;
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
await Promise.all(promises);
|
|
||||||
}
|
|
||||||
static properties = {
|
|
||||||
currentRoutine: {defaultValue: 'initial', type: 'string'},
|
|
||||||
isBehaving: {defaultValue: 1, type: 'uint8'},
|
|
||||||
routines: {
|
|
||||||
type: 'map',
|
|
||||||
value: {
|
|
||||||
type: 'string',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -8,7 +8,7 @@ export default class Interactive extends Component {
|
||||||
const script = this.interactScriptInstance.clone();
|
const script = this.interactScriptInstance.clone();
|
||||||
script.context.initiator = initiator;
|
script.context.initiator = initiator;
|
||||||
const {Ticking} = ecs.get(this.entity);
|
const {Ticking} = ecs.get(this.entity);
|
||||||
Ticking.add(script.ticker());
|
Ticking.addTickingPromise(script.tickingPromise());
|
||||||
}
|
}
|
||||||
get interacting() {
|
get interacting() {
|
||||||
return !!this.$$interacting;
|
return !!this.$$interacting;
|
||||||
|
|
|
@ -11,7 +11,7 @@ export default class Plant extends Component {
|
||||||
}
|
}
|
||||||
grow() {
|
grow() {
|
||||||
const {Ticking} = ecs.get(this.entity);
|
const {Ticking} = ecs.get(this.entity);
|
||||||
Ticking.add(this.growScriptInstance.ticker());
|
Ticking.addTickingPromise(this.growScriptInstance.tickingPromise());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,60 +3,24 @@ import Component from '@/ecs/component.js';
|
||||||
export default class Sprite extends Component {
|
export default class Sprite extends Component {
|
||||||
instanceFromSchema() {
|
instanceFromSchema() {
|
||||||
return class SpriteInstance extends super.instanceFromSchema() {
|
return class SpriteInstance extends super.instanceFromSchema() {
|
||||||
$$sourceJson = {};
|
|
||||||
get anchor() {
|
get anchor() {
|
||||||
return {x: this.anchorX, y: this.anchorY};
|
return {x: this.anchorX, y: this.anchorY};
|
||||||
}
|
}
|
||||||
get animation() {
|
|
||||||
return super.animation;
|
|
||||||
}
|
|
||||||
set animation(animation) {
|
|
||||||
super.animation = animation;
|
|
||||||
// eslint-disable-next-line no-self-assign
|
|
||||||
this.frame = this.frame;
|
|
||||||
}
|
|
||||||
get frame() {
|
|
||||||
return super.frame;
|
|
||||||
}
|
|
||||||
set frame(frame) {
|
|
||||||
super.frame = this.frames ? frame % this.frames : 0;
|
|
||||||
}
|
|
||||||
get frames() {
|
|
||||||
if (
|
|
||||||
!this.animation
|
|
||||||
|| !this.$$sourceJson.animations
|
|
||||||
|| !(this.animation in this.$$sourceJson.animations)
|
|
||||||
) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return this.$$sourceJson.animations[this.animation].length;
|
|
||||||
}
|
|
||||||
get scale() {
|
get scale() {
|
||||||
return {x: this.scaleX, y: this.scaleY};
|
return {x: this.scaleX, y: this.scaleY};
|
||||||
}
|
}
|
||||||
toNet() {
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const {elapsed, ...rest} = super.toNet();
|
|
||||||
return rest;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async load(instance) {
|
async load(instance) {
|
||||||
instance.$$sourceJson = await this.ecs.readJson(instance.source);
|
instance.$$sourceJson = await this.ecs.readJson(instance.source);
|
||||||
}
|
}
|
||||||
markChange(entityId, key, value) {
|
|
||||||
if ('elapsed' === key) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
super.markChange(entityId, key, value);
|
|
||||||
}
|
|
||||||
static properties = {
|
static properties = {
|
||||||
anchorX: {defaultValue: 0.5, type: 'float32'},
|
anchorX: {defaultValue: 0.5, type: 'float32'},
|
||||||
anchorY: {defaultValue: 0.5, type: 'float32'},
|
anchorY: {defaultValue: 0.5, type: 'float32'},
|
||||||
animation: {type: 'string'},
|
animation: {type: 'string'},
|
||||||
elapsed: {type: 'float32'},
|
elapsed: {type: 'float32'},
|
||||||
frame: {type: 'uint16'},
|
frame: {type: 'uint16'},
|
||||||
isAnimating: {defaultValue: 1, type: 'uint8'},
|
frames: {type: 'uint16'},
|
||||||
scaleX: {defaultValue: 1, type: 'float32'},
|
scaleX: {defaultValue: 1, type: 'float32'},
|
||||||
scaleY: {defaultValue: 1, type: 'float32'},
|
scaleY: {defaultValue: 1, type: 'float32'},
|
||||||
source: {type: 'string'},
|
source: {type: 'string'},
|
||||||
|
|
|
@ -5,30 +5,30 @@ export default class Ticking extends Component {
|
||||||
return class TickingInstance extends super.instanceFromSchema() {
|
return class TickingInstance extends super.instanceFromSchema() {
|
||||||
|
|
||||||
$$finished = [];
|
$$finished = [];
|
||||||
$$tickers = [];
|
$$tickingPromises = [];
|
||||||
|
|
||||||
add(ticker) {
|
addTickingPromise(tickingPromise) {
|
||||||
this.$$tickers.push(ticker);
|
this.$$tickingPromises.push(tickingPromise);
|
||||||
ticker.then(() => {
|
tickingPromise.then(() => {
|
||||||
this.$$finished.push(ticker);
|
this.$$finished.push(tickingPromise);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
this.$$finished = [];
|
this.$$finished = [];
|
||||||
this.$$tickers = [];
|
this.$$tickingPromises = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
tick(elapsed) {
|
tick(elapsed) {
|
||||||
for (const ticker of this.$$finished) {
|
for (const tickingPromise of this.$$finished) {
|
||||||
this.$$tickers.splice(
|
this.$$tickingPromises.splice(
|
||||||
this.$$tickers.indexOf(ticker),
|
this.$$tickingPromises.indexOf(tickingPromise),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.$$finished = [];
|
this.$$finished = [];
|
||||||
for (const ticker of this.$$tickers) {
|
for (const tickingPromise of this.$$tickingPromises) {
|
||||||
ticker.tick(elapsed);
|
tickingPromise.tick(elapsed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ export default class Wielder extends Component {
|
||||||
script.context.ecs = ecs;
|
script.context.ecs = ecs;
|
||||||
script.context.item = activeItem;
|
script.context.item = activeItem;
|
||||||
script.context.wielder = entity;
|
script.context.wielder = entity;
|
||||||
Ticking.add(script.ticker());
|
Ticking.addTickingPromise(script.tickingPromise());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import {Encoder, Decoder} from '@msgpack/msgpack';
|
import {Encoder, Decoder} from '@msgpack/msgpack';
|
||||||
import {LRUCache} from 'lru-cache';
|
import {LRUCache} from 'lru-cache';
|
||||||
|
|
||||||
import {withResolvers} from '@/util/promise.js';
|
|
||||||
import Script from '@/util/script.js';
|
import Script from '@/util/script.js';
|
||||||
|
|
||||||
import EntityFactory from './entity-factory.js';
|
import EntityFactory from './entity-factory.js';
|
||||||
|
@ -327,7 +326,11 @@ export default class Ecs {
|
||||||
async readJson(uri) {
|
async readJson(uri) {
|
||||||
const key = ['$$json', uri].join(':');
|
const key = ['$$json', uri].join(':');
|
||||||
if (!cache.has(key)) {
|
if (!cache.has(key)) {
|
||||||
const {promise, resolve, reject} = withResolvers();
|
let promise, resolve, reject;
|
||||||
|
promise = new Promise((res, rej) => {
|
||||||
|
resolve = res;
|
||||||
|
reject = rej;
|
||||||
|
});
|
||||||
cache.set(key, promise);
|
cache.set(key, promise);
|
||||||
this.readAsset(uri)
|
this.readAsset(uri)
|
||||||
.then((chars) => {
|
.then((chars) => {
|
||||||
|
|
|
@ -170,16 +170,10 @@ test('ticks systems', async () => {
|
||||||
.to.deep.equal(JSON.stringify({y: 128 + 30}));
|
.to.deep.equal(JSON.stringify({y: 128 + 30}));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('schedules entities to be deleted when ticking systems', async () => {
|
test('schedules entities to be deleted when ticking systems', () => {
|
||||||
const ecs = new Ecs({
|
const ecs = new Ecs({
|
||||||
Components: {Empty},
|
|
||||||
Systems: {
|
Systems: {
|
||||||
Despawn: class extends System {
|
Despawn: class extends System {
|
||||||
static queries() {
|
|
||||||
return {
|
|
||||||
default: ['Empty'],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
tick() {
|
tick() {
|
||||||
this.ecs.destroy(1);
|
this.ecs.destroy(1);
|
||||||
expect(ecs.get(1))
|
expect(ecs.get(1))
|
||||||
|
@ -189,10 +183,8 @@ test('schedules entities to be deleted when ticking systems', async () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
ecs.system('Despawn').active = true;
|
ecs.system('Despawn').active = true;
|
||||||
await ecs.create({Empty: {}});
|
ecs.create();
|
||||||
ecs.tick(1);
|
ecs.tick(1);
|
||||||
expect(Array.from(ecs.system('Despawn').select('default')))
|
|
||||||
.to.have.lengthOf(0);
|
|
||||||
expect(ecs.get(1))
|
expect(ecs.get(1))
|
||||||
.to.be.undefined;
|
.to.be.undefined;
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,8 +24,8 @@ export default class Query {
|
||||||
}
|
}
|
||||||
|
|
||||||
deindex(entityIds) {
|
deindex(entityIds) {
|
||||||
for (const entityId of entityIds) {
|
for (let i = 0; i < entityIds.length; ++i) {
|
||||||
this.$$index.delete(entityId);
|
this.$$index.delete(entityIds[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
import {System} from '@/ecs/index.js';
|
|
||||||
|
|
||||||
export default class Behave extends System {
|
|
||||||
|
|
||||||
static queries() {
|
|
||||||
return {
|
|
||||||
default: ['Behaving'],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
tick(elapsed) {
|
|
||||||
for (const {Behaving} of this.select('default')) {
|
|
||||||
Behaving.tick(elapsed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -69,14 +69,14 @@ export default class Colliders extends System {
|
||||||
const script = entity.Collider.collisionStartScriptInstance.clone();
|
const script = entity.Collider.collisionStartScriptInstance.clone();
|
||||||
script.context.intersections = intersections;
|
script.context.intersections = intersections;
|
||||||
script.context.other = other;
|
script.context.other = other;
|
||||||
entity.Ticking.add(script.ticker());
|
entity.Ticking.addTickingPromise(script.tickingPromise());
|
||||||
}
|
}
|
||||||
if (other.Collider.collisionStartScriptInstance) {
|
if (other.Collider.collisionStartScriptInstance) {
|
||||||
const script = other.Collider.collisionStartScriptInstance.clone();
|
const script = other.Collider.collisionStartScriptInstance.clone();
|
||||||
script.context.intersections = intersections
|
script.context.intersections = intersections
|
||||||
.map(([l, r]) => [r, l]);
|
.map(([l, r]) => [r, l]);
|
||||||
script.context.other = entity;
|
script.context.other = entity;
|
||||||
other.Ticking.add(script.ticker());
|
other.Ticking.addTickingPromise(script.tickingPromise());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const i in intersections) {
|
for (const i in intersections) {
|
||||||
|
@ -127,12 +127,12 @@ export default class Colliders extends System {
|
||||||
if (entity.Collider.collisionEndScriptInstance) {
|
if (entity.Collider.collisionEndScriptInstance) {
|
||||||
const script = entity.Collider.collisionEndScriptInstance.clone();
|
const script = entity.Collider.collisionEndScriptInstance.clone();
|
||||||
script.context.other = other;
|
script.context.other = other;
|
||||||
entity.Ticking.add(script.ticker());
|
entity.Ticking.addTickingPromise(script.tickingPromise());
|
||||||
}
|
}
|
||||||
if (other.Collider.collisionEndScriptInstance) {
|
if (other.Collider.collisionEndScriptInstance) {
|
||||||
const script = other.Collider.collisionEndScriptInstance.clone();
|
const script = other.Collider.collisionEndScriptInstance.clone();
|
||||||
script.context.other = entity;
|
script.context.other = entity;
|
||||||
other.Ticking.add(script.ticker());
|
other.Ticking.addTickingPromise(script.tickingPromise());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {System} from '@/ecs/index.js';
|
import {System} from '@/ecs/index.js';
|
||||||
|
|
||||||
export default class RunAnimations extends System {
|
export default class ControlMovement extends System {
|
||||||
|
|
||||||
static queries() {
|
static queries() {
|
||||||
return {
|
return {
|
||||||
|
@ -10,13 +10,13 @@ export default class RunAnimations extends System {
|
||||||
|
|
||||||
tick(elapsed) {
|
tick(elapsed) {
|
||||||
for (const {Sprite} of this.select('default')) {
|
for (const {Sprite} of this.select('default')) {
|
||||||
if (0 === Sprite.speed || !Sprite.isAnimating) {
|
if (0 === Sprite.speed) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Sprite.elapsed += elapsed / Sprite.speed;
|
Sprite.elapsed += elapsed / Sprite.speed;
|
||||||
while (Sprite.elapsed > 1) {
|
while (Sprite.elapsed > 1) {
|
||||||
Sprite.elapsed -= 1;
|
Sprite.elapsed -= 1;
|
||||||
Sprite.frame += 1;
|
Sprite.frame = (Sprite.frame + 1) % Sprite.frames;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import {LRUCache} from 'lru-cache';
|
import {LRUCache} from 'lru-cache';
|
||||||
|
|
||||||
import Ecs from '@/ecs/ecs.js';
|
import Ecs from '@/ecs/ecs.js';
|
||||||
import {withResolvers} from '@/util/promise.js';
|
|
||||||
|
|
||||||
const cache = new LRUCache({
|
const cache = new LRUCache({
|
||||||
max: 128,
|
max: 128,
|
||||||
|
@ -10,7 +9,11 @@ const cache = new LRUCache({
|
||||||
export default class ClientEcs extends Ecs {
|
export default class ClientEcs extends Ecs {
|
||||||
async readAsset(uri) {
|
async readAsset(uri) {
|
||||||
if (!cache.has(uri)) {
|
if (!cache.has(uri)) {
|
||||||
const {promise, resolve, reject} = withResolvers();
|
let promise, resolve, reject;
|
||||||
|
promise = new Promise((res, rej) => {
|
||||||
|
resolve = res;
|
||||||
|
reject = rej;
|
||||||
|
});
|
||||||
cache.set(uri, promise);
|
cache.set(uri, promise);
|
||||||
fetch(new URL(uri, window.location.origin))
|
fetch(new URL(uri, window.location.origin))
|
||||||
.then(async (response) => {
|
.then(async (response) => {
|
||||||
|
|
|
@ -16,12 +16,12 @@ export default function Devtools({
|
||||||
}) {
|
}) {
|
||||||
const [ecs] = useEcs();
|
const [ecs] = useEcs();
|
||||||
const [mainEntity] = useMainEntity();
|
const [mainEntity] = useMainEntity();
|
||||||
const [mainEntityJson, setMainEntityJson] = useState('');
|
const [mainEntityJson, setMainEntityJson] = useState({});
|
||||||
useEcsTick(() => {
|
useEcsTick(() => {
|
||||||
if (!ecs || !mainEntity) {
|
if (!ecs || !mainEntity) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setMainEntityJson(JSON.stringify(ecs.get(mainEntity), null, 2));
|
setMainEntityJson(ecs.get(mainEntity).toJSON());
|
||||||
}, [ecs, mainEntity]);
|
}, [ecs, mainEntity]);
|
||||||
return (
|
return (
|
||||||
<div className={styles.devtools}>
|
<div className={styles.devtools}>
|
||||||
|
@ -46,7 +46,7 @@ export default function Devtools({
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<pre><code><small>{mainEntityJson}</small></code></pre>
|
<pre><code><small>{JSON.stringify(mainEntityJson, null, 2)}</small></code></pre>
|
||||||
</div>
|
</div>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {useDebug} from '@/react/context/debug.js';
|
||||||
import {useMainEntity} from '@/react/context/main-entity.js';
|
import {useMainEntity} from '@/react/context/main-entity.js';
|
||||||
|
|
||||||
import Emitter from './emitter.jsx';
|
import Emitter from './emitter.jsx';
|
||||||
// import Light from './light.jsx';
|
import Light from './light.jsx';
|
||||||
import Sprite from './sprite.jsx';
|
import Sprite from './sprite.jsx';
|
||||||
|
|
||||||
function Aabb({color, width = 0.5, x0, y0, x1, y1, ...rest}) {
|
function Aabb({color, width = 0.5, x0, y0, x1, y1, ...rest}) {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import {Group, Layer} from '@pixi/layers';
|
import {Group, Layer} from '@pixi/layers';
|
||||||
import * as Lights from '@pixi/lights';
|
|
||||||
|
|
||||||
class LightLayer extends Layer {
|
class LightLayer extends Layer {
|
||||||
$$diffuseTexture;
|
$$diffuseTexture;
|
||||||
|
@ -43,16 +42,22 @@ class DeferredLighting {
|
||||||
|
|
||||||
export const deferredLighting = new DeferredLighting();
|
export const deferredLighting = new DeferredLighting();
|
||||||
|
|
||||||
export class AmbientLight extends Lights.AmbientLight {
|
let AmbientLight, PointLight;
|
||||||
constructor(...args) {
|
|
||||||
super(...args);
|
if ('undefined' !== typeof window) {
|
||||||
this.parentGroup = deferredLighting.lightGroup;
|
const Lights = await import('@pixi/lights');
|
||||||
|
AmbientLight = class AmbientLight extends Lights.AmbientLight {
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
this.parentGroup = deferredLighting.lightGroup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PointLight = class PointLight extends Lights.PointLight {
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
this.parentGroup = deferredLighting.lightGroup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PointLight extends Lights.PointLight {
|
export {AmbientLight, PointLight};
|
||||||
constructor(...args) {
|
|
||||||
super(...args);
|
|
||||||
this.parentGroup = deferredLighting.lightGroup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import Systems from '@/ecs/systems/index.js';
|
||||||
export default function createEcs(Ecs) {
|
export default function createEcs(Ecs) {
|
||||||
const ecs = new Ecs({Components, Systems});
|
const ecs = new Ecs({Components, Systems});
|
||||||
const defaultSystems = [
|
const defaultSystems = [
|
||||||
'Behave',
|
|
||||||
'PassTime',
|
'PassTime',
|
||||||
'Attract',
|
'Attract',
|
||||||
'ResetForces',
|
'ResetForces',
|
||||||
|
|
|
@ -94,40 +94,5 @@ export default async function createHomestead(id) {
|
||||||
Ticking: {},
|
Ticking: {},
|
||||||
VisibleAabb: {},
|
VisibleAabb: {},
|
||||||
});
|
});
|
||||||
const kitty = {
|
|
||||||
Behaving: {
|
|
||||||
routines: {
|
|
||||||
initial: '/assets/kitty/initial.js',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Collider: {
|
|
||||||
bodies: [
|
|
||||||
{
|
|
||||||
points: [
|
|
||||||
{x: -4, y: -4},
|
|
||||||
{x: 3, y: -4},
|
|
||||||
{x: 3, y: 3},
|
|
||||||
{x: -4, y: 3},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
Controlled: {},
|
|
||||||
Direction: {direction: 2},
|
|
||||||
Forces: {},
|
|
||||||
Position: {x: 250, y: 250},
|
|
||||||
Speed: {speed: 20},
|
|
||||||
Sprite: {
|
|
||||||
anchorX: 0.5,
|
|
||||||
anchorY: 0.7,
|
|
||||||
source: '/assets/kitty/kitty.json',
|
|
||||||
speed: 0.115,
|
|
||||||
},
|
|
||||||
Ticking: {},
|
|
||||||
VisibleAabb: {},
|
|
||||||
};
|
|
||||||
for (let i = 0; i < 10; ++i) {
|
|
||||||
entities.push(kitty);
|
|
||||||
}
|
|
||||||
return entities;
|
return entities;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,10 @@ export default async function createPlayer(id) {
|
||||||
bodies: [
|
bodies: [
|
||||||
{
|
{
|
||||||
points: [
|
points: [
|
||||||
{x: -4, y: -4},
|
{x: -8, y: -8},
|
||||||
{x: 3, y: -4},
|
{x: 7, y: -8},
|
||||||
{x: 3, y: 3},
|
{x: 7, y: 7},
|
||||||
{x: -4, y: 3},
|
{x: -8, y: 7},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -49,9 +49,10 @@ export default async function createPlayer(id) {
|
||||||
Sound: {},
|
Sound: {},
|
||||||
Sprite: {
|
Sprite: {
|
||||||
anchorX: 0.5,
|
anchorX: 0.5,
|
||||||
anchorY: 0.9,
|
anchorY: 0.8,
|
||||||
animation: 'moving:down',
|
animation: 'moving:down',
|
||||||
frame: 0,
|
frame: 0,
|
||||||
|
frames: 8,
|
||||||
source: '/assets/dude/dude.json',
|
source: '/assets/dude/dude.json',
|
||||||
speed: 0.115,
|
speed: 0.115,
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,7 +7,6 @@ import {
|
||||||
RESOLUTION,
|
RESOLUTION,
|
||||||
TPS,
|
TPS,
|
||||||
} from '@/util/constants.js';
|
} from '@/util/constants.js';
|
||||||
import {withResolvers} from '@/util/promise.js';
|
|
||||||
|
|
||||||
import createEcs from './create/ecs.js';
|
import createEcs from './create/ecs.js';
|
||||||
import createForest from './create/forest.js';
|
import createForest from './create/forest.js';
|
||||||
|
@ -49,7 +48,11 @@ export default class Engine {
|
||||||
}
|
}
|
||||||
async readAsset(uri) {
|
async readAsset(uri) {
|
||||||
if (!cache.has(uri)) {
|
if (!cache.has(uri)) {
|
||||||
const {promise, resolve, reject} = withResolvers();
|
let promise, resolve, reject;
|
||||||
|
promise = new Promise((res, rej) => {
|
||||||
|
resolve = res;
|
||||||
|
reject = rej;
|
||||||
|
});
|
||||||
cache.set(uri, promise);
|
cache.set(uri, promise);
|
||||||
server.readAsset(uri)
|
server.readAsset(uri)
|
||||||
.then(resolve)
|
.then(resolve)
|
||||||
|
@ -85,7 +88,7 @@ export default class Engine {
|
||||||
...updates,
|
...updates,
|
||||||
};
|
};
|
||||||
// remove from old ECS
|
// remove from old ECS
|
||||||
this.destroyImmediately(entity.id);
|
this.destroy(entity.id);
|
||||||
// load if necessary
|
// load if necessary
|
||||||
if (!engine.ecses[path]) {
|
if (!engine.ecses[path]) {
|
||||||
await engine.loadEcs(path);
|
await engine.loadEcs(path);
|
||||||
|
@ -227,7 +230,7 @@ export default class Engine {
|
||||||
const {entity, id} = connectedPlayer;
|
const {entity, id} = connectedPlayer;
|
||||||
const ecs = this.ecses[entity.Ecs.path];
|
const ecs = this.ecses[entity.Ecs.path];
|
||||||
await this.savePlayer(id, entity);
|
await this.savePlayer(id, entity);
|
||||||
ecs.destroyImmediately(entity.id);
|
ecs.destroy(entity.id);
|
||||||
this.connectedPlayers.delete(connection);
|
this.connectedPlayers.delete(connection);
|
||||||
this.incomingActions.delete(connection);
|
this.incomingActions.delete(connection);
|
||||||
}
|
}
|
||||||
|
@ -319,6 +322,7 @@ export default class Engine {
|
||||||
stop() {
|
stop() {
|
||||||
clearTimeout(this.handle);
|
clearTimeout(this.handle);
|
||||||
this.handle = undefined;
|
this.handle = undefined;
|
||||||
|
this.tick(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
tick(elapsed) {
|
tick(elapsed) {
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
import {settings} from '@pixi/core';
|
|
||||||
|
|
||||||
settings.ADAPTER = {
|
|
||||||
...settings.ADAPTER,
|
|
||||||
createCanvas: () => ({
|
|
||||||
getContext: () => undefined,
|
|
||||||
}),
|
|
||||||
};
|
|
|
@ -2,7 +2,6 @@ import {del, get, set} from 'idb-keyval';
|
||||||
|
|
||||||
import {encode} from '@/net/packets/index.js';
|
import {encode} from '@/net/packets/index.js';
|
||||||
import Server from '@/net/server.js';
|
import Server from '@/net/server.js';
|
||||||
import {withResolvers} from '@/util/promise.js';
|
|
||||||
|
|
||||||
import createEcs from './create/ecs.js';
|
import createEcs from './create/ecs.js';
|
||||||
import './create/forest.js';
|
import './create/forest.js';
|
||||||
|
@ -63,32 +62,41 @@ onmessage = async (event) => {
|
||||||
})();
|
})();
|
||||||
|
|
||||||
if (import.meta.hot) {
|
if (import.meta.hot) {
|
||||||
const before = withResolvers();
|
const createResolver = () => {
|
||||||
const promises = [before.promise];
|
let r;
|
||||||
|
const promise = new Promise((resolve) => {
|
||||||
|
r = resolve;
|
||||||
|
});
|
||||||
|
promise.resolve = r;
|
||||||
|
return promise;
|
||||||
|
};
|
||||||
|
const beforeResolver = createResolver();
|
||||||
|
const resolvers = [beforeResolver];
|
||||||
import.meta.hot.on('vite:beforeUpdate', async () => {
|
import.meta.hot.on('vite:beforeUpdate', async () => {
|
||||||
engine.stop();
|
engine.stop();
|
||||||
await engine.disconnectPlayer(0);
|
await engine.disconnectPlayer(0);
|
||||||
await engine.saveEcses();
|
await engine.saveEcses();
|
||||||
before.resolve();
|
beforeResolver.resolve();
|
||||||
});
|
});
|
||||||
import.meta.hot.accept('./engine.js');
|
import.meta.hot.accept('./engine.js');
|
||||||
import.meta.hot.accept('./create/player.js', async ({default: createPlayer}) => {
|
import.meta.hot.accept('./create/player.js', async ({default: createPlayer}) => {
|
||||||
const {promise, resolve} = withResolvers();
|
const resolver = createResolver();
|
||||||
promises.push(promise);
|
resolvers.push(resolver);
|
||||||
await before.promise;
|
await beforeResolver;
|
||||||
const oldPlayer = await engine.loadPlayer(0);
|
const oldPlayer = await engine.server.readJson('players/0');
|
||||||
const player = await createPlayer(0);
|
const buffer = await createPlayer(0);
|
||||||
|
const player = JSON.parse((new TextDecoder()).decode(buffer));
|
||||||
// Less jarring
|
// Less jarring
|
||||||
player.Ecs = oldPlayer.Ecs;
|
player.Ecs = oldPlayer.Ecs;
|
||||||
player.Direction = oldPlayer.Direction;
|
player.Direction = oldPlayer.Direction;
|
||||||
player.Position = oldPlayer.Position;
|
player.Position = oldPlayer.Position;
|
||||||
await engine.savePlayer(0, player);
|
await engine.server.writeData('players/0', (new TextEncoder()).encode(JSON.stringify(player)));
|
||||||
resolve();
|
resolver.resolve();
|
||||||
});
|
});
|
||||||
import.meta.hot.accept('./create/forest.js', async ({default: createForest}) => {
|
import.meta.hot.accept('./create/forest.js', async ({default: createForest}) => {
|
||||||
const {promise, resolve} = withResolvers();
|
const resolver = createResolver();
|
||||||
promises.push(promise);
|
resolvers.push(resolver);
|
||||||
await before.promise;
|
await beforeResolver;
|
||||||
delete engine.ecses['forests/0'];
|
delete engine.ecses['forests/0'];
|
||||||
await engine.server.removeData('forests/0');
|
await engine.server.removeData('forests/0');
|
||||||
const forest = createEcs(engine.Ecs);
|
const forest = createEcs(engine.Ecs);
|
||||||
|
@ -96,12 +104,12 @@ if (import.meta.hot) {
|
||||||
await forest.create(entity);
|
await forest.create(entity);
|
||||||
}
|
}
|
||||||
await engine.saveEcs('forests/0', forest);
|
await engine.saveEcs('forests/0', forest);
|
||||||
resolve();
|
resolver.resolve();
|
||||||
});
|
});
|
||||||
import.meta.hot.accept('./create/homestead.js', async ({default: createHomestead}) => {
|
import.meta.hot.accept('./create/homestead.js', async ({default: createHomestead}) => {
|
||||||
const {promise, resolve} = withResolvers();
|
const resolver = createResolver();
|
||||||
promises.push(promise);
|
resolvers.push(resolver);
|
||||||
await before.promise;
|
await beforeResolver;
|
||||||
delete engine.ecses['homesteads/0'];
|
delete engine.ecses['homesteads/0'];
|
||||||
await engine.server.removeData('homesteads/0');
|
await engine.server.removeData('homesteads/0');
|
||||||
const homestead = createEcs(engine.Ecs);
|
const homestead = createEcs(engine.Ecs);
|
||||||
|
@ -109,10 +117,10 @@ if (import.meta.hot) {
|
||||||
await homestead.create(entity);
|
await homestead.create(entity);
|
||||||
}
|
}
|
||||||
await engine.saveEcs('homesteads/0', homestead);
|
await engine.saveEcs('homesteads/0', homestead);
|
||||||
resolve();
|
resolver.resolve();
|
||||||
});
|
});
|
||||||
import.meta.hot.on('vite:afterUpdate', async () => {
|
import.meta.hot.on('vite:afterUpdate', async () => {
|
||||||
await Promise.all(promises);
|
await Promise.all(resolvers);
|
||||||
postMessage(encode({type: 'ConnectionStatus', payload: 'aborted'}));
|
postMessage(encode({type: 'ConnectionStatus', payload: 'aborted'}));
|
||||||
close();
|
close();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
export const CHUNK_SIZE = 32;
|
export const CHUNK_SIZE = 32;
|
||||||
|
|
||||||
export const CLIENT_LATENCY = 100;
|
export const CLIENT_LATENCY = 0;
|
||||||
|
|
||||||
export const CLIENT_PREDICTION = true;
|
export const CLIENT_PREDICTION = true;
|
||||||
|
|
||||||
|
@ -11,6 +11,6 @@ export const RESOLUTION = {
|
||||||
y: 450,
|
y: 450,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SERVER_LATENCY = 100;
|
export const SERVER_LATENCY = 0;
|
||||||
|
|
||||||
export const TPS = 60;
|
export const TPS = 60;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {Ticker} from '@/util/promise.js';
|
import TickingPromise from '@/util/ticking-promise.js';
|
||||||
|
|
||||||
export default function delta(object, properties) {
|
export default function delta(object, properties) {
|
||||||
const deltas = {};
|
const deltas = {};
|
||||||
|
@ -12,7 +12,7 @@ export default function delta(object, properties) {
|
||||||
deltas[key] = delta;
|
deltas[key] = delta;
|
||||||
}
|
}
|
||||||
let stop;
|
let stop;
|
||||||
const promise = new Ticker(
|
const promise = new TickingPromise(
|
||||||
(resolve) => {
|
(resolve) => {
|
||||||
stop = resolve;
|
stop = resolve;
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {Ticker, withResolvers} from '@/util/promise.js';
|
import TickingPromise from '@/util/ticking-promise.js';
|
||||||
|
|
||||||
const Modulators = {
|
const Modulators = {
|
||||||
flat: () => 0.5,
|
flat: () => 0.5,
|
||||||
|
@ -35,7 +35,9 @@ export default function lfo(object, properties) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
oscillator.low = oscillator.median - oscillator.magnitude / 2;
|
oscillator.low = oscillator.median - oscillator.magnitude / 2;
|
||||||
({promise: oscillator.promise, resolve: oscillator.stop} = withResolvers());
|
oscillator.promise = new Promise((resolve) => {
|
||||||
|
oscillator.stop = resolve;
|
||||||
|
});
|
||||||
oscillator.promise.then(() => {
|
oscillator.promise.then(() => {
|
||||||
delete oscillators[key];
|
delete oscillators[key];
|
||||||
});
|
});
|
||||||
|
@ -43,7 +45,7 @@ export default function lfo(object, properties) {
|
||||||
oscillators[key] = oscillator;
|
oscillators[key] = oscillator;
|
||||||
}
|
}
|
||||||
let stop;
|
let stop;
|
||||||
const promise = new Ticker(
|
const promise = new TickingPromise(
|
||||||
(resolve) => {
|
(resolve) => {
|
||||||
stop = resolve;
|
stop = resolve;
|
||||||
Promise.all(promises).then(resolve);
|
Promise.all(promises).then(resolve);
|
||||||
|
|
|
@ -121,13 +121,6 @@ export function createRandom(seed = 0) {
|
||||||
return alea(seed);
|
return alea(seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const directionToVector = [
|
|
||||||
{x: 0, y: -1},
|
|
||||||
{x: 1, y: 0},
|
|
||||||
{x: 0, y: 1},
|
|
||||||
{x: -1, y: 0},
|
|
||||||
];
|
|
||||||
|
|
||||||
export function distance({x: lx, y: ly}, {x: rx, y: ry}) {
|
export function distance({x: lx, y: ly}, {x: rx, y: ry}) {
|
||||||
const xd = lx - rx;
|
const xd = lx - rx;
|
||||||
const yd = ly - ry;
|
const yd = ly - ry;
|
||||||
|
@ -253,6 +246,13 @@ export function isCollinear({x: ax, y: ay}, {x: bx, y: by}, {x: cx, y: cy}) {
|
||||||
return (ay - by) * (ax - cx) === (ay - cy) * (ax - bx);
|
return (ay - by) * (ax - cx) === (ay - cy) * (ax - bx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const directionToVector = [
|
||||||
|
{x: 0, y: -1},
|
||||||
|
{x: 1, y: 0},
|
||||||
|
{x: 0, y: 1},
|
||||||
|
{x: -1, y: 0},
|
||||||
|
];
|
||||||
|
|
||||||
export function ortho(points, k = {x: 1, y: 1}) {
|
export function ortho(points, k = {x: 1, y: 1}) {
|
||||||
if (points.length < 4) {
|
if (points.length < 4) {
|
||||||
throw new TypeError('Math.ortho(): points.length < 4');
|
throw new TypeError('Math.ortho(): points.length < 4');
|
||||||
|
|
|
@ -2,10 +2,10 @@ import {parse as acornParse} from 'acorn';
|
||||||
import {LRUCache} from 'lru-cache';
|
import {LRUCache} from 'lru-cache';
|
||||||
|
|
||||||
import Sandbox from '@/astride/sandbox.js';
|
import Sandbox from '@/astride/sandbox.js';
|
||||||
|
import TickingPromise from '@/util/ticking-promise.js';
|
||||||
import delta from '@/util/delta.js';
|
import delta from '@/util/delta.js';
|
||||||
import lfo from '@/util/lfo.js';
|
import lfo from '@/util/lfo.js';
|
||||||
import * as MathUtil from '@/util/math.js';
|
import * as MathUtil from '@/util/math.js';
|
||||||
import * as PromiseUtil from '@/util/promise.js';
|
|
||||||
import transition from '@/util/transition.js';
|
import transition from '@/util/transition.js';
|
||||||
|
|
||||||
function parse(code, options = {}) {
|
function parse(code, options = {}) {
|
||||||
|
@ -43,7 +43,7 @@ export default class Script {
|
||||||
delta,
|
delta,
|
||||||
lfo,
|
lfo,
|
||||||
Math: MathUtil,
|
Math: MathUtil,
|
||||||
Promise: PromiseUtil,
|
Promise,
|
||||||
transition,
|
transition,
|
||||||
wait: (seconds) => (
|
wait: (seconds) => (
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
|
@ -95,7 +95,7 @@ export default class Script {
|
||||||
|
|
||||||
tick(elapsed, resolve, reject) {
|
tick(elapsed, resolve, reject) {
|
||||||
if (this.promise) {
|
if (this.promise) {
|
||||||
if (this.promise instanceof PromiseUtil.Ticker) {
|
if (this.promise instanceof TickingPromise) {
|
||||||
this.promise.tick(elapsed);
|
this.promise.tick(elapsed);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -106,12 +106,10 @@ export default class Script {
|
||||||
if (async) {
|
if (async) {
|
||||||
this.promise = value;
|
this.promise = value;
|
||||||
value
|
value
|
||||||
.catch(reject ? reject : () => {})
|
.catch(reject)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (done) {
|
if (done) {
|
||||||
if (resolve) {
|
resolve();
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
@ -120,16 +118,14 @@ export default class Script {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (done) {
|
if (done) {
|
||||||
if (resolve) {
|
resolve();
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ticker() {
|
tickingPromise() {
|
||||||
return new PromiseUtil.Ticker(
|
return new TickingPromise(
|
||||||
() => {},
|
() => {},
|
||||||
(elapsed, resolve, reject) => {
|
(elapsed, resolve, reject) => {
|
||||||
this.tick(elapsed, resolve, reject);
|
this.tick(elapsed, resolve, reject);
|
||||||
|
@ -137,18 +133,18 @@ export default class Script {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ticker(code, context = {}) {
|
static tickingPromise(code, context = {}) {
|
||||||
let ticker;
|
let tickingPromise;
|
||||||
return new PromiseUtil.Ticker(
|
return new TickingPromise(
|
||||||
(resolve) => {
|
(resolve) => {
|
||||||
this.fromCode(code, context)
|
this.fromCode(code, context)
|
||||||
.then((script) => {
|
.then((script) => {
|
||||||
ticker = script.ticker();
|
tickingPromise = script.tickingPromise();
|
||||||
resolve(ticker);
|
resolve(tickingPromise);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
(elapsed) => {
|
(elapsed) => {
|
||||||
ticker?.tick?.(elapsed);
|
tickingPromise?.tick?.(elapsed);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,4 @@
|
||||||
export const all = Promise.all.bind(Promise);
|
export default class TickingPromise extends Promise {
|
||||||
export const allSettled = Promise.allSettled.bind(Promise);
|
|
||||||
export const any = Promise.any.bind(Promise);
|
|
||||||
export const race = Promise.race.bind(Promise);
|
|
||||||
export const reject = Promise.reject.bind(Promise);
|
|
||||||
export const resolve = Promise.resolve.bind(Promise);
|
|
||||||
|
|
||||||
export function withResolvers() {
|
|
||||||
let resolve, reject, promise = new Promise((res, rej) => {
|
|
||||||
resolve = res;
|
|
||||||
reject = rej;
|
|
||||||
});
|
|
||||||
return {promise, reject, resolve};
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Ticker extends Promise {
|
|
||||||
|
|
||||||
constructor(executor, ticker) {
|
constructor(executor, ticker) {
|
||||||
let _reject;
|
let _reject;
|
||||||
|
@ -31,22 +16,22 @@ export class Ticker extends Promise {
|
||||||
}
|
}
|
||||||
|
|
||||||
static all(promises) {
|
static all(promises) {
|
||||||
const tickers = [];
|
const tickingPromises = [];
|
||||||
for (let i = 0; i < promises.length; i++) {
|
for (let i = 0; i < promises.length; i++) {
|
||||||
const promise = promises[i];
|
const promise = promises[i];
|
||||||
if (promise instanceof Ticker) {
|
if (promise instanceof TickingPromise) {
|
||||||
tickers.push(promise);
|
tickingPromises.push(promise);
|
||||||
// After resolution, stop ticking the promise.
|
// After resolution, stop ticking the promise.
|
||||||
promise.then(() => {
|
promise.then(() => {
|
||||||
tickers.splice(tickers.indexOf(promise), 1);
|
tickingPromises.splice(tickingPromises.indexOf(promise), 1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* v8 ignore next 3 */
|
/* v8 ignore next 3 */
|
||||||
if (0 === tickers.length) {
|
if (0 === tickingPromises.length) {
|
||||||
return super.all(promises);
|
return super.all(promises);
|
||||||
}
|
}
|
||||||
return new Ticker(
|
return new TickingPromise(
|
||||||
(resolve, reject) => {
|
(resolve, reject) => {
|
||||||
super.all(promises)
|
super.all(promises)
|
||||||
.then(resolve)
|
.then(resolve)
|
||||||
|
@ -54,8 +39,8 @@ export class Ticker extends Promise {
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
},
|
},
|
||||||
(elapsed) => {
|
(elapsed) => {
|
||||||
for (let i = 0; i < tickers.length; i++) {
|
for (let i = 0; i < tickingPromises.length; i++) {
|
||||||
tickers[i].tick(elapsed);
|
tickingPromises[i].tick(elapsed);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
|
@ -1,17 +1,17 @@
|
||||||
import {expect, test} from 'vitest';
|
import {expect, test} from 'vitest';
|
||||||
|
|
||||||
import {Ticker} from './promise.js';
|
import TickingPromise from './ticking-promise.js';
|
||||||
|
|
||||||
test('runs executor', async () => {
|
test('runs executor', async () => {
|
||||||
expect(
|
expect(
|
||||||
await new Ticker((resolve) => {
|
await new TickingPromise((resolve) => {
|
||||||
resolve(32);
|
resolve(32);
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.to.equal(32);
|
.to.equal(32);
|
||||||
expect(
|
expect(
|
||||||
async () => {
|
async () => {
|
||||||
await new Ticker((resolve, reject) => {
|
await new TickingPromise((resolve, reject) => {
|
||||||
reject(new Error(''));
|
reject(new Error(''));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ test('runs executor', async () => {
|
||||||
test('ticks and resolves', async () => {
|
test('ticks and resolves', async () => {
|
||||||
let done = false;
|
let done = false;
|
||||||
let e = 0;
|
let e = 0;
|
||||||
const tp = new Ticker(undefined, (elapsed, resolve) => {
|
const tp = new TickingPromise(undefined, (elapsed, resolve) => {
|
||||||
e += elapsed;
|
e += elapsed;
|
||||||
if (1 === e) {
|
if (1 === e) {
|
||||||
done = true;
|
done = true;
|
||||||
|
@ -49,7 +49,7 @@ test('ticks and resolves', async () => {
|
||||||
|
|
||||||
test('ticks and rejects', async () => {
|
test('ticks and rejects', async () => {
|
||||||
let caught = false;
|
let caught = false;
|
||||||
const tp = new Ticker(undefined, (elapsed, resolve, reject) => {
|
const tp = new TickingPromise(undefined, (elapsed, resolve, reject) => {
|
||||||
reject(new Error());
|
reject(new Error());
|
||||||
});
|
});
|
||||||
tp.catch(() => {
|
tp.catch(() => {
|
||||||
|
@ -66,21 +66,21 @@ test('ticks and rejects', async () => {
|
||||||
test('handles all', async () => {
|
test('handles all', async () => {
|
||||||
let done = 0;
|
let done = 0;
|
||||||
let e1 = 0, e2 = 0;
|
let e1 = 0, e2 = 0;
|
||||||
const tp1 = new Ticker(undefined, (elapsed, resolve) => {
|
const tp1 = new TickingPromise(undefined, (elapsed, resolve) => {
|
||||||
e1 += elapsed;
|
e1 += elapsed;
|
||||||
if (1 === e1) {
|
if (1 === e1) {
|
||||||
done += 1;
|
done += 1;
|
||||||
resolve(16);
|
resolve(16);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const tp2 = new Ticker(undefined, (elapsed, resolve) => {
|
const tp2 = new TickingPromise(undefined, (elapsed, resolve) => {
|
||||||
e2 += elapsed;
|
e2 += elapsed;
|
||||||
if (2 === e2) {
|
if (2 === e2) {
|
||||||
done += 1;
|
done += 1;
|
||||||
resolve(32);
|
resolve(32);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const tpa = Ticker.all([
|
const tpa = TickingPromise.all([
|
||||||
Promise.resolve(8),
|
Promise.resolve(8),
|
||||||
tp1,
|
tp1,
|
||||||
tp2,
|
tp2,
|
|
@ -1,4 +1,4 @@
|
||||||
import {Ticker} from '@/util/promise.js';
|
import TickingPromise from '@/util/ticking-promise.js';
|
||||||
|
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
const Easing = {
|
const Easing = {
|
||||||
|
@ -152,7 +152,7 @@ export default function transition(object, properties) {
|
||||||
transitions[key] = transition;
|
transitions[key] = transition;
|
||||||
}
|
}
|
||||||
let stop;
|
let stop;
|
||||||
const promise = new Ticker(
|
const promise = new TickingPromise(
|
||||||
(resolve) => {
|
(resolve) => {
|
||||||
stop = resolve;
|
stop = resolve;
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
entity.Direction.direction = Math.floor(Math.random() * 4);
|
|
||||||
|
|
||||||
const map = {0: 'moveUp', 1: 'moveRight', 2: 'moveDown', 3: 'moveLeft'};
|
|
||||||
entity.Controlled[map[entity.Direction.direction]] = 1;
|
|
||||||
await wait(0.25 + Math.random() * 2.25);
|
|
||||||
entity.Controlled[map[entity.Direction.direction]] = 0;
|
|
||||||
|
|
||||||
entity.Sprite.isAnimating = 0;
|
|
||||||
|
|
||||||
await wait(1 + Math.random() * 3);
|
|
||||||
|
|
||||||
entity.Direction.direction = Math.floor(Math.random() * 4);
|
|
||||||
|
|
||||||
await wait(0.5 + Math.random() * 2.5);
|
|
||||||
|
|
||||||
entity.Sprite.isAnimating = 1;
|
|
|
@ -1,263 +0,0 @@
|
||||||
{
|
|
||||||
"animations": {
|
|
||||||
"idle:up": [
|
|
||||||
"kitty/0"
|
|
||||||
],
|
|
||||||
"idle:right": [
|
|
||||||
"kitty/3"
|
|
||||||
],
|
|
||||||
"idle:down": [
|
|
||||||
"kitty/6"
|
|
||||||
],
|
|
||||||
"idle:left": [
|
|
||||||
"kitty/9"
|
|
||||||
],
|
|
||||||
"moving:up": [
|
|
||||||
"kitty/0",
|
|
||||||
"kitty/1",
|
|
||||||
"kitty/2"
|
|
||||||
],
|
|
||||||
"moving:right": [
|
|
||||||
"kitty/3",
|
|
||||||
"kitty/4",
|
|
||||||
"kitty/5"
|
|
||||||
],
|
|
||||||
"moving:down": [
|
|
||||||
"kitty/6",
|
|
||||||
"kitty/7",
|
|
||||||
"kitty/8"
|
|
||||||
],
|
|
||||||
"moving:left": [
|
|
||||||
"kitty/9",
|
|
||||||
"kitty/10",
|
|
||||||
"kitty/11"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"frames": {
|
|
||||||
"kitty/0": {
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kitty/1": {
|
|
||||||
"frame": {
|
|
||||||
"x": 16,
|
|
||||||
"y": 0,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kitty/2": {
|
|
||||||
"frame": {
|
|
||||||
"x": 32,
|
|
||||||
"y": 0,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kitty/3": {
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 16,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kitty/4": {
|
|
||||||
"frame": {
|
|
||||||
"x": 16,
|
|
||||||
"y": 16,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kitty/5": {
|
|
||||||
"frame": {
|
|
||||||
"x": 32,
|
|
||||||
"y": 16,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kitty/6": {
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 32,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kitty/7": {
|
|
||||||
"frame": {
|
|
||||||
"x": 16,
|
|
||||||
"y": 32,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kitty/8": {
|
|
||||||
"frame": {
|
|
||||||
"x": 32,
|
|
||||||
"y": 32,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kitty/9": {
|
|
||||||
"frame": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 48,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kitty/10": {
|
|
||||||
"frame": {
|
|
||||||
"x": 16,
|
|
||||||
"y": 48,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"kitty/11": {
|
|
||||||
"frame": {
|
|
||||||
"x": 32,
|
|
||||||
"y": 48,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"spriteSourceSize": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
},
|
|
||||||
"sourceSize": {
|
|
||||||
"w": 16,
|
|
||||||
"h": 16
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"meta": {
|
|
||||||
"format": "RGBA8888",
|
|
||||||
"image": "./kitty.png",
|
|
||||||
"scale": 1,
|
|
||||||
"size": {
|
|
||||||
"w": 48,
|
|
||||||
"h": 64
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 884 B |
|
@ -48,61 +48,71 @@ for (let i = 0; i < 10; ++i) {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
tomato.Ticking.add(
|
const l = lfo(
|
||||||
Promise.Ticker.all([
|
d.deltas.y,
|
||||||
d.promise,
|
{
|
||||||
lfo(
|
delta: {
|
||||||
d.deltas.y,
|
count: 1,
|
||||||
{
|
frequency: 0.5,
|
||||||
delta: {
|
magnitude: 64,
|
||||||
count: 1,
|
median: 0,
|
||||||
frequency: 0.5,
|
offset: -0.5,
|
||||||
magnitude: 64,
|
},
|
||||||
median: 0,
|
},
|
||||||
offset: -0.5,
|
)
|
||||||
},
|
const ls = lfo(
|
||||||
|
tomato.Sprite,
|
||||||
|
{
|
||||||
|
scaleX: {
|
||||||
|
count: 1,
|
||||||
|
frequency: 0.5,
|
||||||
|
magnitude: 0.333,
|
||||||
|
median: 0.333,
|
||||||
|
elapsed: 0.25,
|
||||||
|
offset: -0.5,
|
||||||
|
},
|
||||||
|
scaleY: {
|
||||||
|
count: 1,
|
||||||
|
frequency: 0.5,
|
||||||
|
magnitude: 0.333,
|
||||||
|
median: 0.333,
|
||||||
|
elapsed: 0.25,
|
||||||
|
offset: -0.5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
tomato.Ticking.addTickingPromise(
|
||||||
|
d.promise,
|
||||||
|
);
|
||||||
|
tomato.Ticking.addTickingPromise(
|
||||||
|
l.promise,
|
||||||
|
);
|
||||||
|
tomato.Ticking.addTickingPromise(
|
||||||
|
ls.promise,
|
||||||
|
);
|
||||||
|
|
||||||
|
tomato.Ticking.addTickingPromise(
|
||||||
|
delta(
|
||||||
|
tomato.Position,
|
||||||
|
{
|
||||||
|
x: {
|
||||||
|
duration: 0.5,
|
||||||
|
delta: (12 * x) + Math.random() * 8,
|
||||||
},
|
},
|
||||||
).promise,
|
},
|
||||||
lfo(
|
).promise,
|
||||||
tomato.Sprite,
|
);
|
||||||
{
|
tomato.Ticking.addTickingPromise(
|
||||||
scaleX: {
|
delta(
|
||||||
count: 1,
|
tomato.Position,
|
||||||
frequency: 0.5,
|
{
|
||||||
magnitude: 0.333,
|
y: {
|
||||||
median: 0.333,
|
duration: 0.5,
|
||||||
elapsed: 0.25,
|
delta: (12 * y) + Math.random() * 8,
|
||||||
offset: -0.5,
|
|
||||||
},
|
|
||||||
scaleY: {
|
|
||||||
count: 1,
|
|
||||||
frequency: 0.5,
|
|
||||||
magnitude: 0.333,
|
|
||||||
median: 0.333,
|
|
||||||
elapsed: 0.25,
|
|
||||||
offset: -0.5,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
).promise,
|
},
|
||||||
delta(
|
).promise,
|
||||||
tomato.Position,
|
|
||||||
{
|
|
||||||
x: {
|
|
||||||
duration: 0.5,
|
|
||||||
delta: (12 * x) + Math.random() * 8,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
).promise,
|
|
||||||
delta(
|
|
||||||
tomato.Position,
|
|
||||||
{
|
|
||||||
y: {
|
|
||||||
duration: 0.5,
|
|
||||||
delta: (12 * y) + Math.random() * 8,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
).promise,
|
|
||||||
]),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,8 +44,6 @@ let websocketBuilt = false;
|
||||||
|
|
||||||
const remixHandler = createRequestHandler({
|
const remixHandler = createRequestHandler({
|
||||||
build: async () => {
|
build: async () => {
|
||||||
// patch pixi server context
|
|
||||||
import('./app/server/pixi-context.js');
|
|
||||||
const ssr = await (
|
const ssr = await (
|
||||||
viteDevServer
|
viteDevServer
|
||||||
? viteDevServer.ssrLoadModule('virtual:remix/server-build')
|
? viteDevServer.ssrLoadModule('virtual:remix/server-build')
|
||||||
|
|
|
@ -25,11 +25,6 @@ else {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
esbuild: {
|
|
||||||
supported: {
|
|
||||||
'top-level-await': true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins,
|
plugins,
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: [
|
alias: [
|
||||||
|
@ -46,7 +41,4 @@ export default defineConfig({
|
||||||
cert: readFileSync(`${cacheDirectory}/localhost.pem`),
|
cert: readFileSync(`${cacheDirectory}/localhost.pem`),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
worker: {
|
|
||||||
format: 'es',
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user