Regenbogenland entfernen — Sterne sind die höchste Stufe
This commit is contained in:
parent
60a0fe4297
commit
8947a28e59
|
|
@ -9,12 +9,7 @@
|
||||||
--c-rocket-fin: #4a4a6e;
|
--c-rocket-fin: #4a4a6e;
|
||||||
--c-flame-inner: #fff4b3;
|
--c-flame-inner: #fff4b3;
|
||||||
--c-flame-outer: #ff8a3d;
|
--c-flame-outer: #ff8a3d;
|
||||||
--c-rainbow-1: #ff5555;
|
--c-star: #ffe34a;
|
||||||
--c-rainbow-2: #ffa84a;
|
|
||||||
--c-rainbow-3: #ffe34a;
|
|
||||||
--c-rainbow-4: #6cdc6c;
|
|
||||||
--c-rainbow-5: #4ab3ff;
|
|
||||||
--c-rainbow-6: #b06cff;
|
|
||||||
--c-correct: #5fd07a;
|
--c-correct: #5fd07a;
|
||||||
--c-text: #1f1f3a;
|
--c-text: #1f1f3a;
|
||||||
--c-text-on-dark: #ffffff;
|
--c-text-on-dark: #ffffff;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
// boost — Raketenschub (Whoosh, niedrig)
|
// boost — Raketenschub (Whoosh, niedrig)
|
||||||
// level — neue Stufe (Akkord aufsteigend)
|
// level — neue Stufe (Akkord aufsteigend)
|
||||||
// countdown — letzte 5 Sekunden (Tick pro Sekunde, höher werdend)
|
// countdown — letzte 5 Sekunden (Tick pro Sekunde, höher werdend)
|
||||||
// fanfare — Regenbogenland erreicht (kurze Tonfolge)
|
// fanfare — Sterne erreicht / Runde gewonnen (kurze Tonfolge)
|
||||||
|
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
import { settings } from '../stores/settings';
|
import { settings } from '../stores/settings';
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,15 @@
|
||||||
import Cloud from '../svg/Cloud.svelte';
|
import Cloud from '../svg/Cloud.svelte';
|
||||||
import Moon from '../svg/Moon.svelte';
|
import Moon from '../svg/Moon.svelte';
|
||||||
import Star from '../svg/Star.svelte';
|
import Star from '../svg/Star.svelte';
|
||||||
import Rainbow from '../svg/Rainbow.svelte';
|
|
||||||
|
|
||||||
import { STAGE_THRESHOLDS } from '../../game/stages';
|
import { STAGE_THRESHOLDS } from '../../game/stages';
|
||||||
|
|
||||||
type Props = { correct: number; won: boolean };
|
type Props = { correct: number; won: boolean };
|
||||||
let { correct, won }: Props = $props();
|
let { correct, won }: Props = $props();
|
||||||
|
|
||||||
// Höhenpositionen 0..1 entlang der Bahn (von unten = 0 nach oben = 1)
|
// Höhenpositionen 0..1 entlang der Bahn (von unten = 0 nach oben = 1); Sterne sind oben.
|
||||||
const STAGE_Y = [0.05, 0.25, 0.45, 0.65, 0.85, 0.97] as const;
|
const STAGE_Y = [0.05, 0.25, 0.45, 0.65, 0.85] as const;
|
||||||
|
const WIN_Y = 0.95; // beim Sieg fliegt die Rakete hoch hinauf zu den Sternen
|
||||||
|
|
||||||
// Rakete bewegt sich kontinuierlich pro richtiger Antwort: bei den Schwellen-Counts
|
// Rakete bewegt sich kontinuierlich pro richtiger Antwort: bei den Schwellen-Counts
|
||||||
// sitzt sie genau auf der jeweiligen Stufen-Markierung, dazwischen wird interpoliert.
|
// sitzt sie genau auf der jeweiligen Stufen-Markierung, dazwischen wird interpoliert.
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
}
|
}
|
||||||
return STAGE_Y[4];
|
return STAGE_Y[4];
|
||||||
}
|
}
|
||||||
const rocketY = $derived(won ? STAGE_Y[5] : yFor(correct));
|
const rocketY = $derived(won ? WIN_Y : yFor(correct));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="track" class:won>
|
<div class="track" class:won>
|
||||||
|
|
@ -48,9 +48,6 @@
|
||||||
<Star size={20} color="#fff" />
|
<Star size={20} color="#fff" />
|
||||||
<Star size={24} color="#a8e8ff" />
|
<Star size={24} color="#a8e8ff" />
|
||||||
</div>
|
</div>
|
||||||
<div class="marker rainbow" style="bottom: {STAGE_Y[5] * 100}%" class:visible={won}>
|
|
||||||
<Rainbow size={140} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="rocket" style="bottom: calc({rocketY * 100}% - 60px)" aria-hidden="true">
|
<div class="rocket" style="bottom: calc({rocketY * 100}% - 60px)" aria-hidden="true">
|
||||||
<Rocket size={120} />
|
<Rocket size={120} />
|
||||||
|
|
@ -86,17 +83,6 @@
|
||||||
}
|
}
|
||||||
.marker.stars { display: flex; gap: 6px; left: 60%; }
|
.marker.stars { display: flex; gap: 6px; left: 60%; }
|
||||||
|
|
||||||
.rainbow {
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, 50%);
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.6s ease, transform 0.6s ease;
|
|
||||||
}
|
|
||||||
.rainbow.visible {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translate(-50%, 50%) scale(1.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rocket {
|
.rocket {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
import Cloud from '../svg/Cloud.svelte';
|
import Cloud from '../svg/Cloud.svelte';
|
||||||
import Moon from '../svg/Moon.svelte';
|
import Moon from '../svg/Moon.svelte';
|
||||||
import Star from '../svg/Star.svelte';
|
import Star from '../svg/Star.svelte';
|
||||||
import Rainbow from '../svg/Rainbow.svelte';
|
|
||||||
|
|
||||||
type Props = { target: Target; highlightDate?: string | null };
|
type Props = { target: Target; highlightDate?: string | null };
|
||||||
let { target, highlightDate = null }: Props = $props();
|
let { target, highlightDate = null }: Props = $props();
|
||||||
|
|
@ -24,7 +23,6 @@
|
||||||
2: { c: Cloud, size: 52 },
|
2: { c: Cloud, size: 52 },
|
||||||
3: { c: Moon, size: 40 },
|
3: { c: Moon, size: 40 },
|
||||||
4: { c: Star, size: 36 },
|
4: { c: Star, size: 36 },
|
||||||
5: { c: Rainbow, size: 56 },
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@
|
||||||
|
|
||||||
const bestStage = $derived(($progress.perTarget[target]?.top5[0]?.stage ?? 0) as number);
|
const bestStage = $derived(($progress.perTarget[target]?.top5[0]?.stage ?? 0) as number);
|
||||||
const runs = $derived($progress.perTarget[target]?.runs ?? 0);
|
const runs = $derived($progress.perTarget[target]?.runs ?? 0);
|
||||||
// Fortschritt 0..1 → Höhe der Mini-Rakete in der Karte
|
// Fortschritt 0..1 → Höhe der Mini-Rakete in der Karte (Stufe 4 = Sterne = ganz oben)
|
||||||
const progressFraction = $derived(Math.min(bestStage / 5, 1));
|
const progressFraction = $derived(Math.min(bestStage / 4, 1));
|
||||||
const masteredAtRainbow = $derived(bestStage >= 5);
|
const masteredAtStars = $derived(bestStage >= 4);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button class="card" type="button" onclick={() => onClick(target)} aria-label={`Zielzahl ${target}`}>
|
<button class="card" type="button" onclick={() => onClick(target)} aria-label={`Zielzahl ${target}`}>
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
<div class="dot dot-5"></div>
|
<div class="dot dot-5"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
{#if masteredAtRainbow}
|
{#if masteredAtStars}
|
||||||
<Crown size={28} />
|
<Crown size={28} />
|
||||||
{/if}
|
{/if}
|
||||||
<span class="runs" aria-label={`${runs} Runden gespielt`}>
|
<span class="runs" aria-label={`${runs} Runden gespielt`}>
|
||||||
|
|
@ -87,7 +87,7 @@
|
||||||
.dot-2 { bottom: 38%; }
|
.dot-2 { bottom: 38%; }
|
||||||
.dot-3 { bottom: 58%; }
|
.dot-3 { bottom: 58%; }
|
||||||
.dot-4 { bottom: 78%; }
|
.dot-4 { bottom: 78%; }
|
||||||
.dot-5 { bottom: 92%; background: var(--c-rainbow-3); width: 6px; height: 6px; }
|
.dot-5 { bottom: 92%; background: var(--c-star); width: 6px; height: 6px; }
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ describe('progress', () => {
|
||||||
|
|
||||||
it('limits top5 to five entries', () => {
|
it('limits top5 to five entries', () => {
|
||||||
let p = emptyProgress();
|
let p = emptyProgress();
|
||||||
for (let i = 0; i < 10; i++) p = recordRun(p, 6, ((i % 5) + 1) as 1 | 2 | 3 | 4 | 5);
|
for (let i = 0; i < 10; i++) p = recordRun(p, 6, ((i % 4) + 1) as 1 | 2 | 3 | 4);
|
||||||
expect(p.perTarget[6].top5.length).toBe(5);
|
expect(p.perTarget[6].top5.length).toBe(5);
|
||||||
expect(p.perTarget[6].runs).toBe(10);
|
expect(p.perTarget[6].runs).toBe(10);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
// Schwellen aus BRAINSTORM.md: 2/4/7/10 richtige Aufgaben pro Stufenaufstieg.
|
// Schwellen aus BRAINSTORM.md: 2/4/7/10 richtige Aufgaben pro Stufenaufstieg.
|
||||||
// Während der Runde zeigt die Rakete Stufen 0..4:
|
// Stufen 0..4: 0 Boden, 1 Luftballon, 2 Wolken, 3 Mond, 4 Sterne.
|
||||||
// 0 Boden, 1 Luftballon, 2 Wolken, 3 Mond, 4 Sterne.
|
// Die Sterne sind die höchste Stufe und zugleich der Sieg (isWin).
|
||||||
// Stufe 5 (Regenbogenland) ist die Win-Celebration — wird nicht durch stageFor zurückgegeben,
|
|
||||||
// sondern durch isWin() signalisiert und im ResultScreen dargestellt.
|
|
||||||
|
|
||||||
export const STAGE_THRESHOLDS = [2, 4, 7, 10] as const;
|
export const STAGE_THRESHOLDS = [2, 4, 7, 10] as const;
|
||||||
export const TOTAL_TO_WIN = 10;
|
export const TOTAL_TO_WIN = 10;
|
||||||
|
|
||||||
export type Stage = 0 | 1 | 2 | 3 | 4 | 5;
|
export type Stage = 0 | 1 | 2 | 3 | 4;
|
||||||
|
|
||||||
export const STAGE_NAMES: Record<Stage, string> = {
|
export const STAGE_NAMES: Record<Stage, string> = {
|
||||||
0: 'boden',
|
0: 'boden',
|
||||||
|
|
@ -15,7 +13,6 @@ export const STAGE_NAMES: Record<Stage, string> = {
|
||||||
2: 'wolken',
|
2: 'wolken',
|
||||||
3: 'mond',
|
3: 'mond',
|
||||||
4: 'sterne',
|
4: 'sterne',
|
||||||
5: 'regenbogenland',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function stageFor(correct: number): Stage {
|
export function stageFor(correct: number): Stage {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import Timer from '../components/game/Timer.svelte';
|
import Timer from '../components/game/Timer.svelte';
|
||||||
import BurstFx from '../components/game/BurstFx.svelte';
|
import BurstFx from '../components/game/BurstFx.svelte';
|
||||||
import IconButton from '../components/shared/IconButton.svelte';
|
import IconButton from '../components/shared/IconButton.svelte';
|
||||||
|
import Star from '../components/svg/Star.svelte';
|
||||||
|
|
||||||
type Props = { target: Target };
|
type Props = { target: Target };
|
||||||
let { target }: Props = $props();
|
let { target }: Props = $props();
|
||||||
|
|
@ -84,7 +85,7 @@
|
||||||
/>
|
/>
|
||||||
{:else if $game.status === 'won'}
|
{:else if $game.status === 'won'}
|
||||||
<div class="end-message">
|
<div class="end-message">
|
||||||
<span class="big">🌈</span>
|
<span class="big"><Star size={200} /></span>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</main>
|
</main>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user