2026-04-18 18:00:02 +02:00
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html lang="de">
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
|
<title>Schildkröte überquert den Fluss</title>
|
|
|
|
|
<style>
|
|
|
|
|
body {
|
|
|
|
|
margin: 0;
|
|
|
|
|
padding: 0;
|
|
|
|
|
background: linear-gradient(to bottom, #87CEEB, #E0F7FA);
|
|
|
|
|
font-family: 'Arial', sans-serif;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: center;
|
|
|
|
|
user-select: none;
|
|
|
|
|
}
|
|
|
|
|
#game-container {
|
|
|
|
|
position: relative;
|
|
|
|
|
margin-top: 20px;
|
|
|
|
|
}
|
|
|
|
|
canvas {
|
|
|
|
|
border: 4px solid #333;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
|
|
|
|
|
background: linear-gradient(to bottom, #4EC0CA 0%, #87CEEB 100%);
|
|
|
|
|
}
|
|
|
|
|
#ui {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 10px;
|
|
|
|
|
left: 10px;
|
|
|
|
|
right: 10px;
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
color: #333;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
text-shadow: 1px 1px 2px white;
|
|
|
|
|
}
|
|
|
|
|
#game-over {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 50%;
|
|
|
|
|
left: 50%;
|
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
|
text-align: center;
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
#game-over h2 {
|
|
|
|
|
font-size: 48px;
|
|
|
|
|
color: #D32F2F;
|
|
|
|
|
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
|
|
|
|
|
}
|
|
|
|
|
#game-over button {
|
|
|
|
|
font-size: 24px;
|
|
|
|
|
padding: 12px 32px;
|
|
|
|
|
border: 3px solid #333;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
background: #4CAF50;
|
|
|
|
|
color: white;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
transition: all 0.3s;
|
|
|
|
|
}
|
|
|
|
|
#game-over button:hover {
|
|
|
|
|
background: #45a049;
|
|
|
|
|
transform: scale(1.05);
|
|
|
|
|
}
|
|
|
|
|
#instructions {
|
|
|
|
|
position: fixed;
|
|
|
|
|
bottom: 20px;
|
|
|
|
|
left: 50%;
|
|
|
|
|
transform: translateX(-50%);
|
|
|
|
|
background: rgba(255,255,255,0.9);
|
|
|
|
|
padding: 12px 24px;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
text-align: center;
|
|
|
|
|
border: 2px solid #333;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
|
|
|
|
<h1 style="color: #1565C0; margin: 20px 0; text-shadow: 2px 2px 4px rgba(0,0,0,0.3);">
|
|
|
|
|
🐢 Schildkröte überquert den Fluss 🐊
|
|
|
|
|
</h1>
|
|
|
|
|
|
|
|
|
|
<div id="game-container">
|
|
|
|
|
<canvas id="gameCanvas" width="800" height="600"></canvas>
|
|
|
|
|
<div id="ui">
|
|
|
|
|
<div>Level: <span id="level">1</span></div>
|
|
|
|
|
<div>Punkte: <span id="score">0</span></div>
|
|
|
|
|
<div>Leben: <span id="lives">3</span></div>
|
|
|
|
|
</div>
|
|
|
|
|
<div id="game-over">
|
|
|
|
|
<h2 id="game-over-title">Spiel vorbei!</h2>
|
|
|
|
|
<p style="font-size: 24px; color: #333;">Dein Ergebnis: <span id="final-score">0</span> Punkte</p>
|
|
|
|
|
<button onclick="restartGame()">Nochmal spielen</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div id="instructions">
|
|
|
|
|
Benutze die Pfeiltasten ⬅️⬆️➡️ zum Bewegen
|
|
|
|
|
</div>
|
2026-04-18 18:35:04 +02:00
|
|
|
|
|
|
|
|
<div id="touch-controls" style="display:none; position:fixed; bottom:20px; width:100%; text-align:center; gap:20px;">
|
|
|
|
|
<button id="btn-left" style="font-size:32px; padding:20px; background:#333; color:white; border-radius:50%; border:none; width:60px; height:60px;">⬅️</button>
|
|
|
|
|
<button id="btn-up" style="font-size:32px; padding:20px; background:#333; color:white; border-radius:50%; border:none; width:60px; height:60px;">⬆️</button>
|
|
|
|
|
<button id="btn-down" style="font-size:32px; padding:20px; background:#333; color:white; border-radius:50%; border:none; width:60px; height:60px;">⬇️</button>
|
|
|
|
|
<button id="btn-right" style="font-size:32px; padding:20px; background:#333; color:white; border-radius:50%; border:none; width:60px; height:60px;">➡️</button>
|
|
|
|
|
</div>
|
2026-04-18 18:00:02 +02:00
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
const canvas = document.getElementById('gameCanvas');
|
|
|
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
|
|
|
|
|
|
// Spielzustand
|
|
|
|
|
let gameRunning = true;
|
|
|
|
|
let score = 0;
|
|
|
|
|
let level = 1;
|
|
|
|
|
let lives = 3;
|
|
|
|
|
|
|
|
|
|
// Schildkröte (Spieler)
|
|
|
|
|
const player = {
|
2026-04-18 18:45:06 +02:00
|
|
|
x: canvas.width / 2 - 20,
|
|
|
|
|
y: canvas.height - 60,
|
|
|
|
|
width: 40,
|
|
|
|
|
height: 40,
|
2026-04-18 18:00:02 +02:00
|
|
|
speed: 5,
|
2026-04-18 18:45:06 +02:00
|
|
|
onLog: false
|
2026-04-18 18:00:02 +02:00
|
|
|
};
|
|
|
|
|
|
2026-04-18 18:45:06 +02:00
|
|
|
// Flusslinien (Bäume zum draufspringen)
|
|
|
|
|
const logs = [];
|
|
|
|
|
const numLogs = 5;
|
2026-04-18 18:00:02 +02:00
|
|
|
|
|
|
|
|
// Bäume (Hindernisse)
|
|
|
|
|
const trees = [];
|
|
|
|
|
const numTrees = 10;
|
|
|
|
|
|
|
|
|
|
// Aligatoren (Gegner)
|
|
|
|
|
const alligators = [];
|
|
|
|
|
const numAlligators = 8;
|
|
|
|
|
|
|
|
|
|
// Initialisierung
|
|
|
|
|
function initGame() {
|
2026-04-18 18:47:35 +02:00
|
|
|
// Logs (Baumstämme im Wasser)
|
|
|
|
|
logs.length = 0;
|
2026-04-18 18:45:06 +02:00
|
|
|
for (let i = 0; i < numLogs; i++) {
|
|
|
|
|
logs.push({
|
|
|
|
|
y: canvas.height - 150 - (i * 60),
|
2026-04-18 18:47:35 +02:00
|
|
|
x: Math.random() * (canvas.width - 100),
|
2026-04-18 18:45:06 +02:00
|
|
|
width: 80 + Math.random() * 60,
|
|
|
|
|
speed: 1 + Math.random() * 1.5,
|
|
|
|
|
direction: i % 2 === 0 ? 1 : -1
|
|
|
|
|
});
|
2026-04-18 18:00:02 +02:00
|
|
|
}
|
|
|
|
|
|
2026-04-18 18:45:06 +02:00
|
|
|
// Bäume (Hindernisse im Gras)
|
2026-04-18 18:00:02 +02:00
|
|
|
trees.length = 0;
|
|
|
|
|
for (let i = 0; i < numTrees; i++) {
|
|
|
|
|
trees.push({
|
|
|
|
|
x: Math.random() * (canvas.width - 50),
|
2026-04-18 18:45:06 +02:00
|
|
|
y: canvas.height - 120 - Math.random() * 300,
|
|
|
|
|
width: 30,
|
|
|
|
|
height: 30
|
2026-04-18 18:00:02 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 18:47:35 +02:00
|
|
|
// Aligatoren (Gegner)
|
2026-04-18 18:00:02 +02:00
|
|
|
alligators.length = 0;
|
|
|
|
|
for (let i = 0; i < numAlligators; i++) {
|
|
|
|
|
alligators.push({
|
|
|
|
|
x: Math.random() * canvas.width,
|
2026-04-18 18:47:35 +02:00
|
|
|
y: 150 + Math.random() * 250,
|
2026-04-18 18:00:02 +02:00
|
|
|
width: 60,
|
|
|
|
|
height: 30,
|
|
|
|
|
speed: 1.5 + Math.random(),
|
|
|
|
|
direction: i % 2 === 0 ? 1 : -1
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 18:35:04 +02:00
|
|
|
// Tastensteuerung für Desktop
|
2026-04-18 18:00:02 +02:00
|
|
|
const keys = {};
|
|
|
|
|
window.addEventListener('keydown', e => keys[e.key] = true);
|
|
|
|
|
window.addEventListener('keyup', e => keys[e.key] = false);
|
|
|
|
|
|
2026-04-18 18:35:04 +02:00
|
|
|
// Touch-Steuerung für Handy
|
|
|
|
|
let touchStartX = 0;
|
|
|
|
|
let touchStartY = 0;
|
|
|
|
|
let touchMoving = false;
|
|
|
|
|
|
|
|
|
|
canvas.addEventListener('touchstart', e => {
|
|
|
|
|
touchMoving = false;
|
|
|
|
|
touchStartX = e.touches[0].clientX;
|
|
|
|
|
touchStartY = e.touches[0].clientY;
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}, {passive: false});
|
|
|
|
|
|
|
|
|
|
canvas.addEventListener('touchmove', e => {
|
|
|
|
|
if (!gameRunning) return;
|
|
|
|
|
touchMoving = true;
|
|
|
|
|
const touchX = e.touches[0].clientX;
|
|
|
|
|
const touchY = e.touches[0].clientY;
|
|
|
|
|
|
|
|
|
|
const deltaX = touchX - touchStartX;
|
|
|
|
|
const deltaY = touchY - touchStartY;
|
|
|
|
|
|
|
|
|
|
if (Math.abs(deltaX) > Math.abs(deltaY)) {
|
|
|
|
|
if (deltaX > 10) player.x += player.speed;
|
|
|
|
|
if (deltaX < -10) player.x -= player.speed;
|
|
|
|
|
} else {
|
|
|
|
|
if (deltaY > 10) player.y += player.speed;
|
|
|
|
|
if (deltaY < -10) player.y -= player.speed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
touchStartX = touchX;
|
|
|
|
|
touchStartY = touchY;
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}, {passive: false});
|
|
|
|
|
|
|
|
|
|
canvas.addEventListener('touchend', e => {
|
|
|
|
|
touchMoving = false;
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}, {passive: false});
|
|
|
|
|
|
|
|
|
|
setupTouchButtons();
|
|
|
|
|
|
|
|
|
|
// Touch-Button-Funktionen
|
|
|
|
|
function setupTouchButtons() {
|
|
|
|
|
const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
|
|
|
|
|
if (isTouchDevice) {
|
|
|
|
|
document.getElementById('touch-controls').style.display = 'flex';
|
|
|
|
|
document.getElementById('instructions').style.display = 'none';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const btns = {
|
|
|
|
|
'btn-left': 'ArrowLeft',
|
|
|
|
|
'btn-right': 'ArrowRight',
|
|
|
|
|
'btn-up': 'ArrowUp',
|
|
|
|
|
'btn-down': 'ArrowDown'
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Object.keys(btns).forEach(id => {
|
|
|
|
|
const btn = document.getElementById(id);
|
|
|
|
|
const key = btns[id];
|
|
|
|
|
|
|
|
|
|
btn.addEventListener('touchstart', (e) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
keys[key] = true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
btn.addEventListener('touchend', (e) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
keys[key] = false;
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 18:00:02 +02:00
|
|
|
// Eingabeverarbeitung
|
|
|
|
|
function handleInput() {
|
|
|
|
|
if (!gameRunning) return;
|
|
|
|
|
|
2026-04-18 18:35:04 +02:00
|
|
|
// Touch-Steuerung (Vorrang)
|
|
|
|
|
if (!touchMoving) {
|
|
|
|
|
if (keys['ArrowLeft']) player.x -= player.speed;
|
|
|
|
|
if (keys['ArrowRight']) player.x += player.speed;
|
|
|
|
|
if (keys['ArrowUp']) player.y -= player.speed;
|
|
|
|
|
if (keys['ArrowDown']) player.y += player.speed;
|
|
|
|
|
}
|
2026-04-18 18:00:02 +02:00
|
|
|
|
|
|
|
|
// Grenzen
|
|
|
|
|
if (player.x < 0) player.x = 0;
|
|
|
|
|
if (player.x > canvas.width - player.width) player.x = canvas.width - player.width;
|
|
|
|
|
if (player.y < 0) player.y = 0;
|
|
|
|
|
if (player.y > canvas.height - player.height) player.y = canvas.height - player.height;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 18:45:06 +02:00
|
|
|
// Bäume bewegen
|
|
|
|
|
function moveLogs() {
|
|
|
|
|
logs.forEach(log => {
|
|
|
|
|
log.x += log.speed * log.direction;
|
|
|
|
|
if (log.x < -200) log.x = canvas.width;
|
|
|
|
|
if (log.x > canvas.width) log.x = -200;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 19:18:19 +02:00
|
|
|
// Bäume bewegen
|
|
|
|
|
function moveLogs() {
|
|
|
|
|
logs.forEach(log => {
|
|
|
|
|
log.x += log.speed * log.direction;
|
|
|
|
|
if (log.x < -200) log.x = canvas.width;
|
|
|
|
|
if (log.x > canvas.width) log.x = -200;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 18:00:02 +02:00
|
|
|
// Aligatoren bewegen
|
|
|
|
|
function moveAlligators() {
|
|
|
|
|
alligators.forEach(alligator => {
|
|
|
|
|
alligator.x += alligator.speed * alligator.direction;
|
|
|
|
|
|
|
|
|
|
// zurückspringen am Rand
|
|
|
|
|
if (alligator.x < -50) alligator.x = canvas.width;
|
|
|
|
|
if (alligator.x > canvas.width) alligator.x = -50;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Kollisionserkennung
|
|
|
|
|
function checkCollisions() {
|
|
|
|
|
// Aligatoren
|
|
|
|
|
alligators.forEach(alligator => {
|
|
|
|
|
if (player.x < alligator.x + alligator.width &&
|
|
|
|
|
player.x + player.width > alligator.x &&
|
|
|
|
|
player.y < alligator.y + alligator.height &&
|
|
|
|
|
player.y + player.height > alligator.y) {
|
|
|
|
|
loseLife();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2026-04-18 18:45:06 +02:00
|
|
|
// Bäume (Hindernisse im Gras)
|
|
|
|
|
trees.forEach(tree => {
|
|
|
|
|
if (player.x < tree.x + tree.width &&
|
|
|
|
|
player.x + player.width > tree.x &&
|
|
|
|
|
player.y < tree.y + tree.height &&
|
|
|
|
|
player.y + player.height > tree.y) {
|
|
|
|
|
loseLife();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Bäume im Wasser (Logs) - Spieler bewegt sich mit
|
|
|
|
|
player.onLog = false;
|
|
|
|
|
logs.forEach(log => {
|
|
|
|
|
if (player.y > 100 && player.y < 450) {
|
|
|
|
|
if (player.x < log.x + log.width &&
|
|
|
|
|
player.x + player.width > log.x &&
|
|
|
|
|
player.y + player.height > log.y - 20 &&
|
|
|
|
|
player.y < log.y) {
|
|
|
|
|
player.x += log.speed * log.direction;
|
|
|
|
|
player.onLog = true;
|
|
|
|
|
}
|
2026-04-18 18:00:02 +02:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Ziel erreicht?
|
2026-04-18 18:45:06 +02:00
|
|
|
if (player.y < 60) {
|
2026-04-18 18:00:02 +02:00
|
|
|
levelUp();
|
|
|
|
|
}
|
2026-04-18 18:45:06 +02:00
|
|
|
|
|
|
|
|
// Ins Wasser fallen?
|
|
|
|
|
if (player.y > 100 && player.y < 450 && !player.onLog) {
|
|
|
|
|
loseLife();
|
|
|
|
|
}
|
2026-04-18 18:00:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function loseLife() {
|
|
|
|
|
lives--;
|
|
|
|
|
document.getElementById('lives').textContent = lives;
|
|
|
|
|
player.x = canvas.width / 2 - 25;
|
|
|
|
|
player.y = canvas.height - 70;
|
|
|
|
|
|
|
|
|
|
if (lives <= 0) {
|
|
|
|
|
gameOver();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function levelUp() {
|
|
|
|
|
level++;
|
|
|
|
|
score += 100;
|
|
|
|
|
document.getElementById('level').textContent = level;
|
|
|
|
|
document.getElementById('score').textContent = score;
|
|
|
|
|
|
|
|
|
|
// Schwierigkeit erhöhen
|
|
|
|
|
player.speed += 0.5;
|
|
|
|
|
|
|
|
|
|
//Reset Player
|
|
|
|
|
player.x = canvas.width / 2 - 25;
|
|
|
|
|
player.y = canvas.height - 70;
|
|
|
|
|
|
|
|
|
|
// Aligatoren beschleunigen
|
|
|
|
|
alligators.forEach(a => a.speed += 0.3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Zeichnen
|
|
|
|
|
function draw() {
|
|
|
|
|
// Hintergrund
|
|
|
|
|
ctx.fillStyle = '#4EC0CA';
|
|
|
|
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
|
|
|
|
|
|
|
|
// Startzone (Gras)
|
|
|
|
|
ctx.fillStyle = '#4CAF50';
|
|
|
|
|
ctx.fillRect(0, canvas.height - 100, canvas.width, 50);
|
2026-04-18 18:40:18 +02:00
|
|
|
// Grasdetails
|
|
|
|
|
ctx.fillStyle = '#388E3C';
|
|
|
|
|
for (let i = 0; i < canvas.width; i += 30) {
|
|
|
|
|
ctx.fillRect(i, canvas.height - 90, 5, 5);
|
|
|
|
|
ctx.fillRect(i + 15, canvas.height - 95, 5, 5);
|
|
|
|
|
}
|
2026-04-18 18:00:02 +02:00
|
|
|
|
|
|
|
|
// Zielzone (Gras oben)
|
|
|
|
|
ctx.fillStyle = '#4CAF50';
|
|
|
|
|
ctx.fillRect(0, 0, canvas.width, 50);
|
|
|
|
|
ctx.fillStyle = '#2E7D32';
|
|
|
|
|
ctx.fillText('🏆 ZIEL 🏆', canvas.width/2 - 50, 30);
|
2026-04-18 18:40:18 +02:00
|
|
|
// Grasdetails
|
|
|
|
|
ctx.fillStyle = '#388E3C';
|
|
|
|
|
for (let i = 0; i < canvas.width; i += 30) {
|
|
|
|
|
ctx.fillRect(i, 10, 5, 5);
|
|
|
|
|
ctx.fillRect(i + 15, 5, 5, 5);
|
|
|
|
|
}
|
2026-04-18 18:00:02 +02:00
|
|
|
|
|
|
|
|
// Flüsse
|
|
|
|
|
ctx.fillStyle = '#2196F3';
|
2026-04-18 18:45:06 +02:00
|
|
|
logs.forEach(log => {
|
|
|
|
|
ctx.fillRect(0, log.y - 40, canvas.width, 40);
|
2026-04-18 18:40:18 +02:00
|
|
|
// Welleneffekt
|
|
|
|
|
ctx.fillStyle = '#42A5F5';
|
|
|
|
|
ctx.beginPath();
|
2026-04-18 18:45:06 +02:00
|
|
|
ctx.moveTo(0, log.y - 20);
|
2026-04-18 18:40:18 +02:00
|
|
|
for (let x = 0; x < canvas.width; x += 20) {
|
2026-04-18 18:45:06 +02:00
|
|
|
ctx.lineTo(x, log.y - 20 + Math.sin(x + Date.now()/200 + log.y)*5);
|
2026-04-18 18:40:18 +02:00
|
|
|
}
|
2026-04-18 18:45:06 +02:00
|
|
|
ctx.lineTo(canvas.width, log.y - 10);
|
|
|
|
|
ctx.lineTo(0, log.y - 10);
|
2026-04-18 18:40:18 +02:00
|
|
|
ctx.fill();
|
|
|
|
|
ctx.fillStyle = '#2196F3';
|
2026-04-18 18:00:02 +02:00
|
|
|
});
|
|
|
|
|
|
2026-04-18 18:45:06 +02:00
|
|
|
// Logs (Baumstämme im Wasser)
|
|
|
|
|
logs.forEach(log => {
|
|
|
|
|
// Baumstamm
|
|
|
|
|
ctx.fillStyle = '#795548';
|
|
|
|
|
ctx.fillRect(log.x, log.y - 20, log.width, 20);
|
|
|
|
|
// Details
|
|
|
|
|
ctx.fillStyle = '#5D4037';
|
|
|
|
|
ctx.fillRect(log.x + 5, log.y - 18, 5, 16);
|
|
|
|
|
ctx.fillRect(log.x + log.width - 10, log.y - 18, 5, 16);
|
2026-04-18 18:00:02 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Aligatoren
|
|
|
|
|
alligators.forEach(alligator => {
|
|
|
|
|
// Körper
|
|
|
|
|
ctx.fillStyle = '#1B5E20';
|
2026-04-18 18:40:18 +02:00
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.ellipse(alligator.x + alligator.width/2, alligator.y + alligator.height/2, alligator.width/2, alligator.height/2, 0, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
// Kopf
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.arc(alligator.x, alligator.y + alligator.height/2, 12, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
2026-04-18 18:00:02 +02:00
|
|
|
// Augen
|
|
|
|
|
ctx.fillStyle = 'white';
|
|
|
|
|
ctx.beginPath();
|
2026-04-18 18:40:18 +02:00
|
|
|
ctx.arc(alligator.x + 5, alligator.y + alligator.height/2 - 5, 3, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
ctx.fillStyle = 'black';
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.arc(alligator.x + 5, alligator.y + alligator.height/2 - 5, 1, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
// Schuppen
|
|
|
|
|
ctx.fillStyle = '#2E7D32';
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.arc(alligator.x + alligator.width/2 - 10, alligator.y + alligator.height/2 + 5, 5, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.arc(alligator.x + alligator.width/2 + 10, alligator.y + alligator.height/2 + 5, 5, 0, Math.PI * 2);
|
2026-04-18 18:00:02 +02:00
|
|
|
ctx.fill();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Schildkröte
|
2026-04-18 18:40:18 +02:00
|
|
|
// Panzer
|
|
|
|
|
ctx.fillStyle = '#333';
|
2026-04-18 18:00:02 +02:00
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.ellipse(player.x + player.width/2, player.y + player.height/2, player.width/2, player.height/2, 0, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
2026-04-18 18:40:18 +02:00
|
|
|
// Muster auf Panzer
|
|
|
|
|
ctx.strokeStyle = '#555';
|
|
|
|
|
ctx.lineWidth = 2;
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.moveTo(player.x + player.width/2 - 10, player.y + player.height/2 - 10);
|
|
|
|
|
ctx.lineTo(player.x + player.width/2 + 10, player.y + player.height/2 + 10);
|
|
|
|
|
ctx.stroke();
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.moveTo(player.x + player.width/2 + 10, player.y + player.height/2 - 10);
|
|
|
|
|
ctx.lineTo(player.x + player.width/2 - 10, player.y + player.height/2 + 10);
|
|
|
|
|
ctx.stroke();
|
2026-04-18 18:00:02 +02:00
|
|
|
// Kopf
|
|
|
|
|
ctx.fillStyle = '#689F38';
|
|
|
|
|
ctx.beginPath();
|
2026-04-18 18:40:18 +02:00
|
|
|
ctx.arc(player.x + player.width/2, player.y + player.height - 8, 10, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
// Augen
|
|
|
|
|
ctx.fillStyle = 'white';
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.arc(player.x + player.width/2 - 4, player.y + player.height - 10, 3, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.arc(player.x + player.width/2 + 4, player.y + player.height - 10, 3, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
ctx.fillStyle = 'black';
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.arc(player.x + player.width/2 - 4, player.y + player.height - 10, 1, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.arc(player.x + player.width/2 + 4, player.y + player.height - 10, 1, 0, Math.PI * 2);
|
2026-04-18 18:00:02 +02:00
|
|
|
ctx.fill();
|
|
|
|
|
// Beine
|
|
|
|
|
ctx.fillStyle = '#689F38';
|
2026-04-18 18:40:18 +02:00
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.arc(player.x + 8, player.y + 28, 8, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.arc(player.x + player.width - 8, player.y + 28, 8, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.arc(player.x + 8, player.y + player.height - 12, 8, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.arc(player.x + player.width - 8, player.y + player.height - 12, 8, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
2026-04-18 18:00:02 +02:00
|
|
|
|
|
|
|
|
// Wolkeneffekt (Hintergrund)
|
|
|
|
|
ctx.fillStyle = 'rgba(255,255,255,0.6)';
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.arc(100, 100, 30, 0, Math.PI * 2);
|
|
|
|
|
ctx.arc(140, 100, 40, 0, Math.PI * 2);
|
|
|
|
|
ctx.arc(180, 100, 30, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.arc(canvas.width - 150, 150, 35, 0, Math.PI * 2);
|
|
|
|
|
ctx.arc(canvas.width - 100, 150, 45, 0, Math.PI * 2);
|
|
|
|
|
ctx.arc(canvas.width - 50, 150, 35, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Spiel-Loop
|
|
|
|
|
function gameLoop() {
|
|
|
|
|
if (!gameRunning) return;
|
|
|
|
|
|
|
|
|
|
handleInput();
|
|
|
|
|
moveAlligators();
|
2026-04-18 19:24:53 +02:00
|
|
|
moveLogs();
|
2026-04-18 18:00:02 +02:00
|
|
|
checkCollisions();
|
|
|
|
|
draw();
|
|
|
|
|
|
|
|
|
|
requestAnimationFrame(gameLoop);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function gameOver() {
|
|
|
|
|
gameRunning = false;
|
|
|
|
|
document.getElementById('game-over').style.display = 'block';
|
|
|
|
|
document.getElementById('final-score').textContent = score;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function restartGame() {
|
|
|
|
|
score = 0;
|
|
|
|
|
level = 1;
|
|
|
|
|
lives = 3;
|
|
|
|
|
player.speed = 5;
|
|
|
|
|
document.getElementById('level').textContent = level;
|
|
|
|
|
document.getElementById('score').textContent = score;
|
|
|
|
|
document.getElementById('lives').textContent = lives;
|
|
|
|
|
document.getElementById('game-over').style.display = 'none';
|
|
|
|
|
|
|
|
|
|
// Reset
|
|
|
|
|
player.x = canvas.width / 2 - 25;
|
|
|
|
|
player.y = canvas.height - 70;
|
|
|
|
|
|
|
|
|
|
alligators.forEach(a => {
|
|
|
|
|
a.speed = 1.5 + Math.random();
|
|
|
|
|
a.x = Math.random() * canvas.width;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
gameRunning = true;
|
|
|
|
|
initGame();
|
|
|
|
|
gameLoop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start
|
|
|
|
|
initGame();
|
|
|
|
|
gameLoop();
|
|
|
|
|
</script>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|