fix the bugs with skipping

This commit is contained in:
dylan 2024-04-22 19:52:11 -07:00
parent f4e55a2257
commit e2d1b006fe
4 changed files with 53 additions and 22 deletions

View File

@ -13,9 +13,11 @@ calvin (mathstruck) "Wow, did you know that $a^2+b^2=c^2$?"
calvin (thinking) "Something else" calvin (thinking) "Something else"
bridget (surprised) "Me again" bridget (surprised) "Me again000000"
kit (smiling) "I'm Kit!" kit (smiling) "I'm Kit 1!"
kit (smiling) "I'm Kit 2!"
board "" board ""

View File

@ -1,26 +1,51 @@
import { useEffect, useLayoutEffect, useState } from "react"; import { ForwardedRef, forwardRef, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from "react";
import { MathText } from "./MathText"; import { MathText } from "./MathText";
export const DialogText = (props: {children: string, onFinish?: () => void}) => { export type DialogTextImperatives = {
const {children: str, onFinish} = props; skip(): void;
}
export const DialogText = forwardRef((props: {children: string, speed?: number, onFinish?: () => void}, forwardedRef: ForwardedRef<DialogTextImperatives>) => {
const {children: str, onFinish, speed = 15} = props;
const [len, setLen] = useState(0); const [len, setLen] = useState(0);
const interval = useRef<unknown>(null);
useImperativeHandle(forwardedRef, () => {
return {
skip() {
setLen(str.length);
}
}
}, [str, setLen]);
useLayoutEffect(() => { useLayoutEffect(() => {
setLen(0); setLen(0);
}, [str]); }, [str]);
useEffect(() => { useEffect(() => {
const interval = setInterval(() => { interval.current = setInterval(() => {
setLen(l => Math.max(l+1, str.length)); setLen(l => {
}, 70); return Math.min(l+1, str.length)
if (len === str.length) { });
// clearInterval(interval); }, 1000/speed);
onFinish && onFinish();
}
return () => { return () => {
clearInterval(interval); if (interval.current) {
clearInterval(interval.current as any);
interval.current = null;
}
}; };
}, [str, setLen]); }, [str, setLen]);
useLayoutEffect(() => {
if (len === str.length) {
if (interval.current) {
clearInterval(interval.current as any);
interval.current = null;
}
console.log("onFinish");
onFinish && onFinish();
}
}, [len]);
return <MathText>{str.slice(0, len)}</MathText> return <MathText>{str.slice(0, len)}</MathText>
} });

View File

@ -3,7 +3,7 @@ import { Mathuscript, parseMathuscript } from "./parse";
import { useCallback, useMemo, useRef, useState } from "react"; import { useCallback, useMemo, useRef, useState } from "react";
import { MathText } from "./MathText"; import { MathText } from "./MathText";
import { characterData } from "./data"; import { characterData } from "./data";
import { DialogText } from "./DialogText"; import { DialogText, DialogTextImperatives } from "./DialogText";
type VisualState = { type VisualState = {
turn: number, turn: number,
@ -45,7 +45,6 @@ const afterStep = (state: VisualState, step: Mathuscript[number]): VisualState =
dialog.emotion = char.emotion; dialog.emotion = char.emotion;
dialog.text = step.text; dialog.text = step.text;
} }
console.log(newState);
return newState; return newState;
} }
@ -65,16 +64,18 @@ export const MathuscriptPlayer = (props: { script: string }) => {
const [index, setIndex] = useState(0); const [index, setIndex] = useState(0);
const [visualState, setVisualState] = useState<VisualState>({turn: 0, characters: [], board: {text: ""}, dialog: {name: null, emotion: "", text: ""}}); const [visualState, setVisualState] = useState<VisualState>({turn: 0, characters: [], board: {text: ""}, dialog: {name: null, emotion: "", text: ""}});
const dialogGoing = useRef(false); const dialogGoing = useRef(false);
const dialogTextRef = useRef<DialogTextImperatives>(null);
const doStep = useCallback(() => { const doStep = useCallback(() => {
goAgain.current = false;
if (dialogGoing.current) { if (dialogGoing.current) {
console.log("dialog running"); if (dialogTextRef.current) {
dialogTextRef.current.skip();
}
return; return;
} }
goAgain.current = false;
const step = parsedScript[index]; const step = parsedScript[index];
if (step) { if (step) {
console.log(step);
setIndex(i => i+1); setIndex(i => i+1);
setVisualState(state => afterStep(state, step)); setVisualState(state => afterStep(state, step));
if (step.name === "board") { if (step.name === "board") {
@ -87,6 +88,10 @@ export const MathuscriptPlayer = (props: { script: string }) => {
} }
}, [index, parsedScript, setIndex, setVisualState]); }, [index, parsedScript, setIndex, setVisualState]);
const onDialogFinish = useCallback(() => {
dialogGoing.current = false;
}, []);
if (goAgain.current) { if (goAgain.current) {
doStep(); doStep();
} }
@ -218,9 +223,7 @@ export const MathuscriptPlayer = (props: { script: string }) => {
`}> `}>
<strong>{speakingChar.displayName}</strong> {visualState.dialog.emotion && <em>({visualState.dialog.emotion})</em>} <strong>{speakingChar.displayName}</strong> {visualState.dialog.emotion && <em>({visualState.dialog.emotion})</em>}
</div> </div>
<DialogText onFinish={() => { <DialogText onFinish={onDialogFinish} ref={dialogTextRef}>
dialogGoing.current = false;
}}>
{visualState.dialog.text} {visualState.dialog.text}
</DialogText> </DialogText>
</> </>

View File

@ -2,6 +2,7 @@
"compilerOptions": { "compilerOptions": {
"target": "es2017", "target": "es2017",
"module": "es2022", "module": "es2022",
"lib": ["DOM"],
"moduleResolution": "node", "moduleResolution": "node",
"jsx": "react-jsx", "jsx": "react-jsx",
"allowImportingTsExtensions": true, "allowImportingTsExtensions": true,