<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Galaxy Survivor</title>

<style>
* {
    box-sizing: border-box;
}

body {
    margin: 0;
    background: #080b18;
    color: white;
    font-family: Arial, sans-serif;
    overflow: hidden;
}

canvas {
    display: block;
    margin: auto;
    background: linear-gradient(#111936, #070914);
    border: 3px solid #3949ab;
    box-shadow: 0 0 30px #3949ab;
}

#menu {
    position: fixed;
    inset: 0;
    background: rgba(5, 7, 20, 0.95);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 10;
}

.panel {
    text-align: center;
    background: #111936;
    padding: 40px;
    border-radius: 20px;
    border: 2px solid #536dfe;
    box-shadow: 0 0 40px #536dfe;
    width: 450px;
}

h1 {
    font-size: 48px;
    margin: 0 0 10px;
    color: #7c4dff;
    text-shadow: 0 0 20px #7c4dff;
}

button {
    background: #536dfe;
    color: white;
    border: none;
    padding: 15px 35px;
    margin-top: 20px;
    border-radius: 10px;
    font-size: 20px;
    cursor: pointer;
}

button:hover {
    background: #7c4dff;
    transform: scale(1.05);
}

#hud {
    position: fixed;
    top: 15px;
    left: 15px;
    z-index: 5;
    font-size: 18px;
    line-height: 1.6;
    background: rgba(0,0,0,.45);
    padding: 12px;
    border-radius: 10px;
}

.bar {
    width: 220px;
    height: 18px;
    background: #333;
    border-radius: 10px;
    overflow: hidden;
    margin-top: 5px;
}

#healthBar {
    height: 100%;
    background: #00e676;
    width: 100%;
}

#xpBar {
    height: 100%;
    background: #2979ff;
    width: 0%;
}

#gameOver {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,.9);
    z-index: 20;
    justify-content: center;
    align-items: center;
    text-align: center;
}

#gameOver h2 {
    font-size: 60px;
    color: #ff1744;
}

.mobileControls {
    display: none;
}

@media (max-width: 700px) {
    canvas {
        width: 100%;
        height: auto;
    }

    .mobileControls {
        display: block;
        position: fixed;
        bottom: 20px;
        left: 20px;
        z-index: 8;
    }

    .mobileControls button {
        width: 60px;
        height: 60px;
        padding: 0;
        margin: 3px;
        font-size: 20px;
    }
}
</style>
</head>

<body>

<div id="menu">
    <div class="panel">
        <h1>GALAXY SURVIVOR</h1>

        <p>Überlebe so lange wie möglich!</p>

        <p>
            <b>WASD / Pfeiltasten</b> = Bewegen<br>
            <b>Leertaste</b> = Schießen
        </p>

        <button onclick="startGame()">SPIEL STARTEN</button>
    </div>
</div>

<div id="hud">
    ❤️ Leben:
    <div class="bar">
        <div id="healthBar"></div>
    </div>

    ⭐ XP:
    <div class="bar">
        <div id="xpBar"></div>
    </div>

    <div>
        Level: <span id="level">1</span>
    </div>

    <div>
        Punkte: <span id="score">0</span>
    </div>

    <div>
        Münzen: <span id="coins">0</span>
    </div>

    <div>
        Gegner: <span id="enemyCount">0</span>
    </div>
</div>

<canvas id="game" width="1000" height="650"></canvas>

<div class="mobileControls">
    <button ontouchstart="keys.w=true" ontouchend="keys.w=false">▲</button><br>
    <button ontouchstart="keys.a=true" ontouchend="keys.a=false">◀</button>
    <button ontouchstart="keys.s=true" ontouchend="keys.s=false">▼</button>
    <button ontouchstart="keys.d=true" ontouchend="keys.d=false">▶</button>
</div>

<div id="gameOver">
    <div>
        <h2>GAME OVER</h2>

        <p>
            Punkte: <span id="finalScore">0</span>
        </p>

        <p>
            Level: <span id="finalLevel">1</span>
        </p>

        <p>
            Münzen: <span id="finalCoins">0</span>
        </p>

        <button onclick="startGame()">NOCHMAL SPIELEN</button>
    </div>
</div>

<script>

const canvas = document.getElementById("game");
const ctx = canvas.getContext("2d");

const WIDTH = canvas.width;
const HEIGHT = canvas.height;

let gameRunning = false;

let score = 0;
let coins = 0;
let level = 1;
let xp = 0;

let enemyTimer = 0;
let coinTimer = 0;

let keys = {
    w: false,
    a: false,
    s: false,
    d: false,
    space: false
};

const player = {
    x: WIDTH / 2,
    y: HEIGHT / 2,

    width: 35,
    height: 35,

    speed: 5,

    health: 100,
    maxHealth: 100,

    shootCooldown: 0,

    damage: 25
};

let bullets = [];
let enemies = [];
let particles = [];
let coinsObjects = [];
let stars = [];


/* =========================
   STERNE
========================= */

for (let i = 0; i < 150; i++) {

    stars.push({
        x: Math.random() * WIDTH,
        y: Math.random() * HEIGHT,
        size: Math.random() * 2 + 1,
        speed: Math.random() * 0.5 + 0.1
    });

}


/* =========================
   TASTATUR
========================= */

document.addEventListener("keydown", function(event) {

    if (event.key === "w" || event.key === "W" || event.key === "ArrowUp") {
        keys.w = true;
    }

    if (event.key === "a" || event.key === "A" || event.key === "ArrowLeft") {
        keys.a = true;
    }

    if (event.key === "s" || event.key === "S" || event.key === "ArrowDown") {
        keys.s = true;
    }

    if (event.key === "d" || event.key === "D" || event.key === "ArrowRight") {
        keys.d = true;
    }

    if (event.code === "Space") {
        keys.space = true;
    }

});


document.addEventListener("keyup", function(event) {

    if (event.key === "w" || event.key === "W" || event.key === "ArrowUp") {
        keys.w = false;
    }

    if (event.key === "a" || event.key === "A" || event.key === "ArrowLeft") {
        keys.a = false;
    }

    if (event.key === "s" || event.key === "S" || event.key === "ArrowDown") {
        keys.s = false;
    }

    if (event.key === "d" || event.key === "D" || event.key === "ArrowRight") {
        keys.d = false;
    }

    if (event.code === "Space") {
        keys.space = false;
    }

});


/* =========================
   SPIEL STARTEN
========================= */

function startGame() {

    document.getElementById("menu").style.display = "none";
    document.getElementById("gameOver").style.display = "none";

    score = 0;
    coins = 0;
    level = 1;
    xp = 0;

    player.x = WIDTH / 2;
    player.y = HEIGHT / 2;

    player.health = 100;
    player.maxHealth = 100;

    player.damage = 25;
    player.speed = 5;

    bullets = [];
    enemies = [];
    particles = [];
    coinsObjects = [];

    gameRunning = true;

    updateHUD();

    gameLoop();
}


/* =========================
   SPIELER BEWEGUNG
========================= */

function updatePlayer() {

    if (keys.w) {
        player.y -= player.speed;
    }

    if (keys.s) {
        player.y += player.speed;
    }

    if (keys.a) {
        player.x -= player.speed;
    }

    if (keys.d) {
        player.x += player.speed;
    }

    // Grenzen

    if (player.x < player.width / 2) {
        player.x = player.width / 2;
    }

    if (player.x > WIDTH - player.width / 2) {
        player.x = WIDTH - player.width / 2;
    }

    if (player.y < player.height / 2) {
        player.y = player.height / 2;
    }

    if (player.y > HEIGHT - player.height / 2) {
        player.y = HEIGHT - player.height / 2;
    }

}


/* =========================
   SCHIESSEN
========================= */

function shoot() {

    if (player.shootCooldown > 0) {
        return;
    }

    bullets.push({

        x: player.x,

        y: player.y - 20,

        radius: 5,

        speed: 10,

        damage: player.damage

    });

    player.shootCooldown = 12;

}


function updateBullets() {

    if (player.shootCooldown > 0) {
        player.shootCooldown--;
    }

    if (keys.space) {
        shoot();
    }

    for (let i = bullets.length - 1; i >= 0; i--) {

        let bullet = bullets[i];

        bullet.y -= bullet.speed;

        if (bullet.y < -20) {
            bullets.splice(i, 1);
        }

    }

}


/* =========================
   GEGNER ERSTELLEN
========================= */

function spawnEnemy() {

    let side = Math.floor(Math.random() * 4);

    let x;
    let y;

    if (side === 0) {
        x = Math.random() * WIDTH;
        y = -40;
    }

    if (side === 1) {
        x = WIDTH + 40;
        y = Math.random() * HEIGHT;
    }

    if (side === 2) {
        x = Math.random() * WIDTH;
        y = HEIGHT + 40;
    }

    if (side === 3) {
        x = -40;
        y = Math.random() * HEIGHT;
    }

    let enemyType = Math.random();

    let enemy;

    if (enemyType < 0.15) {

        enemy = {

            x,
            y,

            radius: 28,

            speed: 1.2 + level * 0.03,

            health: 120 + level * 10,

            maxHealth: 120 + level * 10,

            damage: 20,

            color: "#ff1744",

            points: 50

        };

    } else {

        enemy = {

            x,
            y,

            radius: 20,

            speed: 1.5 + level * 0.05,

            health: 50 + level * 5,

            maxHealth: 50 + level * 5,

            damage: 10,

            color: "#ff9100",

            points: 20

        };

    }

    enemies.push(enemy);

}


/* =========================
   GEGNER UPDATE
========================= */

function updateEnemies() {

    enemyTimer++;

    let spawnSpeed = Math.max(20, 70 - level * 3);

    if (enemyTimer > spawnSpeed) {

        spawnEnemy();

        enemyTimer = 0;

    }


    for (let enemy of enemies) {

        let dx = player.x - enemy.x;
        let dy = player.y - enemy.y;

        let distance = Math.sqrt(dx * dx + dy * dy);

        if (distance > 0) {

            enemy.x += dx / distance * enemy.speed;
            enemy.y += dy / distance * enemy.speed;

        }

        // Spieler treffen

        if (distance < enemy.radius + 18) {

            player.health -= enemy.damage * 0.02;

            createExplosion(
                player.x,
                player.y,
                "#ff1744",
                2
            );

        }

    }

}


/* =========================
   KUGELN UND GEGNER
========================= */

function checkBulletCollisions() {

    for (let i = bullets.length - 1; i >= 0; i--) {

        let bullet = bullets[i];

        for (let j = enemies.length - 1; j >= 0; j--) {

            let enemy = enemies[j];

            let dx = bullet.x - enemy.x;
            let dy = bullet.y - enemy.y;

            let distance = Math.sqrt(dx * dx + dy * dy);

            if (distance < enemy.radius + bullet.radius) {

                enemy.health -= bullet.damage;

                bullets.splice(i, 1);

                createExplosion(
                    bullet.x,
                    bullet.y,
                    "#00e5ff",
                    5
                );

                if (enemy.health <= 0) {

                    score += enemy.points;

                    xp += 10;

                    createExplosion(
                        enemy.x,
                        enemy.y,
                        enemy.color,
                        20
                    );

                    if (Math.random() < 0.35) {

                        coinsObjects.push({

                            x: enemy.x,
                            y: enemy.y,

                            radius: 10

                        });

                    }

                    enemies.splice(j, 1);

                    checkLevelUp();

                }

                break;

            }

        }

    }

}


/* =========================
   LEVEL UP
========================= */

function checkLevelUp() {

    let neededXP = level * 100;

    if (xp >= neededXP) {

        xp -= neededXP;

        level++;

        player.maxHealth += 10;

        player.health = player.maxHealth;

        player.damage += 5;

        player.speed += 0.2;

        createExplosion(
            player.x,
            player.y,
            "#7c4dff",
            50
        );

    }

}


/* =========================
   MÜNZEN
========================= */

function updateCoins() {

    for (let i = coinsObjects.length - 1; i >= 0; i--) {

        let coin = coinsObjects[i];

        let dx = player.x - coin.x;
        let dy = player.y - coin.y;

        let distance = Math.sqrt(dx * dx + dy * dy);

        if (distance < 35) {

            coins++;

            score += 10;

            coinsObjects.splice(i, 1);

        }

    }

}


/* =========================
   PARTIKEL
========================= */

function createExplosion(x, y, color, amount) {

    for (let i = 0; i < amount; i++) {

        particles.push({

            x,
            y,

            vx: (Math.random() - 0.5) * 8,

            vy: (Math.random() - 0.5) * 8,

            life: 30 + Math.random() * 30,

            color,

            size: Math.random() * 5 + 2

        });

    }

}


function updateParticles() {

    for (let i = particles.length - 1; i >= 0; i--) {

        let particle = particles[i];

        particle.x += particle.vx;
        particle.y += particle.vy;

        particle.vx *= 0.97;
        particle.vy *= 0.97;

        particle.life--;

        if (particle.life <= 0) {

            particles.splice(i, 1);

        }

    }

}


/* =========================
   STERNE UPDATE
========================= */

function updateStars() {

    for (let star of stars) {

        star.y += star.speed;

        if (star.y > HEIGHT) {

            star.y = 0;

            star.x = Math.random() * WIDTH;

        }

    }

}


/* =========================
   ZEICHNEN
========================= */

function drawBackground() {

    ctx.fillStyle = "#080b18";

    ctx.fillRect(
        0,
        0,
        WIDTH,
        HEIGHT
    );


    for (let star of stars) {

        ctx.fillStyle = "white";

        ctx.globalAlpha = 0.3 + Math.random() * 0.5;

        ctx.fillRect(
            star.x,
            star.y,
            star.size,
            star.size
        );

    }

    ctx.globalAlpha = 1;

}


/* =========================
   SPIELER ZEICHNEN
========================= */

function drawPlayer() {

    ctx.save();

    ctx.translate(
        player.x,
        player.y
    );

    // Glow

    ctx.shadowColor = "#00e5ff";
    ctx.shadowBlur = 20;

    ctx.fillStyle = "#00e5ff";

    ctx.beginPath();

    ctx.moveTo(0, -25);
    ctx.lineTo(20, 20);
    ctx.lineTo(0, 12);
    ctx.lineTo(-20, 20);

    ctx.closePath();

    ctx.fill();

    ctx.restore();

}


/* =========================
   KUGELN ZEICHNEN
========================= */

function drawBullets() {

    for (let bullet of bullets) {

        ctx.shadowColor = "#00e5ff";
        ctx.shadowBlur = 15;

        ctx.fillStyle = "#00e5ff";

        ctx.beginPath();

        ctx.arc(
            bullet.x,
            bullet.y,
            bullet.radius,
            0,
            Math.PI * 2
        );

        ctx.fill();

        ctx.shadowBlur = 0;

    }

}


/* =========================
   GEGNER ZEICHNEN
========================= */

function drawEnemies() {

    for (let enemy of enemies) {

        ctx.shadowColor = enemy.color;
        ctx.shadowBlur = 15;

        ctx.fillStyle = enemy.color;

        ctx.beginPath();

        ctx.arc(
            enemy.x,
            enemy.y,
            enemy.radius,
            0,
            Math.PI * 2
        );

        ctx.fill();

        ctx.shadowBlur = 0;


        // Lebensbalken

        let barWidth = enemy.radius * 2;

        let healthWidth =
            barWidth *
            (enemy.health / enemy.maxHealth);

        ctx.fillStyle = "#333";

        ctx.fillRect(
            enemy.x - enemy.radius,
            enemy.y - enemy.radius - 10,
            barWidth,
            5
        );

        ctx.fillStyle = "#00e676";

        ctx.fillRect(
            enemy.x - enemy.radius,
            enemy.y - enemy.radius - 10,
            healthWidth,
            5
        );

    }

}


/* =========================
   MÜNZEN ZEICHNEN
========================= */

function drawCoins() {

    for (let coin of coinsObjects) {

        ctx.shadowColor = "#ffd600";
        ctx.shadowBlur = 15;

        ctx.fillStyle = "#ffd600";

        ctx.beginPath();

        ctx.arc(
            coin.x,
            coin.y,
            coin.radius,
            0,
            Math.PI * 2
        );

        ctx.fill();

        ctx.shadowBlur = 0;

        ctx.fillStyle = "#8d6e00";

        ctx.font = "bold 12px Arial";

        ctx.textAlign = "center";

        ctx.fillText(
            "$",
            coin.x,
            coin.y + 4
        );

    }

}


/* =========================
   PARTIKEL ZEICHNEN
========================= */

function drawParticles() {

    for (let particle of particles) {

        ctx.globalAlpha =
            particle.life / 60;

        ctx.fillStyle =
            particle.color;

        ctx.beginPath();

        ctx.arc(
            particle.x,
            particle.y,
            particle.size,
            0,
            Math.PI * 2
        );

        ctx.fill();

    }

    ctx.globalAlpha = 1;

}


/* =========================
   HUD
========================= */

function updateHUD() {

    document.getElementById("score").textContent =
        score;

    document.getElementById("coins").textContent =
        coins;

    document.getElementById("level").textContent =
        level;

    document.getElementById("enemyCount").textContent =
        enemies.length;


    let healthPercent =
        Math.max(
            0,
            player.health / player.maxHealth * 100
        );

    document.getElementById("healthBar").style.width =
        healthPercent + "%";


    let neededXP =
        level * 100;

    let xpPercent =
        Math.min(
            100,
            xp / neededXP * 100
        );

    document.getElementById("xpBar").style.width =
        xpPercent + "%";

}


/* =========================
   GAME OVER
========================= */

function gameOver() {

    gameRunning = false;

    document.getElementById("finalScore").textContent =
        score;

    document.getElementById("finalLevel").textContent =
        level;

    document.getElementById("finalCoins").textContent =
        coins;

    document.getElementById("gameOver").style.display =
        "flex";

}


/* =========================
   SPIEL LOOP
========================= */

function gameLoop() {

    if (!gameRunning) {
        return;
    }


    // Updates

    updatePlayer();

    updateBullets();

    updateEnemies();

    checkBulletCollisions();

    updateCoins();

    updateParticles();

    updateStars();

    updateHUD();


    // Zeichnen

    drawBackground();

    drawCoins();

    drawBullets();

    drawEnemies();

    drawPlayer();

    drawParticles();


    // Game Over

    if (player.health <= 0) {

        gameOver();

        return;

    }


    requestAnimationFrame(gameLoop);

}


/* =========================
   DEBUG / INFO
========================= */

console.log(
    "Galaxy Survivor gestartet!"
);

console.log(
    "Steuerung: WASD / Pfeiltasten + Leertaste"
);

</script>

</body>
</html>

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: