fun: light
This commit is contained in:
parent
578e796090
commit
0d8cdff6d7
|
@ -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},
|
||||||
|
|
7
app/ecs-components/light.js
Normal file
7
app/ecs-components/light.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import Component from '@/ecs/component.js';
|
||||||
|
|
||||||
|
export default class Light extends Component {
|
||||||
|
static properties = {
|
||||||
|
radius: {type: 'uint8'},
|
||||||
|
};
|
||||||
|
}
|
|
@ -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} />
|
||||||
)}
|
)}
|
||||||
|
|
27
app/react-components/pixi/light.jsx
Normal file
27
app/react-components/pixi/light.jsx
Normal 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}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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')
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
12
package-lock.json
generated
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
1
public/assets/tileset.normals.json
Normal file
1
public/assets/tileset.normals.json
Normal file
File diff suppressed because one or more lines are too long
BIN
public/assets/tileset.normals.png
Normal file
BIN
public/assets/tileset.normals.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
Loading…
Reference in New Issue
Block a user