More visual improvements
This commit is contained in:
		@@ -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."
 | 
			
		||||
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
 
 | 
			
		||||
@@ -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",
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/server/public/assets/axelle.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/server/public/assets/axelle.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 495 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/server/public/assets/theo.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/server/public/assets/theo.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 773 KiB  | 
		Reference in New Issue
	
	Block a user