feat: real visible AABB

This commit is contained in:
cha0s 2024-07-02 12:00:12 -05:00
parent 5db0478b19
commit 183c8254a2
9 changed files with 81 additions and 55 deletions

View File

@ -3,6 +3,9 @@ import Component from '@/ecs/component.js';
import vector2d from "./helpers/vector-2d"; import vector2d from "./helpers/vector-2d";
export default class Sprite extends Component { export default class Sprite extends Component {
async load(instance) {
instance.$$sourceJson = await this.ecs.readJson(instance.source);
}
static properties = { static properties = {
anchor: vector2d('float32', {x: 0.5, y: 0.5}), anchor: vector2d('float32', {x: 0.5, y: 0.5}),
animation: {type: 'string'}, animation: {type: 'string'},

View File

@ -9,12 +9,24 @@ export default class CalculateAabbs extends System {
} }
tick() { tick() {
for (const {Position: {x, y}, VisibleAabb} of this.ecs.changed(['Position'])) { for (const entity of this.ecs.changed(['Position'])) {
const {Position: {x, y}, Sprite, VisibleAabb} = entity;
if (VisibleAabb) { if (VisibleAabb) {
VisibleAabb.x0 = x - 32; let size = undefined;
VisibleAabb.x1 = x + 32; if (Sprite) {
VisibleAabb.y0 = y - 32; const frame = Sprite.animation
VisibleAabb.y1 = y + 32; ? Sprite.$$sourceJson.animations[Sprite.animation][Sprite.frame]
: '';
size = Sprite.$$sourceJson.frames[frame].sourceSize;
}
/* v8 ignore next 3 */
if (!size) {
throw new Error(`no size for aabb for entity ${entity.id}(${JSON.stringify(entity.toJSON(), null, 2)})`);
}
VisibleAabb.x0 = x - ((size.w ) * (Sprite.anchor.x));
VisibleAabb.x1 = x + ((size.w ) * (1 - Sprite.anchor.x));
VisibleAabb.y0 = y - ((size.h ) * (Sprite.anchor.y));
VisibleAabb.y1 = y + ((size.h ) * (1 - Sprite.anchor.y));
} }
} }
} }

View File

@ -15,6 +15,7 @@ export default class Engine {
connections = []; connections = [];
connectedPlayers = new Map(); connectedPlayers = new Map();
connectingPlayers = [];
ecses = {}; ecses = {};
frame = 0; frame = 0;
handle; handle;
@ -53,7 +54,7 @@ export default class Engine {
}); });
} }
acceptActions() { async acceptActions() {
for (const [ for (const [
entity, entity,
payload, payload,
@ -103,21 +104,28 @@ export default class Engine {
} }
async connectPlayer(connection, id) { async connectPlayer(connection, id) {
const entityJson = await this.loadPlayer(id); this.connectingPlayers.push([connection, id]);
if (!this.ecses[entityJson.Ecs.path]) { }
await this.loadEcs(entityJson.Ecs.path);
async connectPlayers() {
for (const [connection, id] of this.connectingPlayers) {
const entityJson = await this.loadPlayer(id);
if (!this.ecses[entityJson.Ecs.path]) {
await this.loadEcs(entityJson.Ecs.path);
}
const ecs = this.ecses[entityJson.Ecs.path];
const entity = await ecs.create(entityJson);
this.connections.push(connection);
this.connectedPlayers.set(
connection,
{
entity: ecs.get(entity),
id,
memory: new Set(),
},
);
} }
const ecs = this.ecses[entityJson.Ecs.path]; this.connectingPlayers = [];
const entity = await ecs.create(entityJson);
this.connections.push(connection);
this.connectedPlayers.set(
connection,
{
entity: ecs.get(entity),
id,
memory: new Set(),
},
);
} }
createEcs() { createEcs() {
@ -146,7 +154,7 @@ export default class Engine {
Position: {x: 100, y: 100}, Position: {x: 100, y: 100},
Sprite: { Sprite: {
anchor: {x: 0.5, y: 0.8}, anchor: {x: 0.5, y: 0.8},
source: '/assets/shit-shack/shit-shack.png', source: '/assets/shit-shack/shit-shack.json',
}, },
VisibleAabb: {}, VisibleAabb: {},
}); });
@ -290,19 +298,22 @@ export default class Engine {
} }
start() { start() {
this.handle = setInterval(() => { const loop = async () => {
await this.connectPlayers();
await this.acceptActions();
const elapsed = (Date.now() - this.last) / 1000; const elapsed = (Date.now() - this.last) / 1000;
this.last = Date.now(); this.last = Date.now();
this.acceptActions();
this.tick(elapsed); this.tick(elapsed);
this.update(elapsed); this.update(elapsed);
this.setClean(); this.setClean();
this.frame += 1; this.frame += 1;
}, 1000 / TPS); this.handle = setTimeout(loop, 1000 / TPS);
};
loop();
} }
stop() { stop() {
clearInterval(this.handle); clearTimeout(this.handle);
this.handle = undefined; this.handle = undefined;
} }

View File

@ -34,6 +34,9 @@ export default function Entities({entities}) {
}, [entities, ecs, mainEntity]); }, [entities, ecs, mainEntity]);
const renderables = []; const renderables = [];
for (const id in entities) { for (const id in entities) {
if ('1' === id) {
continue;
}
const isHighlightedInteraction = id == willInteractWith; const isHighlightedInteraction = id == willInteractWith;
renderables.push( renderables.push(
<Entity <Entity

View File

@ -6,6 +6,21 @@ import {useDebug} from '@/context/debug.js';
import Emitter from './emitter.jsx'; import Emitter from './emitter.jsx';
import Sprite from './sprite.jsx'; import Sprite from './sprite.jsx';
function VisibleAabb({x0, y0, x1, y1}) {
const draw = useCallback((g) => {
g.clear();
g.lineStyle(0.5, 0xff00ff);
g.moveTo(-0.25, -0.25);
g.lineTo(x1 - x0, 0);
g.lineTo(x1 - x0, y1 - y0);
g.lineTo(0, y1 - y0);
g.lineTo(0, 0);
}, [x0, x1, y0, y1]);
return (
<Graphics draw={draw} x={x0} y={y0} />
);
}
function Crosshair({x, y}) { function Crosshair({x, y}) {
const draw = useCallback((g) => { const draw = useCallback((g) => {
g.clear(); g.clear();
@ -52,6 +67,14 @@ function Entity({entity, ...rest}) {
{debug && entity.Position && ( {debug && entity.Position && (
<Crosshair x={entity.Position.x} y={entity.Position.y} /> <Crosshair x={entity.Position.x} y={entity.Position.y} />
)} )}
{debug && (
<VisibleAabb
x0={entity.VisibleAabb.x0}
x1={entity.VisibleAabb.x1}
y0={entity.VisibleAabb.y0}
y1={entity.VisibleAabb.y1}
/>
)}
</Container> </Container>
); );
} }

View File

@ -8,12 +8,11 @@ export default function Sprite({entity, ...rest}) {
return false; return false;
} }
let texture; let texture;
if (asset.textures) { if (asset.data.animations) {
const animation = asset.animations[entity.Sprite.animation] texture = asset.animations[entity.Sprite.animation][entity.Sprite.frame];
texture = animation[entity.Sprite.frame];
} }
else { else {
texture = asset; texture = asset.textures[''];
} }
return ( return (
<PixiSprite <PixiSprite

25
package-lock.json generated
View File

@ -47,7 +47,6 @@
"eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react": "^7.33.2", "eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"image-size": "^1.1.1",
"storybook": "^8.1.6", "storybook": "^8.1.6",
"vite": "^5.1.0", "vite": "^5.1.0",
"vitest": "^1.6.0" "vitest": "^1.6.0"
@ -11305,21 +11304,6 @@
"node": ">= 4" "node": ">= 4"
} }
}, },
"node_modules/image-size": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz",
"integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==",
"dev": true,
"dependencies": {
"queue": "6.0.2"
},
"bin": {
"image-size": "bin/image-size.js"
},
"engines": {
"node": ">=16.x"
}
},
"node_modules/import-fresh": { "node_modules/import-fresh": {
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@ -15161,15 +15145,6 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/queue": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
"integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
"dev": true,
"dependencies": {
"inherits": "~2.0.3"
}
},
"node_modules/queue-microtask": { "node_modules/queue-microtask": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",

View File

@ -54,7 +54,6 @@
"eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react": "^7.33.2", "eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"image-size": "^1.1.1",
"storybook": "^8.1.6", "storybook": "^8.1.6",
"vite": "^5.1.0", "vite": "^5.1.0",
"vitest": "^1.6.0" "vitest": "^1.6.0"

View File

@ -0,0 +1 @@
{"frames":{"":{"frame":{"x":0,"y":0,"w":110,"h":102},"spriteSourceSize":{"x":0,"y":0,"w":110,"h":102},"sourceSize":{"w":110,"h":102}}},"meta":{"format":"RGBA8888","image":"./shit-shack.png","scale":1,"size":{"w":110,"h":102}}}