Initial commit - Kinderspiele

This commit is contained in:
OpenClaw
2026-04-26 09:44:19 +02:00
commit 35817527c8
29 changed files with 10949 additions and 0 deletions
+231
View File
@@ -0,0 +1,231 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Reaktionstest - KinderWelt</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; user-select: none; }
body {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh; display: flex; flex-direction: column; align-items: center;
font-family: 'Comic Sans MS', cursive, sans-serif; padding: 20px;
}
h1 { color: white; margin-bottom: 15px; font-size: 26px; }
.game-area {
width: 300px; height: 300px; border-radius: 20px;
display: flex; justify-content: center; align-items: center;
cursor: pointer; transition: all 0.1s; margin: 20px 0;
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
}
.game-area.wait { background: #ff6b6b; }
.game-area.ready { background: #4ade80; animation: pulse 0.5s infinite; }
.game-area.too-soon { background: #feca57; }
.game-area.start { background: #3b82f6; }
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.game-text {
color: white; font-size: 28px; font-weight: bold; text-align: center;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.stats {
display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px;
margin: 20px 0; max-width: 300px;
}
.stat-box {
background: white; border-radius: 15px; padding: 15px; text-align: center;
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
.stat-label { color: #666; font-size: 12px; }
.stat-value { color: #333; font-size: 24px; font-weight: bold; }
.stat-value.best { color: #4ade80; }
.controls { display: flex; gap: 15px; margin-top: 20px; }
.btn {
background: white; border: none; border-radius: 10px; padding: 12px 25px;
font-size: 16px; cursor: pointer; font-family: inherit; font-weight: bold;
}
.btn-back { background: #ff6b6b; color: white; text-decoration: none; }
.instructions { color: white; text-align: center; max-width: 400px; margin: 10px 0; }
.reaction-list { background: white; border-radius: 15px; padding: 15px; margin: 10px 0; }
.reaction-item { display: flex; justify-content: space-between; padding: 5px 0; border-bottom: 1px solid #eee; }
</style>
</head>
<body>
<h1>⚡ Reaktionstest</h1>
<p class="instructions">
Warte bis es GRÜN wird, dann so schnell wie möglich klicken!
<br>Aber nicht zu früh...
</p>
<div class="stats">
<div class="stat-box">
<div class="stat-label">Letzte Zeit</div>
<div class="stat-value" id="lastTime">-</div>
</div>
<div class="stat-box">
<div class="stat-label">Bestzeit</div>
<div class="stat-value best" id="bestTime">-</div>
</div>
</div>
<div class="game-area start" id="gameArea" onclick="handleClick()">
<div class="game-text" id="gameText">
Klicken zum
<br>Starten
</div>
</div>
<div class="reaction-list" id="reactionList" style="display:none">
<p style="font-weight:bold;margin-bottom:10px">Letzte Versuche:</p>
<div id="reactionHistory"></div>
</div>
<div class="controls">
<button class="btn" onclick="resetBest()">🗑️ Reset Bestzeit</button>
<a href="../index.html" class="btn btn-back">⬅️ Zurück</a>
</div>
<script>
// Zustände: start, waiting, ready, too_soon, result
let state = 'start';
let startTime = 0;
let waitTimer = null;
let bestTime = localStorage.getItem('reaktion_bestzeit');
let lastTime = null;
let reactionHistory = [];
const gameArea = document.getElementById('gameArea');
const gameText = document.getElementById('gameText');
// Bestzeit anzeigen
if (bestTime) {
document.getElementById('bestTime').textContent = bestTime + ' ms';
}
function handleClick() {
if (state === 'start') {
// Spiel starten
startWaiting();
} else if (state === 'waiting') {
// Zu früh!
tooSoon();
} else if (state === 'ready') {
// Reaktion messen
measureReaction();
} else if (state === 'too_soon' || state === 'result') {
// Neu starten
resetToStart();
}
}
function startWaiting() {
state = 'waiting';
startTime = 0;
gameArea.className = 'game-area wait';
gameText.innerHTML = 'Warte auf<br>GRÜN...';
// Zufällige Zeit 1-4 Sekunden
const delay = 1000 + Math.random() * 3000;
waitTimer = setTimeout(() => {
if (state === 'waiting') {
state = 'ready';
gameArea.className = 'game-area ready';
gameText.innerHTML = 'JETZT!<br>🖱️ Klick!';
startTime = Date.now();
}
}, delay);
}
function tooSoon() {
clearTimeout(waitTimer);
state = 'too_soon';
gameArea.className = 'game-area too-soon';
gameText.innerHTML = 'Zu früh!<br>😅<br><small>Nochmal klicken</small>';
}
function measureReaction() {
const endTime = Date.now();
const reactionTime = endTime - startTime;
state = 'result';
// Bewertung
let message = '';
let emoji = '';
if (reactionTime < 200) {
message = 'Unglaublich!';
emoji = '🚀';
} else if (reactionTime < 300) {
message = 'Super schnell!';
emoji = '⚡';
} else if (reactionTime < 400) {
message = 'Sehr gut!';
emoji = '👍';
} else if (reactionTime < 600) {
message = 'Gut!';
emoji = '👌';
} else {
message = 'Übe mehr!';
emoji = '💪';
}
gameArea.className = 'game-area wait';
gameText.innerHTML = reactionTime + ' ms<br>' + emoji + '<br><small>' + message + '</small>';
// Speichern
lastTime = reactionTime;
document.getElementById('lastTime').textContent = reactionTime + ' ms';
if (!bestTime || reactionTime < bestTime) {
bestTime = reactionTime;
localStorage.setItem('reaktion_bestzeit', bestTime);
document.getElementById('bestTime').textContent = bestTime + ' ms';
}
// Historie
reactionHistory.unshift({ time: reactionTime });
if (reactionHistory.length > 5) reactionHistory.pop();
updateHistory();
// TTS
if ('speechSynthesis' in window) {
const utterance = new SpeechSynthesisUtterance(reactionTime + ' Millisekunden. ' + message);
utterance.lang = 'de-DE';
utterance.rate = 0.9;
speechSynthesis.speak(utterance);
}
}
function resetToStart() {
state = 'start';
startTime = 0;
gameArea.className = 'game-area start';
gameText.innerHTML = 'Klicken zum<br>Starten';
}
function resetBest() {
localStorage.removeItem('reaktion_bestzeit');
bestTime = null;
document.getElementById('bestTime').textContent = '-';
}
function updateHistory() {
const list = document.getElementById('reactionHistory');
document.getElementById('reactionList').style.display = reactionHistory.length > 0 ? 'block' : 'none';
list.innerHTML = reactionHistory.map((r, i) => {
return '<div class="reaction-item"><span>' + (i+1) + '. Versuch</span><span>' + r.time + ' ms</span></div>';
}).join('');
}
// Touch für Mobile
gameArea.addEventListener('touchstart', function(e) {
e.preventDefault();
handleClick();
});
</script>
</body>
</html>