321 lines
9.9 KiB
HTML
321 lines
9.9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Emoji Doodle Jump</title>
|
|
<script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
|
|
<style>
|
|
body {
|
|
margin: 0;
|
|
overflow: hidden;
|
|
background: #f0f0f0;
|
|
font-family: Arial, sans-serif;
|
|
touch-action: none;
|
|
}
|
|
|
|
#gameContainer {
|
|
position: relative;
|
|
width: 320px;
|
|
height: 480px;
|
|
margin: 20px auto;
|
|
}
|
|
|
|
#canvas {
|
|
background: linear-gradient(#87CEEB, #E0F6FF);
|
|
border-radius: 10px;
|
|
}
|
|
|
|
#lives {
|
|
position: absolute;
|
|
top: 10px;
|
|
left: 10px;
|
|
font-size: 24px;
|
|
}
|
|
|
|
#score {
|
|
position: absolute;
|
|
top: 10px;
|
|
right: 10px;
|
|
font-size: 24px;
|
|
color: white;
|
|
}
|
|
|
|
.popup {
|
|
position: fixed;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%);
|
|
background: white;
|
|
padding: 20px;
|
|
border-radius: 10px;
|
|
box-shadow: 0 0 20px rgba(0,0,0,0.2);
|
|
text-align: center;
|
|
display: none;
|
|
}
|
|
|
|
#charSelect {
|
|
display: flex;
|
|
gap: 10px;
|
|
font-size: 40px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.emoji:hover {
|
|
transform: scale(1.2);
|
|
}
|
|
|
|
button {
|
|
background: #4CAF50;
|
|
color: white;
|
|
border: none;
|
|
padding: 10px 20px;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
margin: 5px;
|
|
}
|
|
|
|
#instructions {
|
|
max-width: 320px;
|
|
margin: 20px auto;
|
|
padding: 10px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="gameContainer">
|
|
<div id="lives">❤️❤️❤️</div>
|
|
<div id="score">0</div>
|
|
<canvas id="canvas" width="320" height="480"></canvas>
|
|
</div>
|
|
|
|
<div id="charSelectPopup" class="popup">
|
|
<h3>Wähle deinen Charakter!</h3>
|
|
<div id="charSelect">
|
|
<div class="emoji">💩</div>
|
|
<div class="emoji">🤡</div>
|
|
<div class="emoji">👾</div>
|
|
<div class="emoji">🍌</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="gameOverPopup" class="popup">
|
|
<h3>Game Over!</h3>
|
|
<p>Highscore: <span id="highscore">0</span></p>
|
|
<button onclick="takeScreenshot()">Screenshot</button>
|
|
<button onclick="startGame()">Neustart</button>
|
|
</div>
|
|
|
|
<div id="instructions">
|
|
<h3>Anleitung:</h3>
|
|
<p>Steuere mit Maus/Touch nach links/rechts<br>
|
|
Sammle Punkte indem du höher springst<br>
|
|
Vermeide Gegner 💀👻👽<br>
|
|
Zerbrechliche Plattformen brechen!<br>
|
|
3 Leben ❤️ - Bei 0 ist Spiel vorbei</p>
|
|
</div>
|
|
|
|
<script>
|
|
let canvas = document.getElementById('canvas');
|
|
let ctx = canvas.getContext('2d');
|
|
let player = { x: 160, y: 400, vy: 0, character: '🍌' };
|
|
let platforms = [];
|
|
let enemies = [];
|
|
let lives = 3;
|
|
let score = 0;
|
|
let highscore = localStorage.getItem('highscore') || 0;
|
|
let touchStartX = 0;
|
|
|
|
function init() {
|
|
document.getElementById('charSelectPopup').style.display = 'block';
|
|
}
|
|
|
|
function startGame() {
|
|
document.getElementById('gameOverPopup').style.display = 'none';
|
|
document.getElementById('charSelectPopup').style.display = 'block';
|
|
}
|
|
|
|
function initGame() {
|
|
document.getElementById('charSelectPopup').style.display = 'none';
|
|
lives = 3;
|
|
score = 0;
|
|
player.y = 400;
|
|
player.vy = -8;
|
|
platforms = [];
|
|
enemies = [];
|
|
|
|
// Initialplatformen unter dem Spieler
|
|
for(let i = 0; i < 8; i++) {
|
|
platforms.push({
|
|
x: Math.random() * 290,
|
|
y: 400 + i * 80,
|
|
type: Math.random() < 0.2 && i > 2 ? 'breaking' : 'normal'
|
|
});
|
|
}
|
|
|
|
// Positioniere Spieler auf erster Plattform
|
|
player.x = platforms[0].x + 30;
|
|
player.y = platforms[0].y - 30;
|
|
|
|
gameLoop();
|
|
updateDisplay();
|
|
}
|
|
|
|
function gameLoop() {
|
|
update();
|
|
draw();
|
|
if(lives > 0) requestAnimationFrame(gameLoop);
|
|
else showGameOver();
|
|
}
|
|
|
|
function update() {
|
|
// Physik-Update
|
|
player.y += player.vy;
|
|
player.vy += 0.2;
|
|
|
|
// Begrenze X-Position des Spielers
|
|
player.x = Math.max(20, Math.min(300, player.x));
|
|
|
|
// Plattform-Kollision
|
|
platforms.forEach((p, i) => {
|
|
if(player.vy > 0 &&
|
|
player.x + 20 > p.x &&
|
|
player.x - 20 < p.x + 60 &&
|
|
player.y + 40 > p.y &&
|
|
player.y + 40 < p.y + 15) {
|
|
if(p.type === 'breaking') platforms.splice(i, 1);
|
|
player.vy = -8;
|
|
score += 10;
|
|
updateDisplay();
|
|
}
|
|
});
|
|
|
|
// Plattform-Generierung
|
|
if (platforms.length > 0) { // Prüfe ob Plattformen existieren
|
|
let lowestPlatform = Math.max(...platforms.map(p => p.y));
|
|
while(platforms.length < 15) {
|
|
const newY = Math.min(...platforms.map(p => p.y)) - 80;
|
|
platforms.unshift({
|
|
x: Math.random() * 290,
|
|
y: newY,
|
|
type: Math.random() < (score > 500 ? 0.4 : score > 200 ? 0.3 : 0.2) ? 'breaking' : 'normal'
|
|
});
|
|
}
|
|
}
|
|
|
|
// Entferne alte Plattformen
|
|
platforms = platforms.filter(p => p.y < 600);
|
|
|
|
// Gegner-Logik
|
|
enemies.forEach((e, i) => {
|
|
if(Math.abs(player.x - e.x) < 30 && Math.abs(player.y - e.y) < 30) {
|
|
lives--;
|
|
enemies.splice(i, 1);
|
|
updateDisplay();
|
|
}
|
|
e.x += e.vx;
|
|
if(e.x < 0 || e.x > 300) e.vx *= -1;
|
|
});
|
|
|
|
// Generiere neue Gegner
|
|
if(Math.random() < 0.005 && score > 200 && enemies.length < 3) { // Reduzierte Wahrscheinlichkeit und max 3 Gegner
|
|
enemies.push({
|
|
x: Math.random() * 300,
|
|
y: player.y - 500,
|
|
vx: Math.random() * 2 - 1 // Langsamere Bewegung
|
|
});
|
|
}
|
|
|
|
// Entferne Gegner die zu weit unten sind
|
|
enemies = enemies.filter(e => e.y < 600);
|
|
|
|
// Bildlauf-System
|
|
if(player.y < 200) {
|
|
const scrollAmount = Math.floor(200 - player.y);
|
|
player.y = 200;
|
|
platforms.forEach(p => p.y += scrollAmount);
|
|
enemies.forEach(e => e.y += scrollAmount);
|
|
score = Math.floor(score + scrollAmount);
|
|
}
|
|
|
|
// Spielende-Check
|
|
if(player.y > 600) lives = 0;
|
|
}
|
|
|
|
function draw() {
|
|
ctx.clearRect(0, 0, 320, 480);
|
|
|
|
// Zeichne Plattformen
|
|
platforms.forEach(p => {
|
|
ctx.fillStyle = p.type === 'breaking' ? '#ff5555' : '#55ff55';
|
|
ctx.fillRect(p.x, p.y, 60, 10);
|
|
});
|
|
|
|
// Zeichne Gegner
|
|
enemies.forEach(e => {
|
|
ctx.font = '30px Arial';
|
|
ctx.fillText(['💀','👻','👽'][Math.floor(Math.random()*3)], e.x, e.y);
|
|
});
|
|
|
|
// Zeichne Spieler
|
|
ctx.font = '40px Arial';
|
|
ctx.fillText(player.character, player.x-20, player.y);
|
|
}
|
|
|
|
function updateDisplay() {
|
|
document.getElementById('score').textContent = Math.floor(score);
|
|
document.getElementById('lives').innerHTML = '❤️'.repeat(lives) + '🖤'.repeat(3-lives);
|
|
if(score > highscore) {
|
|
highscore = Math.floor(score);
|
|
localStorage.setItem('highscore', highscore);
|
|
}
|
|
}
|
|
|
|
function showGameOver() {
|
|
document.getElementById('gameOverPopup').style.display = 'block';
|
|
document.getElementById('highscore').textContent = highscore;
|
|
}
|
|
|
|
function takeScreenshot() {
|
|
html2canvas(document.querySelector("#gameContainer")).then(canvas => {
|
|
let link = document.createElement('a');
|
|
link.download = 'doodle-score.png';
|
|
link.href = canvas.toDataURL();
|
|
link.click();
|
|
});
|
|
}
|
|
|
|
// Event Listeners
|
|
document.getElementById('charSelect').addEventListener('click', (e) => {
|
|
if(e.target.classList.contains('emoji')) {
|
|
player.character = e.target.textContent;
|
|
initGame();
|
|
}
|
|
});
|
|
|
|
// Controls
|
|
canvas.addEventListener('mousedown', e => {
|
|
touchStartX = e.clientX;
|
|
});
|
|
|
|
canvas.addEventListener('mousemove', e => {
|
|
if(e.buttons === 1) {
|
|
player.x += e.movementX;
|
|
}
|
|
});
|
|
|
|
canvas.addEventListener('touchstart', e => {
|
|
touchStartX = e.touches[0].clientX;
|
|
});
|
|
|
|
canvas.addEventListener('touchmove', e => {
|
|
let touch = e.touches[0];
|
|
player.x += touch.clientX - touchStartX;
|
|
touchStartX = touch.clientX;
|
|
e.preventDefault();
|
|
}, { passive: false });
|
|
|
|
init();
|
|
</script>
|
|
</body>
|
|
</html> |