Skip to content

Instantly share code, notes, and snippets.

@bcolloran
Created June 12, 2022 19:39
Show Gist options
  • Save bcolloran/a58866b3633aadb0aff76d9feb781e11 to your computer and use it in GitHub Desktop.
Save bcolloran/a58866b3633aadb0aff76d9feb781e11 to your computer and use it in GitHub Desktop.
import * as bit from "bitecs";
type ComponentBundle = { [componentName: string]: bit.ComponentType<any> };
type NumProxy<T> = { [key in keyof T]: number };
export function makeCmpProxyForEnt<T>(cmp: T, eid: number) {
const getterSetterProps = Object.fromEntries(
Object.entries(cmp).map(([k, v]) => [
k,
{
get() {
return v[eid];
},
set(value: number) {
v[eid] = value;
},
},
])
);
const prox = <NumProxy<T>>Object.defineProperties({}, getterSetterProps);
return prox;
}
export function makeCmpProxy<T>(cmp: T) {
let eid = 0;
const setProxEid = (newEid: number) => {
eid = newEid;
};
const getterSetterProps = Object.fromEntries(
Object.entries(cmp).map(([k, v]) => [
k,
{
get() {
return v[eid];
},
set(value: number) {
v[eid] = value;
},
},
])
);
const prox = <NumProxy<T>>Object.defineProperties({}, getterSetterProps);
return [prox, setProxEid] as const;
}
type BundleProxy<T> = { [key in keyof T]: NumProxy<T[key]> };
export function makeBundleProxy<T extends ComponentBundle>(cmpBundle: T) {
const bundleProx: any = {};
const eidSetters: ((eid: number) => void)[] = [];
Object.entries(cmpBundle).forEach(([k, cmp]) => {
const [prox, eidSetter] = makeCmpProxy(cmp);
bundleProx[k] = prox;
eidSetters.push(eidSetter);
});
const setProxEid = (newEid: number) => {
eidSetters.forEach((eidSetter) => eidSetter(newEid));
};
return [<BundleProxy<T>>bundleProx, setProxEid] as const;
}
type BundleMutatorFn<T> = (bundle: {
[key in keyof T]: NumProxy<T[key]>;
}) => void;
export function createComponentBundleForEachSystem<T extends ComponentBundle>(
cmpBundle: T,
bundleMutator: BundleMutatorFn<T>
): bit.System {
const query = bit.defineQuery(Object.values(cmpBundle));
const [prox, eidSetter] = makeBundleProxy(cmpBundle);
return function (world) {
const eids = query(world);
for (let eid of eids) {
eidSetter(eid);
bundleMutator(prox);
}
return world;
};
}
const vec2_f32 = { x: bit.Types.f32, y: bit.Types.f32 };
const size2_i16 = { width: bit.Types.i16, height: bit.Types.i16 };
const index2_i16 = { i: bit.Types.i16, j: bit.Types.i16 };
const Position = bit.defineComponent(vec2_f32);
const Velocity = bit.defineComponent(vec2_f32);
const GridIndex = bit.defineComponent(index2_i16);
const Size = bit.defineComponent(size2_i16);
createComponentBundleForEachSystem(
{ pos: Position, vel: Velocity, GridIndex, Size},
(ent) => {
ent.pos.x += ent.vel.y
ent.GridIndex.j
ent.Size.height
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment