small improvements
This commit is contained in:
		@@ -9,7 +9,19 @@ 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$"
 | 
			
		||||
 | 
			
		||||
axelle (happy) "Wow, did you know that $a^2+b^2=c^2$?"
 | 
			
		||||
calvin (happy) "Wow, did you know that $a^2+b^2=c^2$?"
 | 
			
		||||
 | 
			
		||||
calvin (happy) "Something else"
 | 
			
		||||
 | 
			
		||||
bridget (happy) "Me again"
 | 
			
		||||
 | 
			
		||||
kit (happy) "I'm Kit!"
 | 
			
		||||
 | 
			
		||||
board ""
 | 
			
		||||
 | 
			
		||||
calvin (happy) "I'm back!"
 | 
			
		||||
 | 
			
		||||
bridget (happy) "I'm on the right now!"
 | 
			
		||||
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,22 +6,40 @@ import { MathText } from "./MathText";
 | 
			
		||||
import { characterData } from "./data";
 | 
			
		||||
 | 
			
		||||
type VisualState = {
 | 
			
		||||
	characters: {name: string, emotion: string, x: number}[],
 | 
			
		||||
	turn: number,
 | 
			
		||||
	characters: {name: string, emotion: string, side: "left" | "right", lastTurn: number}[],
 | 
			
		||||
	board: {text: string},
 | 
			
		||||
	dialog: {name: string | null, text: string},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const otherSide = (side: "left" | "right"): "left" | "right" => {
 | 
			
		||||
	return ({
 | 
			
		||||
		left: "right",
 | 
			
		||||
		right: "left",
 | 
			
		||||
	} as const)[side];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const afterStep = (state: VisualState, step: Mathuscript[number]): VisualState => {
 | 
			
		||||
	const newState = structuredClone(state);
 | 
			
		||||
	const {characters, board, dialog} = newState;
 | 
			
		||||
	newState.turn += 1;
 | 
			
		||||
	if (step.name === "board") {
 | 
			
		||||
		board.text = step.text;
 | 
			
		||||
	} else {
 | 
			
		||||
		characters.sort((a, b) => a.lastTurn - b.lastTurn);
 | 
			
		||||
		let char = characters.find(c => c.name === step.name);
 | 
			
		||||
		if (!char) {
 | 
			
		||||
			char = {name: step.name, emotion: "default", x: 0.5};
 | 
			
		||||
			char = {name: step.name, emotion: "default", side: "left", lastTurn: -1};
 | 
			
		||||
			if (characters.length > 1) {
 | 
			
		||||
				characters.splice(0, characters.length-1);
 | 
			
		||||
			}
 | 
			
		||||
			const otherChar = characters[0];
 | 
			
		||||
			if (otherChar) {
 | 
			
		||||
				char.side = otherSide(otherChar.side);
 | 
			
		||||
			}
 | 
			
		||||
			characters.push(char);
 | 
			
		||||
		}
 | 
			
		||||
		char.lastTurn = newState.turn;
 | 
			
		||||
		char.emotion = step.emotion ?? char.emotion;
 | 
			
		||||
		dialog.name = step.name;
 | 
			
		||||
		dialog.text = step.text;
 | 
			
		||||
@@ -41,7 +59,7 @@ export const MathuscriptPlayer = (props: { script: string }) => {
 | 
			
		||||
	const {script} = props;
 | 
			
		||||
	const parsedScript = useMemo(() => parseMathuscript(script), [script]);
 | 
			
		||||
	const [index, setIndex] = useState(0);
 | 
			
		||||
	const [visualState, setVisualState] = useState<VisualState>({characters: [], board: {text: ""}, dialog: {name: null, text: ""}});
 | 
			
		||||
	const [visualState, setVisualState] = useState<VisualState>({turn: 0, characters: [], board: {text: ""}, dialog: {name: null, text: ""}});
 | 
			
		||||
 | 
			
		||||
	const doStep = useCallback(() => {
 | 
			
		||||
		const step = parsedScript[index];
 | 
			
		||||
@@ -105,9 +123,13 @@ export const MathuscriptPlayer = (props: { script: string }) => {
 | 
			
		||||
							return <img
 | 
			
		||||
								className={css`
 | 
			
		||||
									position: absolute;
 | 
			
		||||
									left: -20%;
 | 
			
		||||
									${
 | 
			
		||||
										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"]}
 | 
			
		||||
@@ -126,6 +148,7 @@ export const MathuscriptPlayer = (props: { script: string }) => {
 | 
			
		||||
					<div className={css`
 | 
			
		||||
						flex-basis: 0;
 | 
			
		||||
						flex-grow: 1;
 | 
			
		||||
						position: relative;
 | 
			
		||||
						background-color: hsla(220, 50%, 40%, 0.85);
 | 
			
		||||
						border: 2px solid hsla(220, 30%, 60%, 0.85);
 | 
			
		||||
						border-radius: 0.25em;
 | 
			
		||||
@@ -134,7 +157,18 @@ export const MathuscriptPlayer = (props: { script: string }) => {
 | 
			
		||||
					`}>
 | 
			
		||||
						{
 | 
			
		||||
							speakingChar && <>
 | 
			
		||||
								<strong>{speakingChar.displayName}.</strong> <MathText>{visualState.dialog.text}</MathText>
 | 
			
		||||
								<div className={css`
 | 
			
		||||
									position: absolute;
 | 
			
		||||
									bottom: 100%;
 | 
			
		||||
									left: 0;
 | 
			
		||||
									background-color: hsla(220, 50%, 40%, 0.85);
 | 
			
		||||
									border: 2px solid hsla(220, 30%, 60%, 0.85);
 | 
			
		||||
									border-radius: 0.25em;
 | 
			
		||||
									padding: 0.25em 0.75em;
 | 
			
		||||
								`}>
 | 
			
		||||
									<strong>{speakingChar.displayName}</strong>
 | 
			
		||||
								</div>
 | 
			
		||||
								<MathText>{visualState.dialog.text}</MathText>
 | 
			
		||||
							</>
 | 
			
		||||
						}
 | 
			
		||||
					</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -3,14 +3,18 @@ export const characterData = {
 | 
			
		||||
		displayName: "Bridget",
 | 
			
		||||
		assets: {
 | 
			
		||||
			default: "/assets/bridget.png",
 | 
			
		||||
			fallback: "/assets/bridget.png",
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	axelle: {
 | 
			
		||||
		displayName: "Axelle",
 | 
			
		||||
	calvin: {
 | 
			
		||||
		displayName: "Calvin",
 | 
			
		||||
		assets: {
 | 
			
		||||
			default: "/assets/bridget.png",
 | 
			
		||||
			fallback: "/assets/bridget.png",
 | 
			
		||||
			default: "/assets/calvin.png",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	},
 | 
			
		||||
	kit: {
 | 
			
		||||
		displayName: "Kit",
 | 
			
		||||
		assets: {
 | 
			
		||||
			default: "/assets/kit.png",
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/server/public/assets/calvin.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/server/public/assets/calvin.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 411 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/server/public/assets/kit.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/server/public/assets/kit.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 856 KiB  | 
		Reference in New Issue
	
	Block a user