First-timer coaching, an escape from the judge, and a cleaner polaroid
- judge screen: the foot row now wraps (NEXT ORDER was pushed off-viewport on narrower windows — the game looked unfinishable), ENTER advances after a 0.6s guard, and the button says so - polaroid: dropped the partly.party URL stamp - kitchen: first session gets the phase hints at coaching volume (gold, pulsing) until the first slice is served Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
02ccf9e800
commit
317c78be71
@ -20,6 +20,9 @@ export class JudgeView implements View {
|
|||||||
private slice: Slice | null = null;
|
private slice: Slice | null = null;
|
||||||
private spin = 0;
|
private spin = 0;
|
||||||
private heatmap: 0 | 1 | 2 = 0;
|
private heatmap: 0 | 1 | 2 = 0;
|
||||||
|
/** Seconds since the scorecard appeared — the leftover ENTER that served the
|
||||||
|
* toast must not also dismiss the verdict before anyone reads it. */
|
||||||
|
private age = 0;
|
||||||
|
|
||||||
private panel: Panel;
|
private panel: Panel;
|
||||||
private cardEl!: HTMLElement;
|
private cardEl!: HTMLElement;
|
||||||
@ -98,7 +101,7 @@ export class JudgeView implements View {
|
|||||||
() => undefined,
|
() => undefined,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
this.nextBtn = el('button', 'btn', btns, 'NEXT ORDER');
|
this.nextBtn = el('button', 'btn', btns, 'NEXT ORDER ⏎');
|
||||||
this.nextBtn.addEventListener('click', () => this.onNext?.());
|
this.nextBtn.addEventListener('click', () => this.onNext?.());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,9 +164,6 @@ export class JudgeView implements View {
|
|||||||
row += w + ' ';
|
row += w + ' ';
|
||||||
}
|
}
|
||||||
if (row.trim() && y <= H - 40) g.fillText((y === 762 ? '“' : '') + row.trim() + '”', 34, y);
|
if (row.trim() && y <= H - 40) g.fillText((y === 762 ? '“' : '') + row.trim() + '”', 34, y);
|
||||||
g.font = '16px Georgia, serif';
|
|
||||||
g.fillStyle = '#8a7f72';
|
|
||||||
g.fillText('partly.party/toastsim', W - 210, H - 22);
|
|
||||||
// Hand it over.
|
// Hand it over.
|
||||||
const a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
a.href = out.toDataURL('image/png');
|
a.href = out.toDataURL('image/png');
|
||||||
@ -181,6 +181,7 @@ export class JudgeView implements View {
|
|||||||
eye.hide(); // the full portrait takes over from the corner glance
|
eye.hide(); // the full portrait takes over from the corner glance
|
||||||
this.slice = slice;
|
this.slice = slice;
|
||||||
this.spin = 0;
|
this.spin = 0;
|
||||||
|
this.age = 0;
|
||||||
this.heatmap = 0;
|
this.heatmap = 0;
|
||||||
slice.setHeatmap(0);
|
slice.setHeatmap(0);
|
||||||
slice.setPresentation(true);
|
slice.setPresentation(true);
|
||||||
@ -334,6 +335,8 @@ export class JudgeView implements View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update(dt: number): void {
|
update(dt: number): void {
|
||||||
|
this.age += dt;
|
||||||
|
if (this.age > 0.6 && this.app.input.justPressed('Enter')) this.onNext?.();
|
||||||
this.spin += dt * 0.42;
|
this.spin += dt * 0.42;
|
||||||
if (this.slice) this.slice.mesh.rotation.y = this.spin;
|
if (this.slice) this.slice.mesh.rotation.y = this.spin;
|
||||||
this.app.camera.position.set(0.15, 2.35, 3.5);
|
this.app.camera.position.set(0.15, 2.35, 3.5);
|
||||||
|
|||||||
@ -229,6 +229,10 @@ export class KitchenView implements View {
|
|||||||
|
|
||||||
this.cueEl = el('div', 'cue', p, 'smells like bread');
|
this.cueEl = el('div', 'cue', p, 'smells like bread');
|
||||||
this.hintEl = el('div', 'hint', p, 'SPACE — push the lever down');
|
this.hintEl = el('div', 'hint', p, 'SPACE — push the lever down');
|
||||||
|
// Never-served-a-slice players get the hints at coaching volume.
|
||||||
|
try {
|
||||||
|
if (!localStorage.getItem('toastsim-coached')) this.hintEl.classList.add('coach');
|
||||||
|
} catch { /* storage blocked — quiet hints are fine */ }
|
||||||
this.setSpread(this.spreadId);
|
this.setSpread(this.spreadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,6 +310,10 @@ export class KitchenView implements View {
|
|||||||
|
|
||||||
serve(): void {
|
serve(): void {
|
||||||
if (this.phase !== 'spreading') return;
|
if (this.phase !== 'spreading') return;
|
||||||
|
if (this.hintEl.classList.contains('coach')) {
|
||||||
|
this.hintEl.classList.remove('coach');
|
||||||
|
try { localStorage.setItem('toastsim-coached', '1'); } catch { /* fine */ }
|
||||||
|
}
|
||||||
this.onServed?.();
|
this.onServed?.();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -117,6 +117,20 @@ canvas#c {
|
|||||||
min-height: 14px;
|
min-height: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* First-ever session: same hints, but loud enough to actually teach.
|
||||||
|
The class comes off for good once the first slice has been served. */
|
||||||
|
.toast-panel .hint.coach {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--gold);
|
||||||
|
animation: coach-pulse 1.6s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes coach-pulse {
|
||||||
|
0%, 100% { opacity: 1; }
|
||||||
|
50% { opacity: 0.55; }
|
||||||
|
}
|
||||||
|
|
||||||
/* Pressure gauge: fill = what your wrist is making, gold = what the spread
|
/* Pressure gauge: fill = what your wrist is making, gold = what the spread
|
||||||
needs to flow, red = where spreading becomes scraping. */
|
needs to flow, red = where spreading becomes scraping. */
|
||||||
.toast-panel .gauge {
|
.toast-panel .gauge {
|
||||||
@ -379,6 +393,11 @@ canvas#c {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
/* Four buttons plus the stamp outgrow the 380px column on plenty of
|
||||||
|
windows; without wrap, NEXT ORDER is shoved past the viewport edge
|
||||||
|
and the game looks unfinishable. */
|
||||||
|
flex-wrap: wrap;
|
||||||
|
row-gap: 10px;
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,6 +435,8 @@ canvas#c {
|
|||||||
.judge-btns {
|
.judge-btns {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user