diff --git a/src/client/app.tsx b/src/client/app.tsx index 7a806a1..0222f29 100644 --- a/src/client/app.tsx +++ b/src/client/app.tsx @@ -9,19 +9,23 @@ bridget (happy) "Hi, friends!" board "Given $f: \mathbb{Q} \to \mathbb{R}$ and $x \in \mathbb{Q}$, there is a unique $y \in \mathbb{N}$ such that $f(x)=y$" -calvin (happy) "Wow, did you know that $a^2+b^2=c^2$?" +calvin (mathstruck) "Wow, did you know that $a^2+b^2=c^2$?" -calvin (happy) "Something else" +calvin (thinking) "Something else" -bridget (happy) "Me again" +bridget (surprised) "Me again" -kit (happy) "I'm Kit!" +kit (smiling) "I'm Kit!" board "" calvin (happy) "I'm back!" -bridget (happy) "I'm on the right now!" +bridget (aha) "I'm on the right now!" + +theo (heh) "Oh, hey guys. Didn't see you there." + +axelle "Oh, hi." ` diff --git a/src/client/player/Player.tsx b/src/client/player/Player.tsx index a4aa72b..0d79a55 100644 --- a/src/client/player/Player.tsx +++ b/src/client/player/Player.tsx @@ -1,7 +1,6 @@ import { css } from "@emotion/css"; import { Mathuscript, parseMathuscript } from "./parse"; -import katex from "katex"; -import { useCallback, useLayoutEffect, useMemo, useRef, useState } from "react"; +import { useCallback, useMemo, useRef, useState } from "react"; import { MathText } from "./MathText"; import { characterData } from "./data"; @@ -9,7 +8,7 @@ type VisualState = { turn: number, characters: {name: string, emotion: string, side: "left" | "right", lastTurn: number}[], board: {text: string}, - dialog: {name: string | null, text: string}, + dialog: {name: string | null, emotion: string, text: string}, } const otherSide = (side: "left" | "right"): "left" | "right" => { @@ -42,6 +41,7 @@ const afterStep = (state: VisualState, step: Mathuscript[number]): VisualState = char.lastTurn = newState.turn; char.emotion = step.emotion ?? char.emotion; dialog.name = step.name; + dialog.emotion = char.emotion; dialog.text = step.text; } console.log(newState); @@ -55,23 +55,34 @@ const getCharData = (name: string | null) => { return null; } +const allChars = Object.keys(characterData) as (keyof typeof characterData)[]; + export const MathuscriptPlayer = (props: { script: string }) => { const {script} = props; const parsedScript = useMemo(() => parseMathuscript(script), [script]); + const goAgain = useRef(false); const [index, setIndex] = useState(0); - const [visualState, setVisualState] = useState<VisualState>({turn: 0, characters: [], board: {text: ""}, dialog: {name: null, text: ""}}); + const [visualState, setVisualState] = useState<VisualState>({turn: 0, characters: [], board: {text: ""}, dialog: {name: null, emotion: "", text: ""}}); const doStep = useCallback(() => { + goAgain.current = false; const step = parsedScript[index]; if (step) { console.log(step); setIndex(i => i+1); setVisualState(state => afterStep(state, step)); + if (step.name === "board") { + goAgain.current = true; + } } else { console.log("the end"); } }, [index, parsedScript, setIndex, setVisualState]); + if (goAgain.current) { + doStep(); + } + const speakingChar = getCharData(visualState.dialog.name); return ( @@ -99,7 +110,6 @@ export const MathuscriptPlayer = (props: { script: string }) => { align-items: center; justify-content: center; color: white; - /* background-color: rgba(255, 0, 0, 0.3); */ padding: 1em; `}> <div> @@ -114,26 +124,57 @@ export const MathuscriptPlayer = (props: { script: string }) => { left: 0; `}> { - visualState.characters.map(c => { + allChars.map(name => { + const visChar = visualState.characters.find(ch => ch.name === name); // TODO: make it change with emotion - const char = getCharData(c.name); - if (!char) { + const charDat = getCharData(name); + if (!charDat) { return null; } - return <img - className={css` - position: absolute; - ${ - c.side === "left" ? css`left: -20%;` : css`right: -20%; transform: scaleX(-1);` - } - height: 90%; - bottom: 0; - --outline-color: black; - filter: drop-shadow(1px 1px 0 var(--outline-color)) drop-shadow(-1px 1px 0 var(--outline-color)) drop-shadow(1px -1px 0 var(--outline-color)) drop-shadow(-1px -1px 0 var(--outline-color)); - `} - key={c.name} - src={char.assets["default"]} - /> + const visualInactive = visChar && visualState.dialog.name !== name; + return [ + <img + className={css` + position: absolute; + transition: all 0.25s; + left: -60%; + ${ + visChar?.side === "left" && css`left: -20%;` + } + height: 90%; + bottom: 0; + ${ + visualInactive && css`bottom: -3%;` + } + --outline-color: white; + /* --outline-color: hsl(300, 45%, 40%); */ + filter: drop-shadow(1px 1px 0 var(--outline-color)) drop-shadow(-1px 1px 0 var(--outline-color)) drop-shadow(1px -1px 0 var(--outline-color)) drop-shadow(-1px -1px 0 var(--outline-color)); + `} + key={`${name}-left`} + src={charDat.assets["default"]} + />, + <img + className={css` + position: absolute; + transition: all 0.25s; + transform: scaleX(-1); + right: -60%; + ${ + visChar?.side === "right" && css`right: -20%;` + } + height: 90%; + bottom: 0; + ${ + visualInactive && css`bottom: -3%;` + } + --outline-color: white; + /* --outline-color: hsl(300, 45%, 40%); */ + filter: drop-shadow(1px 1px 0 var(--outline-color)) drop-shadow(-1px 1px 0 var(--outline-color)) drop-shadow(1px -1px 0 var(--outline-color)) drop-shadow(-1px -1px 0 var(--outline-color)); + `} + key={`${name}-right`} + src={charDat.assets["default"]} + /> + ] }) } </div> @@ -168,7 +209,7 @@ export const MathuscriptPlayer = (props: { script: string }) => { `}> <strong>{speakingChar.displayName}</strong> </div> - <MathText>{visualState.dialog.text}</MathText> + {visualState.dialog.emotion && <em>({visualState.dialog.emotion})</em>} <MathText>{visualState.dialog.text}</MathText> </> } </div> diff --git a/src/client/player/data.ts b/src/client/player/data.ts index 558c31d..3711c03 100644 --- a/src/client/player/data.ts +++ b/src/client/player/data.ts @@ -17,4 +17,16 @@ export const characterData = { default: "/assets/kit.png", }, }, + theo: { + displayName: "Theo", + assets: { + default: "/assets/theo.png", + }, + }, + axelle: { + displayName: "Axelle", + assets: { + default: "/assets/axelle.png", + }, + }, } \ No newline at end of file diff --git a/src/server/public/assets/axelle.png b/src/server/public/assets/axelle.png new file mode 100644 index 0000000..dfa9c34 Binary files /dev/null and b/src/server/public/assets/axelle.png differ diff --git a/src/server/public/assets/theo.png b/src/server/public/assets/theo.png new file mode 100644 index 0000000..e7952bf Binary files /dev/null and b/src/server/public/assets/theo.png differ