Der Server bestimmt pro Runde Ziel + alle Items (mit zufaelligen IDs) und validiert
jeden Treffer gegen die Ziel-ID der aktuellen Runde (nonce + itemId). Blindes Spammen
von /api/game/hit bringt damit 0 Punkte. Zusaetzlich Reaktionszeit-Untergrenze und
Mindestabstand; Score weiterhin nach Spielzeit gedeckelt.
- Server: makeRound() + /api/game/start liefert erste Runde, /api/game/hit erwartet
{nonce,itemId} und gibt bei korrektem Treffer die naechste Runde zurueck
- Client: rendert server-gelieferte Runden, sendet geklickte itemId, Vorschub nur bei
Server-Bestaetigung (Sofort-Flash fuers Gefuehl)
- README: Ban-Befehle dokumentiert, Anti-Cheat-Abschnitt aktualisiert
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fuesse.sexy — „Wanted!" 🦶
Ein kleines Arcade-Spiel nach dem Vorbild des „Wanted!"-Minispiels aus New Super Mario Bros.: Oben ein Fahndungsplakat mit einem gesuchten Fuß, unten wuseln viele Füße (in verschiedenen Farben) + etwas Deko herum. Schnapp dir den gesuchten Fuß, bevor die Zeit abläuft — dann kommt sofort ein neues Plakat mit einer anderen Farbe.
- Zeitdruck: Countdown; jeder Treffer gibt Zeit dazu, Fehlklick zieht Zeit ab. Bei 0 → Game-Over.
- Wird schwerer: erst ordentliches Raster, dann wild verteilt, dann Bewegung (erst in 2–3 Gruppen, später einzeln) — und je weiter, desto schneller und mehr Füße.
- Gesucht ist immer ein Fuß, aber die Farbe wechselt jede Runde — nicht auf Autopilot klicken!
- Rangliste: die Top 10 auf der Startseite, serverseitig gespeichert. Nach dem Spiel wird einmal nach dem Namen gefragt (danach gecacht).
Installation
./install.sh
Das Skript installiert alles Nötige, startet den Server im Hintergrund und zeigt die URL. Dann im Browser öffnen: http://:3000 (lokal: http://localhost:3000).
Manuell: npm install && npm start.
Die Füße & Deko erweitern
Alle Bildchen liegen in library/:
library/
feet/ ← die Füße (= die gesuchten Figuren). Farbe = Dateiname.
props/ ← Deko ("andere Bildchen") als Zusatz-Ablenker.
Neue Bildchen einfach in den passenden Ordner legen und Server neu starten — fertig.
Formate: .svg, .png, .webp, .jpg. Für Füße gilt: mind. 2 in library/feet/
(mehr = mehr Farb-Vielfalt). Am besten freigestellt (transparenter Hintergrund), grob
quadratisch.
Woher Bildchen nehmen?
openclipart.org (CC0), svgrepo.com (CC0-Filter), kenney.nl (CC0), pixabay.com. Bei Flaticon/Freepik Namensnennung beachten.
Feintuning
In public/js/app.js oben:
START_TIME,MAX_TIME,BONUS,PENALTY— Timer/Balance.difficulty(score)— Anzahl, Bewegungs-Stufen (grid/scatter/groups/individual) und Tempo je Score.
Rangliste
- Zwei Boards: Hall of Fame (Allzeit-Top-5) + Heute (Top-10). Gespeichert in
data/leaderboard.json(wird automatisch angelegt, überlebt Neustarts). - Anti-Cheat: server-autoritative Runden. Der Server bestimmt pro Runde das Ziel
und alle Items (mit zufälligen IDs) und validiert jeden Treffer gegen die Ziel-ID der
aktuellen Runde (
/api/game/hitmitnonce+itemId). Blindes „Treffer-Spam" bringt dadurch nichts mehr; zusätzlich Reaktionszeit-Untergrenze, Mindestabstand und Deckelung nach echter Spielzeit. Beim Eintragen (/api/score) zählt nur die server-gezählte Trefferzahl. Namen werden beim Anzeigen escaped (kein XSS).Hinweis: In einem Browserspiel bekommt der Client zwangsläufig die Renderdaten — ein eigens gebauter Solver-Bot bleibt theoretisch möglich, 100 % dicht geht nicht.
Verwaltung per CLI
Auf dem Server (im Projektordner):
# Rangliste
node server/admin.js list # beide Boards anzeigen
node server/admin.js delete "Name" # einen bestimmten Spieler löschen
node server/admin.js clear-today # nur die heutige Rangliste leeren
node server/admin.js clear-all # komplette Rangliste leeren
# Bannen (namensbasiert, case-insensitiv)
node server/admin.js ban "Name" # sperren (+ vorhandene Einträge entfernen)
node server/admin.js unban "Name" # Sperre aufheben
node server/admin.js bans # gebannte Namen anzeigen
# Betriebsmodus (wirkt SOFORT, ohne Neustart)
node server/admin.js mode # aktuellen Modus anzeigen
node server/admin.js mode public # Spiel öffentlich unter "/"
node server/admin.js mode private geheim # "/" gesperrt, Spiel nur unter "/geheim"
(Kurzform via npm: npm run lb -- <befehl>.)
- public (Default):
/ist das Spiel. - private:
/zeigt „You are not allowed to play", das Spiel läuft nur unter dem gewählten Pfad (/<pfad>) — praktisch zum Testen im Live-Betrieb.
Deployment (Ausblick)
Normaler Node-Server. Auf einen Node-Host bringen (VPS/LXC/Railway/Render), ./install.sh,
Domain fuesse.sexy per Reverse-Proxy (z.B. Nginx Proxy Manager) darauf zeigen. Für
HTTPS hinter Cloudflare: DNS-Challenge (Cloudflare-Token) im Proxy nutzen.
Projektstruktur
server/index.js schlanker Express-Server (Bildchen-Liste + Rangliste)
public/ Frontend (Startseite, Spiel, Game-Over) — Vanilla JS
library/feet/ die Füße (gesuchte Figuren)
library/props/ Deko-Ablenker
data/ Rangliste (leaderboard.json, zur Laufzeit)
install.sh Ein-Befehl-Setup + detached Start