fun: light

This commit is contained in:
cha0s 2024-07-17 05:07:50 -05:00
parent 578e796090
commit 0d8cdff6d7
11 changed files with 116 additions and 12 deletions

View File

@ -41,6 +41,7 @@ export default async function createPlayer(id) {
}, },
}, },
Health: {health: 100}, Health: {health: 100},
Light: {},
Magnet: {strength: 24}, Magnet: {strength: 24},
Player: {}, Player: {},
Position: {x: 128, y: 128}, Position: {x: 128, y: 128},

View File

@ -0,0 +1,7 @@
import Component from '@/ecs/component.js';
export default class Light extends Component {
static properties = {
radius: {type: 'uint8'},
};
}

View File

@ -5,6 +5,7 @@ import {useDebug} from '@/context/debug.js';
import {useMainEntity} from '@/context/main-entity.js'; import {useMainEntity} from '@/context/main-entity.js';
import Emitter from './emitter.jsx'; import Emitter from './emitter.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}) {
@ -66,6 +67,12 @@ function Entity({entity, ...rest}) {
entity={entity} entity={entity}
/> />
)} )}
{entity.Light && (
<Light
x={entity.Position.x}
y={entity.Position.y}
/>
)}
{debug && entity.Position && ( {debug && entity.Position && (
<Crosshair x={entity.Position.x} y={entity.Position.y} /> <Crosshair x={entity.Position.x} y={entity.Position.y} />
)} )}

View File

@ -0,0 +1,27 @@
import {PixiComponent} from '@pixi/react';
let PointLight;
if ('undefined' !== typeof window) {
({PointLight} = await import('@pixi/lights'));
}
const LightInternal = PixiComponent('Light', {
create({x, y}) {
const light = new PointLight(0xffffff, 1);
light.position.set(x, y);
return light;
},
applyProps(light, oldProps, {x, y}) {
light.position.set(x, y);
},
});
export default function Light({x, y}) {
return (
<LightInternal
x={x}
y={y}
/>
)
}

View File

@ -58,7 +58,7 @@ export default function Pixi({applyFilters, camera, monopolizers, scale}) {
width={RESOLUTION.x} width={RESOLUTION.x}
height={RESOLUTION.y} height={RESOLUTION.y}
options={{ options={{
background: 0x1099bb, background: 0x0,
}} }}
> >
<Ecs <Ecs

View File

@ -1,5 +1,6 @@
import { Application } from '@pixi/app'; import { Application } from '@pixi/app';
import { Stage as LayerStage } from '@pixi/layers'; import { Layer, Stage as LayerStage } from '@pixi/layers';
import { Ticker } from '@pixi/ticker'; import { Ticker } from '@pixi/ticker';
import { AppProvider, PixiFiber } from '@pixi/react'; import { AppProvider, PixiFiber } from '@pixi/react';
@ -28,6 +29,11 @@ const PROPS_DISPLAY_OBJECT = {
y: 0, y: 0,
}; };
let AmbientLight, diffuseGroup, normalGroup, lightGroup;
if ('undefined' !== typeof window) {
({AmbientLight, diffuseGroup, normalGroup, lightGroup} = await import('@pixi/lights'));
}
const noop = () => {}; const noop = () => {};
/** /**
@ -134,7 +140,12 @@ class Stage extends React.Component
...options, ...options,
autoDensity: options?.autoDensity !== false, autoDensity: options?.autoDensity !== false,
}); });
this.app.stage = new LayerStage(); const stage = new LayerStage();
this.app.stage = stage;
stage.addChild(new Layer(diffuseGroup));
stage.addChild(new Layer(normalGroup));
stage.addChild(new Layer(lightGroup));
stage.addChild(new AmbientLight(0xffffff, 1));
if (process.env.NODE_ENV === 'development') if (process.env.NODE_ENV === 'development')
{ {

View File

@ -1,28 +1,43 @@
import {RenderTexture} from '@pixi/core';
import {Container} from '@pixi/display'; import {Container} from '@pixi/display';
import {PixiComponent} from '@pixi/react'; import {PixiComponent, useApp} from '@pixi/react';
import {Sprite} from '@pixi/sprite';
import '@pixi/spritesheet'; // NECESSARY! import '@pixi/spritesheet'; // NECESSARY!
import {CompositeTilemap} from '@pixi/tilemap'; import {CompositeTilemap} from '@pixi/tilemap';
import {CHUNK_SIZE} from '@/constants.js'; import {CHUNK_SIZE} from '@/constants.js';
import {useAsset} from '@/context/assets.js'; import {useAsset} from '@/context/assets.js';
let diffuseGroup, normalGroup;
if ('undefined' !== typeof window) {
({diffuseGroup, normalGroup} = await import('@pixi/lights'));
}
const TileLayerInternal = PixiComponent('TileLayer', { const TileLayerInternal = PixiComponent('TileLayer', {
create: ({tileLayer}) => { create: ({group, stage, tileLayer}) => {
const container = new Container(); const container = new Container();
const cy = Math.ceil(tileLayer.area.y / CHUNK_SIZE); const cy = Math.ceil(tileLayer.area.y / CHUNK_SIZE);
const cx = Math.ceil(tileLayer.area.x / CHUNK_SIZE); const cx = Math.ceil(tileLayer.area.x / CHUNK_SIZE);
for (let iy = 0; iy < cy; ++iy) { for (let iy = 0; iy < cy; ++iy) {
for (let ix = 0; ix < cx; ++ix) { for (let ix = 0; ix < cx; ++ix) {
const tilemap = new CompositeTilemap(); const tilemap = new CompositeTilemap();
tilemap.x = tileLayer.tileSize.x * CHUNK_SIZE * ix; const renderTexture = RenderTexture.create({
tilemap.y = tileLayer.tileSize.y * CHUNK_SIZE * iy; width: tileLayer.tileSize.x * CHUNK_SIZE,
container.addChild(tilemap); height: tileLayer.tileSize.y * CHUNK_SIZE,
});
const sprite = new Sprite(renderTexture);
sprite.x = tileLayer.tileSize.x * CHUNK_SIZE * ix;
sprite.y = tileLayer.tileSize.y * CHUNK_SIZE * iy;
sprite.parentGroup = group;
sprite.tilemap = tilemap;
container.addChild(sprite);
} }
} }
return container; return container;
}, },
applyProps: (container, {tileLayer: oldTileLayer}, props) => { applyProps: (container, {tileLayer: oldTileLayer}, props) => {
const {asset, tileLayer} = props; const {asset, group, renderer, tileLayer} = props;
const extless = tileLayer.source.slice('/assets/'.length, -'.json'.length); const extless = tileLayer.source.slice('/assets/'.length, -'.json'.length);
const {textures} = asset; const {textures} = asset;
if (tileLayer === oldTileLayer) { if (tileLayer === oldTileLayer) {
@ -30,7 +45,7 @@ const TileLayerInternal = PixiComponent('TileLayer', {
} }
for (const i in tileLayer.$$chunks) { for (const i in tileLayer.$$chunks) {
if (!oldTileLayer || oldTileLayer.$$chunks[i] !== tileLayer.$$chunks[i]) { if (!oldTileLayer || oldTileLayer.$$chunks[i] !== tileLayer.$$chunks[i]) {
const tilemap = container.children[i]; const {texture, tilemap} = container.children[i];
tilemap.clear(); tilemap.clear();
const ax = Math.ceil(tileLayer.area.x / CHUNK_SIZE); const ax = Math.ceil(tileLayer.area.x / CHUNK_SIZE);
const cy = Math.floor(i / ax); const cy = Math.floor(i / ax);
@ -47,22 +62,34 @@ const TileLayerInternal = PixiComponent('TileLayer', {
) { ) {
continue; continue;
} }
const parts = [
extless,
...(normalGroup === group ? ['normals'] : []),
tileLayer.data[ty * tileLayer.area.x + tx],
];
tilemap.tile( tilemap.tile(
textures[`${extless}/${tileLayer.data[ty * tileLayer.area.x + tx]}`], textures[parts.join('/')],
tileLayer.tileSize.x * x, tileLayer.tileSize.x * x,
tileLayer.tileSize.y * y, tileLayer.tileSize.y * y,
{
tileWidth: 16,
tileHeight: 16,
},
); );
} }
} }
renderer.render(tilemap, {renderTexture: texture});
} }
} }
}, },
}); });
export default function TileLayer(props) { export default function TileLayer(props) {
const {renderer, stage} = useApp();
const {tileLayer} = props; const {tileLayer} = props;
const asset = useAsset(tileLayer.source); const asset = useAsset(tileLayer.source);
if (!asset) { const normalsAsset = useAsset([tileLayer.source.slice(0, -'.json'.length), 'normals.json'].join('.'));
if (!asset || !normalsAsset) {
return false; return false;
} }
return ( return (
@ -70,6 +97,16 @@ export default function TileLayer(props) {
<TileLayerInternal <TileLayerInternal
{...props} {...props}
asset={asset} asset={asset}
group={diffuseGroup}
renderer={renderer}
stage={stage}
/>
<TileLayerInternal
{...props}
asset={normalsAsset}
group={normalGroup}
renderer={renderer}
stage={stage}
/> />
</> </>
); );

12
package-lock.json generated
View File

@ -11,6 +11,7 @@
"@pixi/filter-color-matrix": "^7.4.2", "@pixi/filter-color-matrix": "^7.4.2",
"@pixi/filter-glow": "^5.2.1", "@pixi/filter-glow": "^5.2.1",
"@pixi/layers": "^2.1.0", "@pixi/layers": "^2.1.0",
"@pixi/lights": "^4.1.0",
"@pixi/particle-emitter": "^5.0.8", "@pixi/particle-emitter": "^5.0.8",
"@pixi/react": "^7.1.2", "@pixi/react": "^7.1.2",
"@pixi/spritesheet": "^7.4.2", "@pixi/spritesheet": "^7.4.2",
@ -3724,6 +3725,17 @@
"@pixi/display": "^7.0.0" "@pixi/display": "^7.0.0"
} }
}, },
"node_modules/@pixi/lights": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/@pixi/lights/-/lights-4.1.0.tgz",
"integrity": "sha512-UPY5/GTVZefev9iVY4zCgslHhxw5D196T8u/AP8X7T5rJQa9PNcGK9FS0aFnOg9dpX1PuPi3cs2cdtYMvYVDRw==",
"peerDependencies": {
"@pixi/core": "^7.0.0",
"@pixi/display": "^7.0.0",
"@pixi/layers": "^2.0.1",
"@pixi/mesh": "^7.0.0"
}
},
"node_modules/@pixi/math": { "node_modules/@pixi/math": {
"version": "7.4.2", "version": "7.4.2",
"resolved": "https://registry.npmjs.org/@pixi/math/-/math-7.4.2.tgz", "resolved": "https://registry.npmjs.org/@pixi/math/-/math-7.4.2.tgz",

View File

@ -18,6 +18,7 @@
"@pixi/filter-color-matrix": "^7.4.2", "@pixi/filter-color-matrix": "^7.4.2",
"@pixi/filter-glow": "^5.2.1", "@pixi/filter-glow": "^5.2.1",
"@pixi/layers": "^2.1.0", "@pixi/layers": "^2.1.0",
"@pixi/lights": "^4.1.0",
"@pixi/particle-emitter": "^5.0.8", "@pixi/particle-emitter": "^5.0.8",
"@pixi/react": "^7.1.2", "@pixi/react": "^7.1.2",
"@pixi/spritesheet": "^7.4.2", "@pixi/spritesheet": "^7.4.2",

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB