refactor: radians
This commit is contained in:
parent
94685e4654
commit
4529d2e8d3
9
app/context/radians.js
Normal file
9
app/context/radians.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import {createContext, useContext} from 'react';
|
||||||
|
|
||||||
|
const context = createContext();
|
||||||
|
|
||||||
|
export default context;
|
||||||
|
|
||||||
|
export function useRadians() {
|
||||||
|
return useContext(context);
|
||||||
|
}
|
|
@ -1,33 +1,32 @@
|
||||||
import {useEffect, useState} from 'react';
|
import {memo, useEffect, useState} from 'react';
|
||||||
|
|
||||||
|
import {useRadians} from '@/context/radians.js';
|
||||||
import {render} from '@/dialogue.js';
|
import {render} from '@/dialogue.js';
|
||||||
import {TAU} from '@/util/math.js';
|
|
||||||
|
|
||||||
import styles from './message.module.css';
|
import styles from './message.module.css';
|
||||||
|
|
||||||
export default function Message({letters}) {
|
function Message({letters}) {
|
||||||
const [radians, setRadians] = useState(0);
|
const radians = useRadians();
|
||||||
|
const [localRadians, setLocalRadians] = useState(radians);
|
||||||
|
const [isAnimating, setIsAnimating] = useState(true);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setRadians(0);
|
const handle = setTimeout(() => {
|
||||||
let handle;
|
setIsAnimating(false);
|
||||||
let last;
|
}, 2_000);
|
||||||
const spin = (ts) => {
|
|
||||||
if ('undefined' === typeof last) {
|
|
||||||
last = ts;
|
|
||||||
}
|
|
||||||
const elapsed = (ts - last) / 1000;
|
|
||||||
last = ts;
|
|
||||||
setRadians((radians) => radians + (elapsed * TAU));
|
|
||||||
handle = requestAnimationFrame(spin);
|
|
||||||
};
|
|
||||||
handle = requestAnimationFrame(spin);
|
|
||||||
return () => {
|
return () => {
|
||||||
cancelAnimationFrame(handle);
|
clearTimeout(handle);
|
||||||
};
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
useEffect(() => {
|
||||||
|
if (isAnimating) {
|
||||||
|
setLocalRadians(radians)
|
||||||
|
}
|
||||||
|
}, [isAnimating, radians]);
|
||||||
return (
|
return (
|
||||||
<div className={styles.message}>
|
<div className={styles.message}>
|
||||||
{render(letters, '')(letters.length - 1, radians)}
|
{render(letters, '')(letters.length - 1, localRadians)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default memo(Message);
|
||||||
|
|
|
@ -2,8 +2,8 @@ import {useEffect, useMemo, useRef, useState} from 'react';
|
||||||
|
|
||||||
import {RESOLUTION} from '@/constants.js';
|
import {RESOLUTION} from '@/constants.js';
|
||||||
import {useDomScale} from '@/context/dom-scale.js';
|
import {useDomScale} from '@/context/dom-scale.js';
|
||||||
|
import {useRadians} from '@/context/radians.js';
|
||||||
import {render} from '@/dialogue.js';
|
import {render} from '@/dialogue.js';
|
||||||
import {TAU} from '@/util/math.js';
|
|
||||||
|
|
||||||
import styles from './dialogue.module.css';
|
import styles from './dialogue.module.css';
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ export default function Dialogue({
|
||||||
const ref = useRef();
|
const ref = useRef();
|
||||||
const [dimensions, setDimensions] = useState({h: 0, w: 0});
|
const [dimensions, setDimensions] = useState({h: 0, w: 0});
|
||||||
const [caret, setCaret] = useState(0);
|
const [caret, setCaret] = useState(0);
|
||||||
const [radians, setRadians] = useState(0);
|
const radians = useRadians();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return dialogue.addSkipListener(() => {
|
return dialogue.addSkipListener(() => {
|
||||||
if (caret >= dialogue.letters.length - 1) {
|
if (caret >= dialogue.letters.length - 1) {
|
||||||
|
@ -29,24 +29,6 @@ export default function Dialogue({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [caret, dialogue]);
|
}, [caret, dialogue]);
|
||||||
useEffect(() => {
|
|
||||||
setRadians(0);
|
|
||||||
let handle;
|
|
||||||
let last;
|
|
||||||
const spin = (ts) => {
|
|
||||||
if ('undefined' === typeof last) {
|
|
||||||
last = ts;
|
|
||||||
}
|
|
||||||
const elapsed = (ts - last) / 1000;
|
|
||||||
last = ts;
|
|
||||||
setRadians((radians) => radians + (elapsed * TAU));
|
|
||||||
handle = requestAnimationFrame(spin);
|
|
||||||
};
|
|
||||||
handle = requestAnimationFrame(spin);
|
|
||||||
return () => {
|
|
||||||
cancelAnimationFrame(handle);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const {params} = dialogue.letters[caret];
|
const {params} = dialogue.letters[caret];
|
||||||
let handle;
|
let handle;
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import {AdjustmentFilter} from '@pixi/filter-adjustment';
|
import {AdjustmentFilter} from '@pixi/filter-adjustment';
|
||||||
import {GlowFilter} from '@pixi/filter-glow';
|
import {GlowFilter} from '@pixi/filter-glow';
|
||||||
import {Container} from '@pixi/react';
|
import {Container} from '@pixi/react';
|
||||||
import {useEffect, useState} from 'react';
|
import {useState} from 'react';
|
||||||
|
|
||||||
import {usePacket} from '@/context/client.js';
|
import {usePacket} from '@/context/client.js';
|
||||||
import {useEcs, useEcsTick} from '@/context/ecs.js';
|
import {useEcs, useEcsTick} from '@/context/ecs.js';
|
||||||
import {useMainEntity} from '@/context/main-entity.js';
|
import {useMainEntity} from '@/context/main-entity.js';
|
||||||
|
import {useRadians} from '@/context/radians.js';
|
||||||
|
|
||||||
import Entity from './entity.jsx';
|
import Entity from './entity.jsx';
|
||||||
|
|
||||||
|
@ -13,10 +14,13 @@ export default function Entities({filters, monopolizers}) {
|
||||||
const [ecs] = useEcs();
|
const [ecs] = useEcs();
|
||||||
const [entities, setEntities] = useState({});
|
const [entities, setEntities] = useState({});
|
||||||
const [mainEntity] = useMainEntity();
|
const [mainEntity] = useMainEntity();
|
||||||
const [radians, setRadians] = useState(0);
|
const radians = useRadians();
|
||||||
const [willInteractWith, setWillInteractWith] = useState(0);
|
const [willInteractWith, setWillInteractWith] = useState(0);
|
||||||
const [interactionFilters] = useState([new AdjustmentFilter(), new GlowFilter({color: 0x0})]);
|
const [interactionFilters] = useState([
|
||||||
const pulse = (Math.cos(radians) + 1) * 0.5;
|
new AdjustmentFilter(),
|
||||||
|
new GlowFilter({color: 0x0}),
|
||||||
|
]);
|
||||||
|
const pulse = (Math.cos(radians / 4) + 1) * 0.5;
|
||||||
interactionFilters[0].brightness = (pulse * 0.75) + 1;
|
interactionFilters[0].brightness = (pulse * 0.75) + 1;
|
||||||
interactionFilters[1].outerStrength = pulse * 0.5;
|
interactionFilters[1].outerStrength = pulse * 0.5;
|
||||||
usePacket('EcsChange', async () => {
|
usePacket('EcsChange', async () => {
|
||||||
|
@ -64,15 +68,6 @@ export default function Entities({filters, monopolizers}) {
|
||||||
setWillInteractWith(main.Interacts.willInteractWith);
|
setWillInteractWith(main.Interacts.willInteractWith);
|
||||||
}
|
}
|
||||||
}, [ecs, mainEntity]);
|
}, [ecs, mainEntity]);
|
||||||
useEffect(() => {
|
|
||||||
setRadians(0);
|
|
||||||
const handle = setInterval(() => {
|
|
||||||
setRadians((radians) => (radians + 0.1) % (Math.PI * 2))
|
|
||||||
}, 50);
|
|
||||||
return () => {
|
|
||||||
clearInterval(handle);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
const renderables = [];
|
const renderables = [];
|
||||||
for (const id in entities) {
|
for (const id in entities) {
|
||||||
const isHighlightedInteraction = 0 === monopolizers.length && id == willInteractWith;
|
const isHighlightedInteraction = 0 === monopolizers.length && id == willInteractWith;
|
||||||
|
|
|
@ -11,13 +11,21 @@ import ClientContext from '@/context/client.js';
|
||||||
import DebugContext from '@/context/debug.js';
|
import DebugContext from '@/context/debug.js';
|
||||||
import EcsContext from '@/context/ecs.js';
|
import EcsContext from '@/context/ecs.js';
|
||||||
import MainEntityContext from '@/context/main-entity.js';
|
import MainEntityContext from '@/context/main-entity.js';
|
||||||
|
import RadiansContext from '@/context/radians.js';
|
||||||
|
|
||||||
import Ecs from './ecs.jsx';
|
import Ecs from './ecs.jsx';
|
||||||
import styles from './pixi.module.css';
|
import styles from './pixi.module.css';
|
||||||
|
|
||||||
BaseTexture.defaultOptions.scaleMode = SCALE_MODES.NEAREST;
|
BaseTexture.defaultOptions.scaleMode = SCALE_MODES.NEAREST;
|
||||||
|
|
||||||
const Contexts = [AssetsContext, ClientContext, DebugContext, EcsContext, MainEntityContext];
|
const Contexts = [
|
||||||
|
AssetsContext,
|
||||||
|
ClientContext,
|
||||||
|
DebugContext,
|
||||||
|
EcsContext,
|
||||||
|
MainEntityContext,
|
||||||
|
RadiansContext,
|
||||||
|
];
|
||||||
|
|
||||||
const ContextBridge = ({children, render}) => {
|
const ContextBridge = ({children, render}) => {
|
||||||
const contexts = Contexts.map(useContext);
|
const contexts = Contexts.map(useContext);
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import {Container} from '@pixi/display';
|
import {Container} from '@pixi/display';
|
||||||
import {Graphics} from '@pixi/graphics';
|
import {Graphics} from '@pixi/graphics';
|
||||||
import {PixiComponent} from '@pixi/react';
|
import {PixiComponent} from '@pixi/react';
|
||||||
import {useEffect, useState} from 'react';
|
|
||||||
|
import {useRadians} from '@/context/radians.js';
|
||||||
|
|
||||||
const tileSize = {x: 16, y: 16};
|
const tileSize = {x: 16, y: 16};
|
||||||
|
|
||||||
|
@ -34,15 +35,7 @@ const TargetingGhostInternal = PixiComponent('TargetingGhost', {
|
||||||
})
|
})
|
||||||
|
|
||||||
export default function TargetingGhost({projected, tileLayer}) {
|
export default function TargetingGhost({projected, tileLayer}) {
|
||||||
const [radians, setRadians] = useState(0);
|
const radians = useRadians();
|
||||||
useEffect(() => {
|
|
||||||
const handle = setInterval(() => {
|
|
||||||
setRadians((radians) => (radians + 0.2) % (Math.PI * 2))
|
|
||||||
}, 50);
|
|
||||||
return () => {
|
|
||||||
clearInterval(handle);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
const ghosts = [];
|
const ghosts = [];
|
||||||
const {area} = tileLayer;
|
const {area} = tileLayer;
|
||||||
for (const {x, y} of projected) {
|
for (const {x, y} of projected) {
|
||||||
|
@ -54,7 +47,7 @@ export default function TargetingGhost({projected, tileLayer}) {
|
||||||
key={JSON.stringify({x, y})}
|
key={JSON.stringify({x, y})}
|
||||||
x={x * tileSize.x + tileSize.x * 0.5}
|
x={x * tileSize.x + tileSize.x * 0.5}
|
||||||
y={y * tileSize.y + tileSize.y * 0.5}
|
y={y * tileSize.y + tileSize.y * 0.5}
|
||||||
radians={radians}
|
radians={radians / 2}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,8 @@ import {BlurFilter} from '@pixi/filter-blur';
|
||||||
import {Graphics} from '@pixi/graphics';
|
import {Graphics} from '@pixi/graphics';
|
||||||
import {PixiComponent, useApp} from '@pixi/react';
|
import {PixiComponent, useApp} from '@pixi/react';
|
||||||
import {Sprite} from '@pixi/sprite';
|
import {Sprite} from '@pixi/sprite';
|
||||||
import {useEffect, useState} from 'react';
|
|
||||||
|
import {useRadians} from '@/context/radians.js';
|
||||||
|
|
||||||
const tileSize = {x: 16, y: 16};
|
const tileSize = {x: 16, y: 16};
|
||||||
const radius = 9;
|
const radius = 9;
|
||||||
|
@ -86,19 +87,11 @@ const TargetingGridInternal = PixiComponent('TargetingGrid', {
|
||||||
|
|
||||||
export default function TargetingGrid({tileLayer, x, y}) {
|
export default function TargetingGrid({tileLayer, x, y}) {
|
||||||
const app = useApp();
|
const app = useApp();
|
||||||
const [radians, setRadians] = useState(0);
|
const radians = useRadians();
|
||||||
useEffect(() => {
|
|
||||||
const handle = setInterval(() => {
|
|
||||||
setRadians((radians) => (radians + 0.1) % (Math.PI * 2))
|
|
||||||
}, 50);
|
|
||||||
return () => {
|
|
||||||
clearInterval(handle);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
return (
|
return (
|
||||||
<TargetingGridInternal
|
<TargetingGridInternal
|
||||||
app={app}
|
app={app}
|
||||||
radians={radians}
|
radians={radians / 4}
|
||||||
tileLayer={tileLayer}
|
tileLayer={tileLayer}
|
||||||
x={x}
|
x={x}
|
||||||
y={y}
|
y={y}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {useEffect, useRef, useState} from 'react';
|
import {memo, useEffect, useRef, useState} from 'react';
|
||||||
|
|
||||||
import addKeyListener from '@/add-key-listener.js';
|
import addKeyListener from '@/add-key-listener.js';
|
||||||
import ClientEcs from '@/client-ecs';
|
import ClientEcs from '@/client-ecs';
|
||||||
|
@ -47,7 +47,7 @@ const devEventsChannel = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Ui({disconnected}) {
|
function Ui({disconnected}) {
|
||||||
// Key input.
|
// Key input.
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const chatInputRef = useRef();
|
const chatInputRef = useRef();
|
||||||
|
@ -483,3 +483,4 @@ export default function Ui({disconnected}) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default memo(Ui);
|
||||||
|
|
|
@ -7,8 +7,10 @@ import ClientContext from '@/context/client.js';
|
||||||
import DebugContext from '@/context/debug.js';
|
import DebugContext from '@/context/debug.js';
|
||||||
import EcsContext from '@/context/ecs.js';
|
import EcsContext from '@/context/ecs.js';
|
||||||
import MainEntityContext from '@/context/main-entity.js';
|
import MainEntityContext from '@/context/main-entity.js';
|
||||||
|
import RadiansContext from '@/context/radians.js';
|
||||||
import Ui from '@/react-components/ui.jsx';
|
import Ui from '@/react-components/ui.jsx';
|
||||||
import {juggleSession} from '@/session.server';
|
import {juggleSession} from '@/session.server';
|
||||||
|
import {TAU} from '@/util/math.js';
|
||||||
|
|
||||||
export async function loader({request}) {
|
export async function loader({request}) {
|
||||||
await juggleSession(request);
|
await juggleSession(request);
|
||||||
|
@ -26,6 +28,24 @@ export default function PlaySpecific() {
|
||||||
const [disconnected, setDisconnected] = useState(false);
|
const [disconnected, setDisconnected] = useState(false);
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const [type, url] = params['*'].split('/');
|
const [type, url] = params['*'].split('/');
|
||||||
|
const [radians, setRadians] = useState(0);
|
||||||
|
useEffect(() => {
|
||||||
|
let handle;
|
||||||
|
let last;
|
||||||
|
const spin = (ts) => {
|
||||||
|
if ('undefined' === typeof last) {
|
||||||
|
last = ts;
|
||||||
|
}
|
||||||
|
const elapsed = (ts - last) / 1000;
|
||||||
|
last = ts;
|
||||||
|
setRadians((radians) => radians + (elapsed * TAU));
|
||||||
|
handle = requestAnimationFrame(spin);
|
||||||
|
};
|
||||||
|
handle = requestAnimationFrame(spin);
|
||||||
|
return () => {
|
||||||
|
cancelAnimationFrame(handle);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!Client) {
|
if (!Client) {
|
||||||
return;
|
return;
|
||||||
|
@ -121,7 +141,9 @@ export default function PlaySpecific() {
|
||||||
<EcsContext.Provider value={ecsTuple}>
|
<EcsContext.Provider value={ecsTuple}>
|
||||||
<DebugContext.Provider value={debugTuple}>
|
<DebugContext.Provider value={debugTuple}>
|
||||||
<AssetsContext.Provider value={assetsTuple}>
|
<AssetsContext.Provider value={assetsTuple}>
|
||||||
|
<RadiansContext.Provider value={radians}>
|
||||||
<Ui disconnected={disconnected} />
|
<Ui disconnected={disconnected} />
|
||||||
|
</RadiansContext.Provider>
|
||||||
</AssetsContext.Provider>
|
</AssetsContext.Provider>
|
||||||
</DebugContext.Provider>
|
</DebugContext.Provider>
|
||||||
</EcsContext.Provider>
|
</EcsContext.Provider>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user