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
+273
View File
@@ -0,0 +1,273 @@
<!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>Autorennen - KinderWelt</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; user-select: none; }
body {
background: linear-gradient(135deg, #1a472a 0%, #0f2918 100%);
min-height: 100vh; display: flex; flex-direction: column; align-items: center;
font-family: 'Comic Sans MS', cursive, sans-serif; padding: 15px;
}
h1 { color: white; margin-bottom: 10px; font-size: 24px; }
.track-container {
background: #2d3748; border-radius: 15px; padding: 15px;
box-shadow: 0 10px 30px rgba(0,0,0,0.5); margin: 15px 0;
}
.track {
width: 320px; height: 60px; background: linear-gradient(90deg, #4a5568 0%, #718096 50%, #4a5568 100%);
border-radius: 10px; margin: 10px 0; position: relative;
border: 3px solid #e2e8f0; overflow: hidden;
}
.track::before {
content: ''; position: absolute; top: 50%; left: 0; right: 0;
height: 4px; background: repeating-linear-gradient(90deg, #fff 0px, #fff 20px, transparent 20px, transparent 40px);
transform: translateY(-50%);
}
.finish-line {
position: absolute; right: 10px; top: 0; bottom: 0; width: 8px;
background: repeating-linear-gradient(180deg, #fff 0px, #fff 10px, #000 10px, #000 20px);
}
.car {
position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
font-size: 40px; transition: left 0.5s ease-out;
filter: drop-shadow(2px 2px 4px rgba(0,0,0,0.5));
}
.car.moving { animation: bounce 0.3s ease-in-out; }
@keyframes bounce {
0%, 100% { transform: translateY(-50%) scale(1); }
50% { transform: translateY(-60%) scale(1.1); }
}
.dice-container {
perspective: 1000px; margin: 20px 0;
}
.dice {
width: 80px; height: 80px; position: relative;
transform-style: preserve-3d; cursor: pointer;
}
.dice.rolling { animation: rollDice 0.8s ease-out; }
@keyframes rollDice {
0% { transform: rotateX(0) rotateY(0) rotateZ(0); }
100% { transform: rotateX(720deg) rotateY(720deg) rotateZ(360deg); }
}
.face {
position: absolute; width: 80px; height: 80px;
background: white; border: 2px solid #333; border-radius: 12px;
display: flex; justify-content: center; align-items: center;
font-size: 40px; font-weight: bold;
}
.face-1 { transform: rotateY(0deg) translateZ(40px); }
.face-2 { transform: rotateY(90deg) translateZ(40px); }
.face-3 { transform: rotateY(180deg) translateZ(40px); }
.face-4 { transform: rotateY(-90deg) translateZ(40px); }
.face-5 { transform: rotateX(90deg) translateZ(40px); }
.face-6 { transform: rotateX(-90deg) translateZ(40px); }
.dot-grid { display: grid; gap: 5px; }
.dot-grid.col-2 { grid-template-columns: 1fr 1fr; }
.dot { width: 12px; height: 12px; background: #333; border-radius: 50%; }
.status { color: white; font-size: 20px; margin: 15px 0; text-align: center; }
.turn-indicator {
background: rgba(255,255,255,0.2); padding: 10px 20px; border-radius: 20px;
color: white; margin: 10px 0; font-size: 18px;
}
.turn-indicator .player { font-weight: bold; }
.turn-indicator .player.red { color: #ff6b6b; }
.turn-indicator .player.blue { color: #4dabf7; }
.controls { display: flex; gap: 15px; margin-top: 20px; flex-wrap: wrap; justify-content: center; }
.btn {
background: white; border: none; border-radius: 10px; padding: 12px 25px;
font-size: 16px; cursor: pointer; font-family: inherit; font-weight: bold;
}
.btn-roll { background: #4ade80; color: white; font-size: 18px; padding: 15px 40px; }
.btn-roll:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-back { background: #ff6b6b; color: white; text-decoration: none; }
.winner {
position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
background: white; padding: 30px 50px; border-radius: 20px;
text-align: center; display: none; z-index: 100;
box-shadow: 0 10px 50px rgba(0,0,0,0.5);
}
.winner h2 { color: #333; margin-bottom: 15px; }
.winner-emoji { font-size: 60px; }
.instructions { color: #aaa; text-align: center; margin: 10px 0; font-size: 14px; }
</style>
</head>
<body>
<h1>🏎️ Autorennen</h1>
<p class="instructions">Würfle und bewege dein Auto! Wer zuerst im Ziel ist, gewinnt!</p>
<div class="turn-indicator" id="turnIndicator">
<span class="player red">🔴 Rot</span> ist dran!
</div>
<div class="track-container">
<div class="track">
<div class="finish-line"></div>
<div class="car" id="car1">🔴</div>
</div>
<div class="track">
<div class="finish-line"></div>
<div class="car" id="car2">🔵</div>
</div>
</div>
<div class="status" id="status">Klicke auf den Würfel!</div>
<div class="dice-container">
<div class="dice" id="dice" onclick="roll()">
<div class="face face-1"><div class="dot-grid"><div class="dot"></div></div></div>
<div class="face face-2"><div class="dot-grid col-2"><div class="dot"></div><div class="dot"></div></div></div>
<div class="face face-3"><div class="dot-grid col-2"><div class="dot"></div><div class="dot"></div><div class="dot"></div></div></div>
<div class="face face-4"><div class="dot-grid col-2"><div class="dot"></div><div class="dot"></div><div class="dot"></div><div class="dot"></div></div></div>
<div class="face face-5"><div class="dot-grid col-2"><div class="dot"></div><div class="dot"></div><div class="dot"></div><div class="dot"></div><div class="dot"></div></div></div>
<div class="face face-6"><div class="dot-grid col-2"><div class="dot"></div><div class="dot"></div><div class="dot"></div><div class="dot"></div><div class="dot"></div><div class="dot"></div></div></div>
</div>
</div>
<div class="controls">
<button class="btn btn-roll" id="rollBtn" onclick="roll()">🎲 Würfeln</button>
<button class="btn" onclick="resetGame()">🔄 Neustart</button>
<a href="../index.html" class="btn btn-back">⬅️ Zurück</a>
</div>
<div class="winner" id="winner">
<h2>🎉 Gewinner! 🎉</h2>
<div class="winner-emoji" id="winnerEmoji"></div>
<button class="btn btn-roll" onclick="resetGame()" style="margin-top: 20px">🔄 Nochmal</button>
</div>
<script>
const TRACK_LENGTH = 280; // Pixel bis zum Ziel
const STEPS_TO_FINISH = 20; // 20 Felder bis zum Ziel
let positions = [0, 0]; // Position der Autos (in Schritten)
let currentPlayer = 0; // 0 = Rot, 1 = Blau
let rolling = false;
let gameEnded = false;
const cars = [document.getElementById('car1'), document.getElementById('car2')];
const dice = document.getElementById('dice');
const status = document.getElementById('status');
const turnIndicator = document.getElementById('turnIndicator');
const rotations = {
1: 'rotateX(0deg) rotateY(0deg)',
2: 'rotateX(0deg) rotateY(-90deg)',
3: 'rotateX(0deg) rotateY(180deg)',
4: 'rotateX(0deg) rotateY(90deg)',
5: 'rotateX(-90deg) rotateY(0deg)',
6: 'rotateX(90deg) rotateY(0deg)'
};
function roll() {
if (rolling || gameEnded) return;
rolling = true;
// Animation
dice.classList.add('rolling');
// Zufällige Zahl
const result = Math.floor(Math.random() * 6) + 1;
setTimeout(() => {
dice.classList.remove('rolling');
dice.style.transform = rotations[result];
// Auto bewegen
moveCar(currentPlayer, result);
setTimeout(() => {
rolling = false;
}, 500);
}, 800);
}
function moveCar(player, steps) {
const car = cars[player];
car.classList.add('moving');
positions[player] += steps;
// Position berechnen (in Pixel)
const pixelPos = Math.min(positions[player] / STEPS_TO_FINISH * TRACK_LENGTH, TRACK_LENGTH);
car.style.left = (10 + pixelPos) + 'px';
// Status aktualisieren
const playerName = player === 0 ? '🔴 Rot' : '🔵 Blau';
status.textContent = playerName + ' würfelt ' + steps + '!';
// TTS
if ('speechSynthesis' in window) {
const utterance = new SpeechSynthesisUtterance(playerName.replace('🔴', 'Rot').replace('🔵', 'Blau') + ' würfelt ' + steps);
utterance.lang = 'de-DE';
speechSynthesis.speak(utterance);
}
setTimeout(() => {
car.classList.remove('moving');
// Prüfen ob gewonnen
if (positions[player] >= STEPS_TO_FINISH) {
endGame(player);
} else {
// Nächster Spieler
switchPlayer();
}
}, 500);
}
function switchPlayer() {
currentPlayer = currentPlayer === 0 ? 1 : 0;
if (currentPlayer === 0) {
turnIndicator.innerHTML = '<span class="player red">🔴 Rot</span> ist dran!';
} else {
turnIndicator.innerHTML = '<span class="player blue">🔵 Blau</span> ist dran!';
}
}
function endGame(winner) {
gameEnded = true;
const winnerEmoji = winner === 0 ? '🔴' : '🔵';
const winnerName = winner === 0 ? 'Rot' : 'Blau';
document.getElementById('winnerEmoji').textContent = winnerEmoji + ' ' + winnerName + ' gewinnt!';
document.getElementById('winner').style.display = 'block';
if ('speechSynthesis' in window) {
const utterance = new SpeechSynthesisUtterance(winnerName + ' gewinnt das Rennen!');
utterance.lang = 'de-DE';
speechSynthesis.speak(utterance);
}
}
function resetGame() {
positions = [0, 0];
currentPlayer = 0;
gameEnded = false;
rolling = false;
cars.forEach(car => {
car.style.left = '10px';
car.classList.remove('moving');
});
dice.style.transform = rotations[1];
status.textContent = 'Klicke auf den Würfel!';
turnIndicator.innerHTML = '<span class="player red">🔴 Rot</span> ist dran!';
document.getElementById('winner').style.display = 'none';
}
</script>
</body>
</html>