refactor: engine

This commit is contained in:
cha0s 2024-06-14 12:05:02 -05:00
parent 0685243b7b
commit 6a7aa68002
7 changed files with 76 additions and 68 deletions

View File

@ -0,0 +1,7 @@
export default (type) => ({
type: 'object',
properties: {
x: {type},
y: {type},
},
});

View File

@ -1,15 +1,20 @@
import vector2d from './helpers/vector-2d';
export default {
layers: {
type: 'array',
subtype: {
type: 'object',
properties: {
area: vector2d('float32'),
data: {
type: 'array',
subtype: {
type: 'uint16',
},
},
source: {type: 'string'},
tileSize: vector2d('float32'),
},
},
},

View File

@ -1,6 +1,5 @@
import {
MOVE_MAP,
RESOLUTION,
TPS,
} from '@/constants.js';
import ControlMovement from '@/ecs-systems/control-movement.js';
@ -36,8 +35,6 @@ const players = {
export default class Engine {
static Ecs = Ecs;
incomingActions = [];
connections = [];
@ -53,34 +50,8 @@ export default class Engine {
server;
constructor(Server) {
const ecs = new this.constructor.Ecs();
const layerSize = {x: Math.ceil(RESOLUTION.x / 4), y: Math.ceil(RESOLUTION.y / 4)};
ecs.create({
AreaSize: {x: RESOLUTION.x * 4, y: RESOLUTION.y * 4},
TileLayers: {
layers: [
{
data: (
Array(layerSize.x * layerSize.y)
.fill(0)
.map(() => 1 + Math.floor(Math.random() * 4))
),
size: layerSize,
}
],
},
});
ecs.addSystem(ControlMovement);
ecs.addSystem(ApplyMomentum);
ecs.addSystem(ClampPositions);
ecs.addSystem(FollowCamera);
ecs.addSystem(CalculateAabbs);
ecs.addSystem(UpdateSpatialHash);
ecs.addSystem(ControlDirection);
ecs.addSystem(SpriteDirection);
ecs.addSystem(RunAnimations);
this.ecses = {
1: ecs,
1: this.createHomestead(),
};
class SilphiusServer extends Server {
accept(connection, packed) {
@ -110,6 +81,38 @@ export default class Engine {
);
}
createEcs(master) {
const ecs = new Ecs();
ecs.create(master);
ecs.addSystem(ControlMovement);
ecs.addSystem(ApplyMomentum);
ecs.addSystem(ClampPositions);
ecs.addSystem(FollowCamera);
ecs.addSystem(CalculateAabbs);
ecs.addSystem(UpdateSpatialHash);
ecs.addSystem(ControlDirection);
ecs.addSystem(SpriteDirection);
ecs.addSystem(RunAnimations);
return ecs;
}
createHomestead() {
const area = {x: 100, y: 60};
return this.createEcs({
AreaSize: {x: area.x * 16, y: area.y * 16},
TileLayers: {
layers: [
{
area,
data: Array(area.x * area.y).fill(0).map(() => 1 + Math.floor(Math.random() * 4)),
source: '/assets/tileset.json',
tileSize: {x: 16, y: 16},
}
],
},
});
}
disconnectPlayer(connection) {
const {entity} = this.connectedPlayers.get(connection);
const ecs = this.ecses[entity.World.world];

15
app/hooks/use-asset.js Normal file
View File

@ -0,0 +1,15 @@
import {Assets} from '@pixi/assets';
import {useEffect, useState} from 'react';
export default function useAsset(source) {
const [asset, setAsset] = useState();
useEffect(() => {
if (Assets.cache.has(source)) {
setAsset(Assets.get(source));
}
else {
Assets.load(source).then(setAsset);
}
}, [setAsset, source]);
return asset;
}

View File

@ -43,10 +43,7 @@ export default function EcsComponent() {
return (
<Container>
<TileLayer
size={TileLayers.layers[0].size}
tiles={TileLayers.layers[0].data}
tileset="/assets/tileset.json"
tileSize={{x: 16, y: 16}}
tileLayer={TileLayers.layers[0]}
x={-cx}
y={-cy}
/>

View File

@ -1,18 +1,9 @@
import {Assets} from '@pixi/assets';
import {Sprite as PixiSprite} from '@pixi/react';
import {useEffect, useState} from 'react';
import useAsset from '@/hooks/use-asset.js';
export default function Sprite({entity}) {
const [asset, setAsset] = useState();
useEffect(() => {
const asset = Assets.get(entity.Sprite.source);
if (asset) {
setAsset(asset);
}
else {
Assets.load(entity.Sprite.source).then(setAsset);
}
}, [setAsset, entity.Sprite.source]);
const asset = useAsset(entity.Sprite.source);
if (!asset) {
return false;
}

View File

@ -1,42 +1,33 @@
import {useEffect, useState} from 'react';
import {Assets} from '@pixi/assets';
import {PixiComponent} from '@pixi/react';
import '@pixi/spritesheet'; // NECESSARY!
import {CompositeTilemap} from '@pixi/tilemap';
import useAsset from '@/hooks/use-asset.js';
const TileLayerInternal = PixiComponent('TileLayer', {
create: () => new CompositeTilemap(),
applyProps: (tilemap, {tiles: oldTiles}, props) => {
const {asset, tiles, tileset, tileSize, size, x, y} = props;
const extless = tileset.slice('/assets/'.length, -'.json'.length);
applyProps: (tilemap, {tileLayer: oldTileLayer}, props) => {
const {asset, tileLayer, x, y} = props;
const extless = tileLayer.source.slice('/assets/'.length, -'.json'.length);
const {textures} = asset;
tilemap.position.x = x;
tilemap.position.y = y;
if (tiles === oldTiles) {
if (tileLayer === oldTileLayer) {
return;
}
tilemap.clear();
let i = 0;
for (let y = 0; y < size.y; ++y) {
for (let x = 0; x < size.x; ++x) {
tilemap.tile(textures[`${extless}/${tiles[i++]}`], tileSize.x * x, tileSize.y * y);
for (let y = 0; y < tileLayer.area.y; ++y) {
for (let x = 0; x < tileLayer.area.x; ++x) {
tilemap.tile(textures[`${extless}/${tileLayer.data[i++]}`], tileLayer.tileSize.x * x, tileLayer.tileSize.y * y);
}
}
},
})
export default function TileLayer(props) {
const {tileset} = props;
const [asset, setAsset] = useState();
useEffect(() => {
const asset = Assets.get(tileset);
if (asset) {
setAsset(asset);
}
else {
Assets.load(tileset).then(setAsset);
}
}, [setAsset, tileset]);
const {tileLayer} = props;
const asset = useAsset(tileLayer.source);
if (!asset) {
return false;
}
@ -44,7 +35,6 @@ export default function TileLayer(props) {
<TileLayerInternal
{...props}
asset={asset}
tileset={tileset}
/>
);
};
}