Faithful day loop - weather report, cost of lemonade rising over the summer, glasses/signs/price decisions, thunderstorms, heat waves and street crews - with the $$ LEMONSVILLE DAILY FINANCIAL REPORT $$ laid out the way it printed. The simulation is kept out of React so a season can be run headlessly: a careful player compounds $2.00 into roughly $22 over twelve days, while an all-in player goes broke about seven times in ten. Weather scenes are pixel rectangles in SVG and the music is a small chiptune engine on the Web Audio API, so there are no binary assets. The screen is locked to a 4:3 tube and never scrolls.
62 lines
1.7 KiB
TypeScript
62 lines
1.7 KiB
TypeScript
import { useState } from 'react'
|
|
import { MAX_PLAYERS } from '../game/constants'
|
|
import { Btn, Line } from './Crt'
|
|
|
|
export function SetupScreen({
|
|
onStart,
|
|
onBlip,
|
|
}: {
|
|
onStart: (names: string[]) => void
|
|
onBlip: () => void
|
|
}) {
|
|
const [count, setCount] = useState(1)
|
|
const [names, setNames] = useState<string[]>(['', '', '', ''])
|
|
|
|
const setName = (i: number, v: string) =>
|
|
setNames((prev) => prev.map((n, j) => (j === i ? v.slice(0, 12) : n)))
|
|
|
|
return (
|
|
<div className="stack">
|
|
<Line className="center inv-line">LEMONSVILLE BUSINESS LICENCE</Line>
|
|
<Line />
|
|
<Line>HOW MANY PEOPLE WILL PLAY?</Line>
|
|
<div className="row">
|
|
{Array.from({ length: MAX_PLAYERS }, (_, i) => i + 1).map((n) => (
|
|
<Btn
|
|
key={n}
|
|
kind={count === n ? 'primary' : 'normal'}
|
|
onClick={() => {
|
|
onBlip()
|
|
setCount(n)
|
|
}}
|
|
>
|
|
{n}
|
|
</Btn>
|
|
))}
|
|
</div>
|
|
<Line />
|
|
<Line>WHAT ARE THEIR NAMES?</Line>
|
|
{Array.from({ length: count }, (_, i) => (
|
|
<label className="field" key={i}>
|
|
<span className="field-label">STAND {i + 1}</span>
|
|
<input
|
|
className="field-input field-input-name"
|
|
value={names[i]}
|
|
placeholder={`PLAYER ${i + 1}`}
|
|
onChange={(e) => setName(i, e.target.value)}
|
|
maxLength={12}
|
|
/>
|
|
</label>
|
|
))}
|
|
<Line />
|
|
<Line className="dim">EVERY STAND OPENS WITH $2.00 IN THE TIN.</Line>
|
|
<Line />
|
|
<div className="row center">
|
|
<Btn kind="primary" onClick={() => onStart(names.slice(0, count))}>
|
|
OPEN FOR BUSINESS
|
|
</Btn>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|