108 lines
5.2 KiB
Markdown
108 lines
5.2 KiB
Markdown
# Delfin Tippen
|
||
|
||
Ein Lernspiel fürs Zehnfingerschreiben auf einer deutschen QWERTZ-Tastatur, gebaut für
|
||
eine Sechsjährige, die Delfine mag. Alles auf Deutsch.
|
||
|
||
Technisch ein Geschwister des Musik-Players in `../web` — React 19, TypeScript, Vite,
|
||
keine Laufzeit-Abhängigkeiten außer React, dieselbe oklch-Glasoptik und dieselbe
|
||
Nunito — aber **vollständig entkoppelt**: eigenes Vite-Projekt, eigener Dev-Server,
|
||
kein Backend, kein gemeinsamer Build. Was geteilt werden sollte, wurde kopiert.
|
||
|
||
## Loslegen
|
||
|
||
```sh
|
||
npm install
|
||
npm run dev # http://localhost:5174
|
||
npm run test # vitest über src/lib
|
||
npx tsc --noEmit # der eigentliche Check
|
||
npm run build # -> dist/
|
||
```
|
||
|
||
Es braucht eine echte QWERTZ-Tastatur. Der Fortschritt liegt im `localStorage`
|
||
(`delfin-tippen:v1`); zum Zurücksetzen den Key löschen.
|
||
|
||
## Wie es aufgebaut ist
|
||
|
||
Die Logik ist DOM-frei und getestet, die Komponenten sind Layout. Das ist dieselbe
|
||
Aufteilung wie in `../web` und der Grund, warum sechs Spielmodi dieselbe Mechanik teilen
|
||
können, ohne sie sechsmal zu implementieren.
|
||
|
||
| Datei | Wofür |
|
||
|---|---|
|
||
| `lib/fingers.ts` | Die QWERTZ-Belegung: welcher Finger welche Taste, welche Farbe, welche Grundstellungstaste. |
|
||
| `lib/curriculum.ts` | 48 Lektionen in 5 Welten. Höchstens zwei neue Tasten pro Lektion, mit Übungslektionen dazwischen. |
|
||
| `lib/generator.ts` | Was getippt wird — Übungszeilen aus den aktiven Tasten, echte Wörter sobald möglich. |
|
||
| `lib/engine.ts` | Die Tippmechanik: ein Tastendruck rein, ein neuer Zustand und Ereignisse raus. Pur. |
|
||
| `lib/grading.ts` | Zeichen pro Minute, Genauigkeit, Sterne, Tier. |
|
||
| `lib/progress.ts` | Was das Spiel sich merkt, und wann die nächste Lektion aufgeht. |
|
||
| `hooks/useRun.ts` | Der dünne Adapter zwischen echten Tastendrücken und `engine.ts`. |
|
||
|
||
## Die Entscheidungen, die das Spiel ausmachen
|
||
|
||
Vier davon sind bewusst anders, als man es zuerst bauen würde. Sie stehen ausführlicher
|
||
in den Dateikommentaren:
|
||
|
||
**Tempo schaltet nichts frei.** Die nächste Lektion geht bei 93 % Treffern auf — ohne
|
||
jede Geschwindigkeitsbedingung. Wer langsam und sorgfältig tippt, kommt durch den ganzen
|
||
Kurs. Tempo bringt nur das Tier. Zusätzlich geht die nächste Lektion nach fünf Versuchen
|
||
ohnehin auf, damit niemand an einer Taste hängen bleibt.
|
||
|
||
**`punkte = tempo × genauigkeit³`.** Die Lehrbuchformel `netto = brutto − fehler/minute`
|
||
wird bei einem Anfänger negativ, und ein negatives Ergebnis darf hier nie erscheinen.
|
||
Multiplikativ kann das nicht passieren: 95 % Genauigkeit behalten 86 % des Tempos, 90 %
|
||
behalten 73 %.
|
||
|
||
**Eine falsche Taste rückt nicht vor und zählt pro Stelle nur einmal.** Es gibt kein
|
||
Backspace und keine zerschossene Zeile zum Anstarren, und zehnmal panisch dieselbe
|
||
falsche Taste ist ein Fehler, nicht zehn.
|
||
|
||
**Es gibt keinen Verloren-Bildschirm.** Eine schwache Runde zeigt weniger Sterne und ein
|
||
langsameres Tier — nie ein rotes X, nie einen Summer, und die Perlen steigen immer.
|
||
|
||
## Die sechs Spielmodi
|
||
|
||
Alle sechs laufen über dieselbe Mechanik (`lib/engine.ts`) und landen in derselben
|
||
Bewertung. Sie unterscheiden sich nur darin, *wie* das Ziel gezeigt wird — deshalb ist
|
||
ein siebter Modus eine Datei und eine Zeile, keine zweite Spiellogik.
|
||
|
||
| Modus | Was man sieht | Wofür |
|
||
|---|---|---|
|
||
| 🤿 Tauchgang | Eine Zeile mit Cursor | Die Kernübung. Sie zählt fürs Freischalten. |
|
||
| 🫧 Blasenplatzen | Blasen steigen auf, eine pro Buchstabe | Tastenlage, weiche Uhr |
|
||
| 🦑 Quallenalarm | Sechs Quallen, eine leuchtet | Reine Tastenlage — erst suchen, dann tippen |
|
||
| 🐟 Fütterungszeit | Fische mit Wörtern schwimmen zum Delfin | Ganze Wörter statt Buchstaben |
|
||
| 🐬 Delfinrennen | Zwei Bahnen: du gegen deinen Rekord | Tempo, gegen den einzigen fairen Gegner |
|
||
| 🦪 Perlentaucher | Eine Muschel, ein Wort, eine Perlenkette | Genauigkeit — **ohne jede Uhr** |
|
||
|
||
Beim Delfinrennen ist der Gegner der Geist des eigenen besten Laufs: die Tastenzeiten
|
||
liegen in `progress.lessons[id].ghost` und werden gegen die Uhr abgespielt. Gegen sich
|
||
selbst zu rennen ist das einzige Wettkampfformat, das nicht entmutigen kann — der Gegner
|
||
ist per Definition genau so gut, wie man selbst war. Vor dem ersten Rekord schwimmt eine
|
||
absichtlich schlagbare Krabbe.
|
||
|
||
## Das Aquarium
|
||
|
||
Wer eine Welt schafft, bekommt ein Haustier — Clownfisch, Krake, Seepferdchen,
|
||
Schildkröte, Perlmuschel. Es zieht für immer ein und schwimmt ab dann frei hinter jedem
|
||
Bildschirm herum; während einer Runde nur blass, damit es nicht mit der Zeile
|
||
konkurriert. Das Schwimmen ist ein purer, getesteter Schritt in `lib/aquarium.ts`,
|
||
`components/AquariumTiere.tsx` zeichnet nur.
|
||
|
||
Ein neues Tier: die Zeichnung (auf schwarzem Hintergrund) nach `art/aquarium/` legen,
|
||
|
||
```sh
|
||
scripts/aquarium-bild.sh art/aquarium/qualle.png public/aquarium/qualle.webp
|
||
```
|
||
|
||
und in `KREATUREN` eintragen. Das Skript entfernt den Hintergrund als zusammenhängende
|
||
Fläche statt als Farbe — schwarze Augen und Wimpern bleiben stehen — und rechnet die
|
||
Kanten aus dem Schwarz heraus, damit kein dunkler Rand bleibt.
|
||
|
||
## Stand
|
||
|
||
Fertig und spielbar: alle 48 Lektionen, alle sechs Modi, Freischalten, Bewertung,
|
||
Tierleiter, Aquarium, Sprachausgabe und die Bildschirmtastatur.
|
||
|
||
Noch offen: die Geschichten am Ende jeder Welt, der Eltern-Bildschirm (`?eltern=1`) und
|
||
eine Welt 6 mit der Zahlenreihe.
|