🎮ArcadeLab

Penguin Dash: Overdrive Edition

by NovaGalaxy88
724 lines22.9 KB
▶ Play
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Penguin Dash: Overdrive Edition</title>
<style>
:root {
    --bg-grad-top: #1a2a6c;
    --bg-grad-mid: #b21f1f;
    --bg-grad-bottom: #fdbb2d;
    --ground-color: #e0f2f1;
    --ground-border: #b2dfdb;
    --accent-color: #ffcc00;
    --panel-bg: rgba(255, 255, 255, 0.15);
    --text-color: #ffffff;
}

body {
    margin: 0;
    padding: 0;
    font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    overflow: hidden;
    background: #0f172a;
    user-select: none;
    color: var(--text-color);
}

/* SCREEN WRAPPERS */
.screen {
    position: absolute;
    width: 100vw;
    height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    z-index: 100;
    transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
    backdrop-filter: blur(8px);
    background: rgba(15, 23, 42, 0.85);
}

.hidden {
    opacity: 0;
    pointer-events: none;
    transform: scale(0.95);
}

/* GLASSMORPHISM PANELS */
.glass-panel {
    background: var(--panel-bg);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 24px;
    padding: 40px;
    box-shadow: 0 20px 40px rgba(0,0,0,0.4);
    text-align: center;
    max-width: 500px;
    width: 80%;
}

h1, h2, h3 {
    margin-top: 0;
    text-transform: uppercase;
    letter-spacing: 2px;
    text-shadow: 0 2px 10px rgba(0,0,0,0.5);
}

h1 { font-size: 3rem; color: var(--accent-color); }

/* BUTTONS */
.btn {
    padding: 14px 28px;
    font-size: 18px;
    font-weight: bold;
    border: none;
    border-radius: 12px;
    color: white;
    cursor: pointer;
    transition: all 0.2s ease;
    box-shadow: 0 4px 15px rgba(0,0,0,0.2);
    text-transform: uppercase;
}

.btn-primary { background: linear-gradient(45deg, #4CAF50, #45a049); }
.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(76,175,80,0.4); }

.btn-secondary { background: linear-gradient(45deg, #2196F3, #1e88e5); }
.btn-secondary:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(33,150,243,0.4); }

.btn-danger { background: linear-gradient(45deg, #f44336, #e53935); }

/* LOADING SCREEN */
#loadingScreen {
    background: #0f172a;
    z-index: 500;
}

.loader-container {
    width: 80%;
    max-width: 400px;
    background: rgba(255, 255, 255, 0.1);
    height: 20px;
    border-radius: 10px;
    overflow: hidden;
    margin-top: 20px;
    border: 1px solid rgba(255, 255, 255, 0.2);
}

.loader-bar {
    width: 0%;
    height: 100%;
    background: linear-gradient(90deg, var(--accent-color), #ff5500);
    transition: width 0.1s linear;
}

/* GAME AREA */
#gameContainer {
    position: relative;
    width: 100vw;
    height: 100vh;
    overflow: hidden;
    background: linear-gradient(to bottom, var(--bg-grad-top), var(--bg-grad-mid), var(--bg-grad-bottom));
}

#sky-elements {
    position: absolute;
    width: 100%;
    height: 60%;
}

/* CANVAS FOR PARTICLES */
#particleCanvas {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 3;
}

#ground {
    position: absolute;
    bottom: 0;
    width: 100%;
    height: 20%;
    background: var(--ground-color);
    border-top: 6px solid var(--ground-border);
    z-index: 4;
}

/* ENTITIES - Steht jetzt bombenfest auf der hellblauen Eisbahn */
#penguin {
    position: absolute;
    left: 12%;
    bottom: 20%; /* Exakt auf der Eisbahn platziert */
    width: 64px;
    height: 64px;
    font-size: 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 5;
    transform-origin: bottom center;
    margin-bottom: 2px;
    will-change: transform;
}

.shield-bubble {
    position: absolute;
    width: 80px;
    height: 80px;
    border: 3px solid #00e5ff;
    border-radius: 50%;
    box-shadow: 0 0 15px #00e5ff;
    animation: pulse 1s infinite alternate;
    display: none;
    z-index: 6;
}

@keyframes pulse {
    0% { transform: scale(0.95); opacity: 0.6; }
    100% { transform: scale(1.05); opacity: 1; }
}

/* OBSTACLES & ITEMS */
.obstacle {
    position: absolute;
    z-index: 4;
    border-radius: 8px;
    will-change: left;
}
.obs-rock { background: #546e7a; border: 2px solid #37474f; }
.obs-spike { width: 0; height: 0; border-left: 20px solid transparent; border-right: 20px solid transparent; border-bottom: 50px solid #d32f2f; }
.obs-bird { font-size: 35px; }

.item {
    position: absolute;
    font-size: 30px;
    z-index: 4;
    will-change: left, bottom;
}

/* HUD / UI */
#hud {
    position: absolute;
    top: 20px;
    left: 20px;
    right: 20px;
    display: flex;
    justify-content: space-between;
    pointer-events: none;
    z-index: 50;
}

.hud-card {
    background: rgba(0, 0, 0, 0.4);
    padding: 12px 24px;
    border-radius: 16px;
    border: 1px solid rgba(255,255,255,0.1);
    font-weight: bold;
    font-size: 1.1rem;
    display: flex;
    gap: 20px;
    pointer-events: auto;
}

.stat-val { color: var(--accent-color); }

/* CONTROLS OVERLAY WITH BIG JUMP BUTTON */
#controlsOverlay {
    position: absolute;
    bottom: 20px;
    right: 20px;
    z-index: 60;
}

.jump-btn {
    width: 95px;
    height: 95px;
    background: rgba(255, 255, 255, 0.3);
    border: 3px solid rgba(255, 255, 255, 0.7);
    border-radius: 50%;
    color: white;
    font-size: 18px;
    font-weight: bold;
    text-transform: uppercase;
    cursor: pointer;
    box-shadow: 0 8px 24px rgba(0,0,0,0.3);
    backdrop-filter: blur(4px);
    display: flex;
    align-items: center;
    justify-content: center;
    user-select: none;
    touch-action: manipulation;
}

.jump-btn:active {
    transform: scale(0.90);
    background: rgba(255, 255, 255, 0.5);
}

/* SHOP SYSTEM UI */
.shop-tabs {
    display: flex;
    justify-content: center;
    gap: 10px;
    margin-bottom: 20px;
}
.tab-btn {
    background: rgba(255,255,255,0.1);
    border: none;
    color: white;
    padding: 8px 16px;
    border-radius: 8px;
    cursor: pointer;
}
.tab-btn.active { background: var(--accent-color); color: black; font-weight: bold; }

.shop-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 15px;
    max-height: 300px;
    overflow-y: auto;
    padding-right: 5px;
}

.shop-item {
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 12px;
    padding: 12px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    text-align: center;
}

.shop-item span { font-size: 28px; margin-bottom: 5px; }

/* NOTIFICATIONS */
#toast-container {
    position: absolute;
    bottom: 20px;
    left: 20px;
    z-index: 200;
}
.toast {
    background: rgba(76, 175, 80, 0.95);
    color: white;
    padding: 15px 25px;
    border-radius: 10px;
    margin-top: 10px;
    box-shadow: 0 5px 15px rgba(0,0,0,0.3);
    animation: slideIn 0.3s ease, fadeOut 0.3s ease 3s forwards;
}

@keyframes slideIn { from { transform: translateX(-100%); } to { transform: translateX(0); } }
@keyframes fadeOut { to { opacity: 0; transform: translateY(-10px); } }

/* DAILY REWARDS UI */
.daily-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
    margin: 20px 0;
}
.daily-day {
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 10px;
    padding: 10px 5px;
    font-size: 14px;
}
.daily-day.completed { background: rgba(76, 175, 80, 0.3); border-color: #4CAF50; }
.daily-day.current { background: rgba(255, 204, 0, 0.3); border-color: var(--accent-color); }
</style>
</head>
<body>

<div id="loadingScreen" class="screen">
    <h2 style="font-size: 2.5rem; letter-spacing: 4px; color: var(--accent-color); animation: pulse 0.6s infinite alternate;">Loading...</h2>
    <div class="loader-container">
        <div id="loaderBar" class="loader-bar"></div>
    </div>
</div>

<div id="mainMenu" class="screen hidden">
    <div class="glass-panel">
        <h1>Penguin Dash</h1>
        <p>Weiche Hindernissen aus, sammle Münzen und schalte mächtige Upgrades frei!</p>
        <div style="margin: 20px 0; font-size: 1.2rem;">
            <div>Highscore: <span id="menuHighScore" class="stat-val">0</span></div>
            <div>Münzen insgesamt: <span id="menuTotalCoins" class="stat-val">0</span></div>
        </div>
        <div style="display: flex; flex-direction: column; gap: 10px;">
            <button class="btn btn-primary" onclick="launchDirectGame()">Spiel Starten</button>
            <button class="btn btn-secondary" onclick="openShop()">Shop & Upgrades 🛍️</button>
            <button class="btn btn-secondary" onclick="togglePanel('achievementsPanel')">Erfolge 🏆</button>
            <button class="btn btn-secondary" style="background: linear-gradient(45deg, #ff9900, #ff5500);" onclick="togglePanel('dailyPanel')">Tägliche Belohnung 🎁</button>
        </div>
    </div>
</div>

<div id="dailyPanel" class="screen hidden">
    <div class="glass-panel" style="max-width: 550px;">
        <h2>🎁 Tägliche Belohnungen</h2>
        <div id="dailyGrid" class="daily-grid"></div>
        <button id="claimDailyBtn" class="btn btn-primary" onclick="claimDailyReward()">Belohnung Abholen!</button>
        <button class="btn btn-danger" style="margin-top: 15px; display: block; width: 100%;" onclick="togglePanel('dailyPanel')">Zurück</button>
    </div>
</div>

<div id="gameOverScreen" class="screen hidden">
    <div class="glass-panel">
        <h2 style="color: #ff3333;">Game Over</h2>
        <div style="margin: 20px 0; font-size: 1.3rem; display: flex; justify-content: space-around;">
            <div>Score: <span id="finalScore" class="stat-val">0</span></div>
            <div>Münzen: <span id="finalCoins" class="stat-val">0</span></div>
        </div>
        <div style="display: flex; gap: 10px; justify-content: center;">
            <button class="btn btn-primary" onclick="launchDirectGame()">Nochmal</button>
            <button class="btn btn-secondary" onclick="changeScreen('gameOverScreen', 'mainMenu')">Hauptmenü</button>
        </div>
    </div>
</div>

<div id="shopPanel" class="screen hidden">
    <div class="glass-panel" style="max-width: 600px;">
        <h2>Shop & Anpassung</h2>
        <div style="font-size: 1.2rem; margin-bottom: 15px;">Deine Coins: <span id="shopCoinCount" class="stat-val">0</span> 🪙</div>
        <div class="shop-tabs">
            <button id="tabBtn-skins" class="tab-btn active" onclick="switchTab('skins')">Skins</button>
            <button id="tabBtn-themes" class="tab-btn" onclick="switchTab('themes')">Themen</button>
            <button id="tabBtn-upgrades" class="tab-btn" onclick="switchTab('upgrades')">Upgrades</button>
        </div>
        <div id="shopGrid" class="shop-grid"></div>
        <button class="btn btn-danger" style="margin-top: 20px;" onclick="closeShop()">Schließen</button>
    </div>
</div>

<div id="achievementsPanel" class="screen hidden">
    <div class="glass-panel">
        <h2>🏆 Deine Erfolge</h2>
        <div id="achievementsList" style="max-height: 300px; overflow-y: auto; text-align: left; padding: 10px;"></div>
        <button class="btn btn-danger" style="margin-top: 20px;" onclick="togglePanel('achievementsPanel')">Zurück</button>
    </div>
</div>

<div id="gameContainer" style="display:none;">
    <div id="hud">
        <div class="hud-card">
            <div>Score: <span id="hudScore" class="stat-val">0</span></div>
            <div>Level: <span id="hudLevel" class="stat-val">1</span></div>
        </div>
        <div class="hud-card">
            <div>Coins: <span id="hudCoins" class="stat-val">0</span> 🪙</div>
        </div>
    </div>

    <div id="sky-elements"></div>
    <canvas id="particleCanvas"></canvas>
    
    <div id="controlsOverlay">
        <button class="jump-btn" onmousedown="triggerJump()" ontouchstart="event.preventDefault(); triggerJump();">Jump</button>
    </div>

    <div id="penguin"><span id="penguinSkinRender">🐧</span><div id="shieldBubble" class="shield-bubble"></div></div>
    <div id="ground"></div>
</div>

<div id="toast-container"></div>

<script>
// --- GAME STATE ---
let state = {
    highScore: parseInt(localStorage.getItem('pd_highscore')) || 0,
    totalCoins: parseInt(localStorage.getItem('pd_coins')) || 0,
    ownedSkins: JSON.parse(localStorage.getItem('pd_skins')) || ['🐧'],
    activeSkin: localStorage.getItem('pd_activeskin') || '🐧',
    ownedThemes: JSON.parse(localStorage.getItem('pd_themes')) || ['Arktis'],
    activeTheme: localStorage.getItem('pd_activetheme') || 'Arktis',
    upgrades: JSON.parse(localStorage.getItem('pd_upgrades')) || { magnet: 0, shield: 0 },
    achievements: JSON.parse(localStorage.getItem('pd_achieve')) || [],
    lastDailyClaim: localStorage.getItem('pd_lastdaily') || "", 
    dailyStreak: parseInt(localStorage.getItem('pd_dailystreak')) || 0
};

// --- CONSTANTS ---
const ALL_SKINS = [
    { id: '🐧', name: 'Standard', cost: 0 },
    { id: '🕶️', name: 'Cooler Pingu', cost: 50 },
    { id: '👑', name: 'König', cost: 150 },
    { id: '🥷', name: 'Ninja', cost: 300 }
];

const ALL_THEMES = [
    { id: 'Arktis', name: 'Klassische Arktis', cost: 0, top: '#1a2a6c', mid: '#b21f1f', bot: '#fdbb2d', ground: '#e0f2f1', border: '#b2dfdb' },
    { id: 'Neon', name: 'Cyberpunk Neon', cost: 100, top: '#0f172a', mid: '#581c87', bot: '#0284c7', ground: '#1e1b4b', border: '#f43f5e' }
];

function saveState() {
    localStorage.setItem('pd_highscore', state.highScore);
    localStorage.setItem('pd_coins', state.totalCoins);
    localStorage.setItem('pd_skins', JSON.stringify(state.ownedSkins));
    localStorage.setItem('pd_activeskin', state.activeSkin);
    localStorage.setItem('pd_themes', JSON.stringify(state.ownedThemes));
    localStorage.setItem('pd_activetheme', state.activeTheme);
    localStorage.setItem('pd_upgrades', JSON.stringify(state.upgrades));
    localStorage.setItem('pd_achieve', JSON.stringify(state.achievements));
    localStorage.setItem('pd_lastdaily', state.lastDailyClaim);
    localStorage.setItem('pd_dailystreak', state.dailyStreak);
}

function showToast(text) {
    const container = document.getElementById('toast-container');
    const toast = document.createElement('div');
    toast.className = 'toast';
    toast.innerText = text;
    container.appendChild(toast);
    setTimeout(() => toast.remove(), 3000);
}

function changeScreen(fromId, toId) {
    document.getElementById(fromId).classList.add('hidden');
    const toScreen = document.getElementById(toId);
    toScreen.classList.remove('hidden');
    if(toId === 'gameContainer' || toId === 'mainMenu') {
        toScreen.style.display = (toId === 'gameContainer') ? 'block' : 'none';
    }
}

function togglePanel(id) {
    const el = document.getElementById(id);
    el.classList.contains('hidden') ? el.classList.remove('hidden') : el.classList.add('hidden');
}

function updateMenuStats() {
    document.getElementById('menuHighScore').innerText = state.highScore;
    document.getElementById('menuTotalCoins').innerText = state.totalCoins;
}

// --- EINMALIGER LADEBILDSCHIRM BEIM STARTEN DER SEITE ---
function runInitialLoadingSequence() {
    const loadingScreen = document.getElementById('loadingScreen');
    const bar = document.getElementById('loaderBar');
    let progress = 0;
    
    const loadTick = setInterval(() => {
        progress += Math.random() * 8 + 2;
        if(progress >= 100) {
            progress = 100;
            clearInterval(loadTick);
            setTimeout(() => {
                loadingScreen.classList.add('hidden');
                document.getElementById('mainMenu').classList.remove('hidden');
                updateMenuStats();
            }, 300);
        }
        bar.style.width = `${progress}%`;
    }, 40);
}

// --- DIREKTER SPIELSTART OHNE WARTEZEIT ---
function launchDirectGame() {
    document.getElementById('mainMenu').classList.add('hidden');
    document.getElementById('gameOverScreen').classList.add('hidden');
    changeScreen('mainMenu', 'gameContainer'); 
    initGame();
}

// --- SHOP ENGINE ---
let currentShopTab = 'skins';
function openShop() {
    document.getElementById('shopCoinCount').innerText = state.totalCoins;
    switchTab(currentShopTab);
    changeScreen('mainMenu', 'shopPanel');
}
function closeShop() { changeScreen('shopPanel', 'mainMenu'); }
function switchTab(tab) {
    currentShopTab = tab;
    document.querySelectorAll('.shop-tabs .tab-btn').forEach(b => b.classList.remove('active'));
    document.getElementById(`tabBtn-${tab}`).classList.add('active');
    const grid = document.getElementById('shopGrid');
    grid.innerHTML = '';

    if (tab === 'skins') {
        ALL_SKINS.forEach(skin => {
            const isOwned = state.ownedSkins.includes(skin.id);
            const isActive = state.activeSkin === skin.id;
            grid.innerHTML += `
                <div class="shop-item">
                    <span>${skin.id}</span>
                    <small>${skin.name}</small>
                    <button class="btn btn-primary" style="font-size:12px; padding:6px 12px;" onclick="buySkin('${skin.id}', ${skin.cost})">
                        ${isActive ? 'Aktiv' : (isOwned ? 'Nutzen' : skin.cost + ' 🪙')}
                    </button>
                </div>
            `;
        });
    }
}

function buySkin(id, cost) {
    if (state.ownedSkins.includes(id)) { state.activeSkin = id; }
    else if (state.totalCoins >= cost) { state.totalCoins -= cost; state.ownedSkins.push(id); state.activeSkin = id; }
    saveState(); openShop();
}

function applyTheme(themeId) {
    const t = ALL_THEMES.find(x => x.id === themeId) || ALL_THEMES[0];
    const r = document.documentElement;
    r.style.setProperty('--bg-grad-top', t.top);
    r.style.setProperty('--bg-grad-mid', t.mid);
    r.style.setProperty('--bg-grad-bottom', t.bot);
    r.style.setProperty('--ground-color', t.ground);
    r.style.setProperty('--ground-border', t.border);
}

// --- GAME LOGIC ENGINE ---
let gameLoopId, gameActive = false;
let score = 0, coinsCollected = 0, level = 1, gameSpeed = 5;
const gravity = 0.6;
let playerY = 0, vy = 0, isJumping = false;
let shieldActive = false, shieldTimer = 0;
let obstacles = [], items = [], particles = [];
let spawnTimer = 0, groundHeight = 0;
let canvas, ctx;

function initGame() {
    canvas = document.getElementById('particleCanvas');
    ctx = canvas.getContext('2d');
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

    groundHeight = window.innerHeight * 0.2; // Entspricht exakt der Höhe der Bahn
    playerY = 0; vy = 0; isJumping = false;
    shieldActive = false;
    obstacles = []; items = []; particles = [];
    score = 0; coinsCollected = 0; level = 1; gameSpeed = 5; spawnTimer = 0;

    document.getElementById('penguinSkinRender').innerText = state.activeSkin;
    applyTheme(state.activeTheme);

    window.removeEventListener('keydown', jump);
    window.addEventListener('keydown', jump);

    gameActive = true;
    gameLoop();
}

function jump(e) { if(e.code === 'Space' || e.code === 'ArrowUp') triggerJump(); }

function triggerJump() {
    if(!isJumping && gameActive) {
        vy = 14.5;
        isJumping = true;
        createParticles(window.innerWidth * 0.12 + 32, window.innerHeight - groundHeight, '#ffffff', 8);
    }
}

function createParticles(x, y, color, count) {
    for (let i = 0; i < count; i++) {
        particles.push({
            x: x, y: y,
            vx: (Math.random() - 0.5) * 6, vy: (Math.random() - 0.5) * 6,
            alpha: 1, color: color, size: Math.random() * 4 + 2
        });
    }
}

function gameLoop() {
    if(!gameActive) return;

    // Physik-Berechnung
    playerY += vy;
    vy -= gravity;
    if(playerY <= 0) { playerY = 0; vy = 0; isJumping = false; }

    // Verschiebt den Pinguin absolut sauber von der Eisbahnbasis nach oben
    document.getElementById('penguin').style.transform = `translateY(${-playerY}px)`;

    // Spawn-System
    spawnTimer++;
    if(spawnTimer > Math.max(50, 120 - gameSpeed * 4)) {
        spawnTimer = 0;
        if(Math.random() > 0.4) {
            let type = Math.random() > 0.5 ? 'rock' : 'spike';
            let el = document.createElement('div');
            el.className = `obstacle obs-${type}`;
            let w = 40, h = 40, bot = groundHeight;
            if(type === 'spike') { w = 30; h = 45; }
            el.style.width = w+'px'; el.style.height = h+'px'; el.style.bottom = bot+'px'; el.style.left = window.innerWidth + 'px';
            document.getElementById('gameContainer').appendChild(el);
            obstacles.push({el, type, x: window.innerWidth, w, h, bot});
        } else {
            let el = document.createElement('div');
            el.className = 'item'; el.innerText = '🪙';
            let bot = groundHeight + 20 + Math.random()*80;
            el.style.bottom = bot+'px'; el.style.left = window.innerWidth + 'px';
            document.getElementById('gameContainer').appendChild(el);
            items.push({el, type: 'coin', x: window.innerWidth, w: 30, h: 30, bot});
        }
    }

    let px = window.innerWidth * 0.12;
    let py = groundHeight + playerY;

    // Kollisionsprüfung für Hindernisse
    for(let i=obstacles.length-1; i>=0; i--) {
        let o = obstacles[i]; o.x -= gameSpeed; o.el.style.left = o.x + 'px';
        if(o.x < px + 50 && o.x + o.w > px + 14 && o.bot < py + 55 && o.bot + o.h > py) {
            gameOver(); return;
        }
        if(o.x < -100) { o.el.remove(); obstacles.splice(i,1); }
    }

    // Münzen einsammeln
    for(let i=items.length-1; i>=0; i--) {
        let it = items[i]; it.x -= gameSpeed; it.el.style.left = it.x + 'px';
        if(it.x < px + 50 && it.x + it.w > px + 10 && it.bot < py + 55 && it.bot + it.h > py) {
            coinsCollected++;
            it.el.remove(); items.splice(i,1); continue;
        }
        if(it.x < -100) { it.el.remove(); items.splice(i,1); }
    }

    // Partikel rendern
    ctx.clearRect(0,0,canvas.width,canvas.height);
    for (let i = particles.length - 1; i >= 0; i--) {
        let p = particles[i]; p.x += p.vx; p.y += p.vy; p.alpha -= 0.025;
        if (p.alpha <= 0) { particles.splice(i, 1); continue; }
        ctx.save(); ctx.globalAlpha = p.alpha; ctx.fillStyle = p.color;
        ctx.beginPath(); ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2); ctx.fill(); ctx.restore();
    }

    score += 0.15;
    document.getElementById('hudScore').innerText = Math.floor(score);
    document.getElementById('hudCoins').innerText = coinsCollected;
    
    gameLoopId = requestAnimationFrame(gameLoop);
}

function gameOver() {
    gameActive = false;
    cancelAnimationFrame(gameLoopId);
    state.totalCoins += coinsCollected;
    if(Math.floor(score) > state.highScore) state.highScore = Math.floor(score);
    saveState();
    document.getElementById('finalScore').innerText = Math.floor(score);
    document.getElementById('finalCoins').innerText = coinsCollected;
    document.querySelectorAll('.obstacle, .item').forEach(e => e.remove());
    changeScreen('gameContainer', 'gameOverScreen');
}

window.onload = () => {
    runInitialLoadingSequence(); // Startet den Ladebildschirm nur exakt hier!
};
</script>
</body>
</html>

Game Source: Penguin Dash: Overdrive Edition

Creator: NovaGalaxy88

Libraries: none

Complexity: complex (724 lines, 22.9 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: penguin-dash-evolution-novagalaxy88" to link back to the original. Then publish at arcadelab.ai/publish.