More visual improvements

This commit is contained in:
dylan 2024-04-21 21:44:02 -07:00
parent fd91fe1d31
commit dfc6d1c751
5 changed files with 85 additions and 28 deletions

View File

@ -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."
`

View File

@ -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
const visualInactive = visChar && visualState.dialog.name !== name;
return [
<img
className={css`
position: absolute;
transition: all 0.25s;
left: -60%;
${
c.side === "left" ? css`left: -20%;` : css`right: -20%; transform: scaleX(-1);`
visChar?.side === "left" && css`left: -20%;`
}
height: 90%;
bottom: 0;
--outline-color: black;
${
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={c.name}
src={char.assets["default"]}
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>

View File

@ -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",
},
},
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 773 KiB