Initial commit - Kinderspiele
This commit is contained in:
@@ -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>
|
||||
Reference in New Issue
Block a user