Rakete steigt schon ab der ersten richtigen Antwort

This commit is contained in:
schmop 2026-05-31 16:12:07 +02:00
parent 97cff09c4e
commit cac6d1810c
3 changed files with 24 additions and 8 deletions

View File

@ -1,5 +1,4 @@
<script lang="ts">
import type { Stage } from '../../game/stages';
import Rocket from '../svg/Rocket.svelte';
import Balloon from '../svg/Balloon.svelte';
import Cloud from '../svg/Cloud.svelte';
@ -7,12 +6,30 @@
import Star from '../svg/Star.svelte';
import Rainbow from '../svg/Rainbow.svelte';
type Props = { stage: Stage; won: boolean };
let { stage, won }: Props = $props();
import { STAGE_THRESHOLDS } from '../../game/stages';
type Props = { correct: number; won: boolean };
let { correct, won }: Props = $props();
// Höhenpositionen 0..1 entlang der Bahn (von unten = 0 nach oben = 1)
const STAGE_Y = [0.05, 0.25, 0.45, 0.65, 0.85, 0.97] as const;
const rocketY = $derived(won ? STAGE_Y[5] : STAGE_Y[stage]);
// Rakete bewegt sich kontinuierlich pro richtiger Antwort: bei den Schwellen-Counts
// sitzt sie genau auf der jeweiligen Stufen-Markierung, dazwischen wird interpoliert.
// So steigt sie schon ab der ersten richtigen Antwort sichtbar.
const BREAKPOINTS = [0, ...STAGE_THRESHOLDS] as const; // [0, 2, 4, 7, 10]
function yFor(c: number): number {
if (c <= 0) return STAGE_Y[0];
for (let i = 1; i < BREAKPOINTS.length; i++) {
if (c <= BREAKPOINTS[i]) {
const lo = BREAKPOINTS[i - 1];
const t = (c - lo) / (BREAKPOINTS[i] - lo);
return STAGE_Y[i - 1] + t * (STAGE_Y[i] - STAGE_Y[i - 1]);
}
}
return STAGE_Y[4];
}
const rocketY = $derived(won ? STAGE_Y[5] : yFor(correct));
</script>
<div class="track" class:won>

View File

@ -1,7 +1,7 @@
<script lang="ts">
import { fade } from 'svelte/transition';
import type { Target } from '../game/tasks';
import { game, stage, timeLeftSeconds, answer, abortGame } from '../stores/game';
import { game, timeLeftSeconds, answer, abortGame } from '../stores/game';
import { goHome, goResult } from '../stores/route';
import { play } from '../audio/soundManager';
import HeightTrack from '../components/game/HeightTrack.svelte';
@ -71,7 +71,7 @@
<div class="layout">
<aside class="track-wrap">
<HeightTrack stage={$stage} won={$game.status === 'won'} />
<HeightTrack correct={$game.correctCount} won={$game.status === 'won'} />
<BurstFx triggerKey={$game.stageBumpKey} />
</aside>
<main class="play">

View File

@ -1,6 +1,6 @@
import { get, writable, derived } from 'svelte/store';
import { generateTask, type Target, type Task } from '../game/tasks';
import { isWin, stageFor, type Stage } from '../game/stages';
import { isWin, stageFor } from '../game/stages';
import { settings } from './settings';
import { recordResult } from './progress';
@ -32,7 +32,6 @@ const initial: GameState = {
export const game = writable<GameState>(initial);
export const stage = derived(game, ($g): Stage => stageFor($g.correctCount));
export const timeLeftSeconds = derived(game, ($g) => Math.max(0, Math.ceil($g.timeLeftMs / 1000)));
let tickHandle: number | null = null;