silphius/app/react-components/pixi/tile-layer.jsx
2024-07-12 01:29:54 -05:00

77 lines
2.3 KiB
JavaScript

import {Container} from '@pixi/display';
import {PixiComponent} from '@pixi/react';
import '@pixi/spritesheet'; // NECESSARY!
import {CompositeTilemap} from '@pixi/tilemap';
import {CHUNK_SIZE} from '@/constants.js';
import {useAsset} from '@/context/assets.js';
const TileLayerInternal = PixiComponent('TileLayer', {
create: ({tileLayer}) => {
const container = new Container();
const cy = Math.ceil(tileLayer.area.y / CHUNK_SIZE);
const cx = Math.ceil(tileLayer.area.x / CHUNK_SIZE);
for (let iy = 0; iy < cy; ++iy) {
for (let ix = 0; ix < cx; ++ix) {
const tilemap = new CompositeTilemap();
tilemap.x = tileLayer.tileSize.x * CHUNK_SIZE * ix;
tilemap.y = tileLayer.tileSize.y * CHUNK_SIZE * iy;
container.addChild(tilemap);
}
}
return container;
},
applyProps: (container, {tileLayer: oldTileLayer}, props) => {
const {asset, tileLayer} = props;
const extless = tileLayer.source.slice('/assets/'.length, -'.json'.length);
const {textures} = asset;
if (tileLayer === oldTileLayer) {
return;
}
for (const i in tileLayer.$$chunks) {
if (!oldTileLayer || oldTileLayer.$$chunks[i] !== tileLayer.$$chunks[i]) {
const tilemap = container.children[i];
tilemap.clear();
const ax = Math.ceil(tileLayer.area.x / CHUNK_SIZE);
const cy = Math.floor(i / ax);
const cx = i % ax;
for (let y = 0; y < CHUNK_SIZE; ++y) {
for (let x = 0; x < CHUNK_SIZE; ++x) {
const ty = (cy * CHUNK_SIZE) + y;
const tx = (cx * CHUNK_SIZE) + x;
if (
tx < 0
|| ty < 0
|| tx >= tileLayer.area.x
|| ty >= tileLayer.area.y
) {
continue;
}
tilemap.tile(
textures[`${extless}/${tileLayer.data[ty * tileLayer.area.x + tx]}`],
tileLayer.tileSize.x * x,
tileLayer.tileSize.y * y,
);
}
}
}
}
},
});
export default function TileLayer(props) {
const {tileLayer} = props;
const asset = useAsset(tileLayer.source);
if (!asset) {
return false;
}
return (
<>
<TileLayerInternal
{...props}
asset={asset}
/>
</>
);
}