forms

Neon Invaders

Neon Invaders: The Ultimate Retro-Modern Arcade War
Prepare for a high-intensity, neon-drenched battle for Earth’s survival! Neon Invaders is a professional-grade reimagining of the legendary space shooter, optimized for modern web browsers with stunning "Cyberpunk" visuals and responsive gameplay.

🛸 Defend the Grid
Command your neon interceptor against waves of glowing mechanical invaders. As the commander, your objective is simple: eliminate the alien threat before they reach your base. But beware—as their numbers dwindle, their speed increases, and their desperation turns into a lethal blitz.

✨ Premium Game Features:
Cyberpunk Aesthetic: High-contrast visuals featuring electric greens, hot pinks, and neon blues against a deep space background.

Dynamic Enemy AI: Invaders move in strategic formations that accelerate and drop closer as the battle intensifies.

Explosive Particle Physics: Every hit and ship destruction triggers a vibrant burst of digital particles for a satisfying arcade feel.

Persistent High Scores: Compete against your past self with a built-in leaderboard that tracks your best performance.

Cross-Platform Optimized: Play seamlessly on desktop with keyboard controls or on mobile with a custom-designed touch interface.

🕹️ How to Play:
Launch: Click "INSERT COIN" to start your mission.

Move: Use the Left/Right Arrow Keys (Desktop) or On-Screen Buttons (Mobile) to navigate.

Attack: Press Space or the Fire Button to launch plasma bolts.

Strategy: Prioritize invaders at the edges to slow down their horizontal progression.

Code Snippet

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>Neon Invaders Arcade</title>
    <style>
        :root {
            --neon-green: #39ff14;
            --neon-blue: #00f3ff;
            --neon-pink: #ff00ff;
            --neon-red: #ff3131;
            --bg-dark: #050508;
        }

        * {
            box-sizing: border-box;
            user-select: none;
            touch-action: none;
        }

        body {
            margin: 0;
            padding: 0;
            background-color: #000;
            display: flex;
            align-items: center;
            justify-content: center;
            height: 100vh;
            width: 100vw;
            overflow: hidden;
            font-family: 'Courier New', Courier, monospace;
        }

        #game-container {
            position: relative;
            width: 100%;
            max-width: 600px;
            aspect-ratio: 4 / 5;
            background: var(--bg-dark);
            border: 3px solid #1a1a2e;
            box-shadow: 0 0 40px rgba(0, 243, 255, 0.15);
            border-radius: 8px;
            overflow: hidden;
        }

        canvas {
            display: block;
            width: 100%;
            height: 100%;
        }

        /* UI Elements */
        .hud {
            position: absolute;
            top: 0;
            width: 100%;
            padding: 15px 20px;
            display: flex;
            justify-content: space-between;
            color: var(--neon-blue);
            font-size: 1.2rem;
            text-shadow: 0 0 5px var(--neon-blue);
            z-index: 5;
            pointer-events: none;
        }

        .overlay {
            position: absolute;
            inset: 0;
            background: rgba(0, 0, 0, 0.85);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            z-index: 10;
            backdrop-filter: blur(5px);
            text-align: center;
        }

        h1 {
            color: var(--neon-green);
            font-size: 3rem;
            margin: 0;
            text-shadow: 0 0 20px var(--neon-green);
            letter-spacing: 5px;
        }

        .btn-action {
            margin-top: 30px;
            padding: 15px 40px;
            background: transparent;
            border: 2px solid var(--neon-blue);
            color: var(--neon-blue);
            font-family: inherit;
            font-size: 1.5rem;
            cursor: pointer;
            border-radius: 4px;
            transition: 0.3s;
            text-transform: uppercase;
        }

        .btn-action:hover {
            background: var(--neon-blue);
            color: #000;
            box-shadow: 0 0 20px var(--neon-blue);
        }

        .hidden { display: none !important; }

        /* Mobile Controls */
        #mobile-controls {
            position: absolute;
            bottom: 20px;
            width: 100%;
            display: flex;
            justify-content: space-around;
            padding: 0 20px;
            z-index: 5;
        }

        .ctrl-btn {
            width: 70px;
            height: 70px;
            background: rgba(255, 255, 255, 0.05);
            border: 1px solid var(--neon-blue);
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            color: var(--neon-blue);
            font-size: 1.5rem;
        }

        @media (min-width: 768px) {
            #mobile-controls { display: none; }
        }
    </style>
</head>
<body>

    <div id="game-container">
        <div class="hud">
            <div>SCORE: <span id="score-val">0</span></div>
            <div>HI: <span id="hi-val">0</span></div>
        </div>

        <div id="start-screen" class="overlay">
            <h1>NEON<br>INVADERS</h1>
            <p style="color: #666; margin-top: 10px;">[LEFT/RIGHT] to move. [SPACE] to fire.</p>
            <button class="btn-action" id="start-btn">INSERT COIN</button>
        </div>

        <div id="game-over-screen" class="overlay hidden">
            <h1 id="over-title" style="color: var(--neon-red); text-shadow: 0 0 20px var(--neon-red);">GAME OVER</h1>
            <p id="final-score" style="color: #fff; font-size: 1.2rem; margin-top: 20px;"></p>
            <button class="btn-action" id="restart-btn">RETRY</button>
        </div>

        <canvas id="gameCanvas"></canvas>

        <div id="mobile-controls">
            <div class="ctrl-btn" id="left-btn">◀</div>
            <div class="ctrl-btn" id="fire-btn">◉</div>
            <div class="ctrl-btn" id="right-btn">▶</div>
        </div>
    </div>

    <script>
        const canvas = document.getElementById('gameCanvas');
        const ctx = canvas.getContext('2d');
        const scoreVal = document.getElementById('score-val');
        const hiVal = document.getElementById('hi-val');
        const startScreen = document.getElementById('start-screen');
        const gameOverScreen = document.getElementById('game-over-screen');
        
        let gameActive = false;
        let score = 0;
        let hiScore = localStorage.getItem('neonInvadersHi') || 0;
        hiVal.innerText = hiScore;

        // Constants
        const INVADER_ROWS = 5;
        const INVADER_COLS = 10;
        const INVADER_SIZE = 30;

        // State
        let player, projectiles, enemyProjectiles, invaders, particles, stars;
        let keys = {};
        let enemyDirection = 1;
        let enemyMoveTimer = 0;
        let enemyMoveInterval = 40; // Frame count between steps
        let animationId;

        class Player {
            constructor() {
                this.width = 40;
                this.height = 20;
                this.x = canvas.width / 2 - this.width / 2;
                this.y = canvas.height - 40;
                this.speed = 5;
                this.color = '#00f3ff';
            }

            draw() {
                ctx.save();
                ctx.shadowBlur = 15;
                ctx.shadowColor = this.color;
                ctx.fillStyle = this.color;
                
                // Ship shape
                ctx.beginPath();
                ctx.moveTo(this.x + this.width / 2, this.y);
                ctx.lineTo(this.x + this.width, this.y + this.height);
                ctx.lineTo(this.x, this.y + this.height);
                ctx.closePath();
                ctx.fill();

                // Cockpit
                ctx.fillStyle = '#fff';
                ctx.fillRect(this.x + this.width/2 - 2, this.y + 5, 4, 8);
                ctx.restore();
            }

            update() {
                if (keys['ArrowLeft'] || keys['left']) this.x = Math.max(0, this.x - this.speed);
                if (keys['ArrowRight'] || keys['right']) this.x = Math.min(canvas.width - this.width, this.x + this.speed);
            }
        }

        class Invader {
            constructor(x, y, type) {
                this.x = x;
                this.y = y;
                this.width = INVADER_SIZE;
                this.height = 20;
                this.type = type; // 0, 1, 2 for different shapes
                this.color = type === 0 ? '#ff3131' : (type === 1 ? '#ff00ff' : '#39ff14');
            }

            draw() {
                ctx.save();
                ctx.shadowBlur = 10;
                ctx.shadowColor = this.color;
                ctx.fillStyle = this.color;
                
                // Simple pixel-art style invaders using rects
                if (this.type === 0) {
                    ctx.fillRect(this.x + 5, this.y, 20, 15);
                    ctx.fillRect(this.x, this.y + 5, 5, 5);
                    ctx.fillRect(this.x + 25, this.y + 5, 5, 5);
                } else if (this.type === 1) {
                    ctx.fillRect(this.x, this.y, 30, 10);
                    ctx.fillRect(this.x + 5, this.y + 10, 20, 5);
                    ctx.fillRect(this.x + 10, this.y - 5, 10, 5);
                } else {
                    ctx.fillRect(this.x + 5, this.y, 20, 10);
                    ctx.fillRect(this.x, this.y + 10, 30, 5);
                    ctx.fillRect(this.x + 5, this.y - 5, 5, 5);
                    ctx.fillRect(this.x + 20, this.y - 5, 5, 5);
                }
                ctx.restore();
            }
        }

        class Projectile {
            constructor(x, y, speed, color) {
                this.x = x;
                this.y = y;
                this.width = 3;
                this.height = 15;
                this.speed = speed;
                this.color = color;
            }

            draw() {
                ctx.save();
                ctx.shadowBlur = 10;
                ctx.shadowColor = this.color;
                ctx.fillStyle = this.color;
                ctx.fillRect(this.x, this.y, this.width, this.height);
                ctx.restore();
            }

            update() {
                this.y += this.speed;
            }
        }

        class Particle {
            constructor(x, y, color) {
                this.x = x;
                this.y = y;
                this.color = color;
                this.size = Math.random() * 3;
                this.vx = (Math.random() - 0.5) * 6;
                this.vy = (Math.random() - 0.5) * 6;
                this.life = 1.0;
            }

            update() {
                this.x += this.vx;
                this.y += this.vy;
                this.life -= 0.02;
            }

            draw() {
                ctx.globalAlpha = this.life;
                ctx.fillStyle = this.color;
                ctx.fillRect(this.x, this.y, this.size, this.size);
                ctx.globalAlpha = 1;
            }
        }

        function createStars() {
            stars = [];
            for (let i = 0; i < 50; i++) {
                stars.push({
                    x: Math.random() * canvas.width,
                    y: Math.random() * canvas.height,
                    size: Math.random() * 2,
                    speed: Math.random() * 0.5 + 0.1
                });
            }
        }

        function spawnInvaders() {
            invaders = [];
            for (let row = 0; row < INVADER_ROWS; row++) {
                for (let col = 0; col < INVADER_COLS; col++) {
                    const type = row === 0 ? 0 : (row < 3 ? 1 : 2);
                    invaders.push(new Invader(60 + col * 45, 80 + row * 40, type));
                }
            }
        }

        function resize() {
            const container = document.getElementById('game-container');
            canvas.width = container.clientWidth;
            canvas.height = container.clientHeight;
        }

        function init() {
            resize();
            player = new Player();
            projectiles = [];
            enemyProjectiles = [];
            particles = [];
            createStars();
            spawnInvaders();
            score = 0;
            scoreVal.innerText = score;
            enemyMoveInterval = 40;
            gameActive = true;
            startScreen.classList.add('hidden');
            gameOverScreen.classList.add('hidden');
            animate();
        }

        function explode(x, y, color) {
            for (let i = 0; i < 15; i++) {
                particles.push(new Particle(x, y, color));
            }
        }

        function endGame(victory = false) {
            gameActive = false;
            cancelAnimationFrame(animationId);
            if (score > hiScore) {
                hiScore = score;
                localStorage.setItem('neonInvadersHi', hiScore);
                hiVal.innerText = hiScore;
            }
            document.getElementById('over-title').innerText = victory ? "MISSION SUCCESS" : "MISSION FAILED";
            document.getElementById('over-title').style.color = victory ? 'var(--neon-green)' : 'var(--neon-red)';
            document.getElementById('final-score').innerText = `FINAL SCORE: ${score}`;
            gameOverScreen.classList.remove('hidden');
        }

        function animate() {
            if (!gameActive) return;
            ctx.fillStyle = 'rgba(5, 5, 8, 0.3)'; // Trail effect
            ctx.fillRect(0, 0, canvas.width, canvas.height);

            // Background Stars
            ctx.fillStyle = '#fff';
            stars.forEach(star => {
                ctx.fillRect(star.x, star.y, star.size, star.size);
                star.y += star.speed;
                if (star.y > canvas.height) star.y = 0;
            });

            player.update();
            player.draw();

            // Player Projectiles
            for (let i = projectiles.length - 1; i >= 0; i--) {
                const p = projectiles[i];
                p.update();
                p.draw();

                // Check collision with invaders
                invaders.forEach((invader, index) => {
                    if (p.x > invader.x && p.x < invader.x + invader.width && 
                        p.y > invader.y && p.y < invader.y + invader.height) {
                        explode(invader.x + 15, invader.y + 10, invader.color);
                        invaders.splice(index, 1);
                        projectiles.splice(i, 1);
                        score += 100;
                        scoreVal.innerText = score;
                        enemyMoveInterval = Math.max(5, 40 - (score / 500));
                    }
                });

                if (p.y < 0) projectiles.splice(i, 1);
            }

            // Enemy Projectiles
            for (let i = enemyProjectiles.length - 1; i >= 0; i--) {
                const ep = enemyProjectiles[i];
                ep.update();
                ep.draw();

                // Player collision
                if (ep.x > player.x && ep.x < player.x + player.width &&
                    ep.y > player.y && ep.y < player.y + player.height) {
                    explode(player.x + 20, player.y + 10, player.color);
                    endGame(false);
                }

                if (ep.y > canvas.height) enemyProjectiles.splice(i, 1);
            }

            // Invader Logic
            let edgeReached = false;
            invaders.forEach(invader => {
                invader.draw();
                if (enemyMoveTimer >= enemyMoveInterval) {
                    invader.x += 10 * enemyDirection;
                    if (invader.x > canvas.width - 40 || invader.x < 10) edgeReached = true;
                }
                
                // Reach bottom
                if (invader.y + invader.height > player.y) endGame(false);
            });

            if (enemyMoveTimer >= enemyMoveInterval) {
                if (edgeReached) {
                    enemyDirection *= -1;
                    invaders.forEach(inv => inv.y += 20);
                }
                enemyMoveTimer = 0;

                // Random enemy fire
                if (invaders.length > 0 && Math.random() < 0.3) {
                    const shooter = invaders[Math.floor(Math.random() * invaders.length)];
                    enemyProjectiles.push(new Projectile(shooter.x + 15, shooter.y + 20, 4, shooter.color));
                }
            }
            enemyMoveTimer++;

            if (invaders.length === 0) endGame(true);

            // Particles
            for (let i = particles.length - 1; i >= 0; i--) {
                particles[i].update();
                particles[i].draw();
                if (particles[i].life <= 0) particles.splice(i, 1);
            }

            animationId = requestAnimationFrame(animate);
        }

        // Input
        window.addEventListener('keydown', e => {
            keys[e.code] = true;
            if (e.code === 'Space' && gameActive && projectiles.length < 3) {
                projectiles.push(new Projectile(player.x + player.width/2 - 1.5, player.y - 10, -7, '#fff'));
            }
        });
        window.addEventListener('keyup', e => keys[e.code] = false);

        // Mobile Events
        const leftBtn = document.getElementById('left-btn');
        const rightBtn = document.getElementById('right-btn');
        const fireBtn = document.getElementById('fire-btn');

        leftBtn.ontouchstart = () => keys['left'] = true;
        leftBtn.ontouchend = () => keys['left'] = false;
        rightBtn.ontouchstart = () => keys['right'] = true;
        rightBtn.ontouchend = () => keys['right'] = false;
        fireBtn.ontouchstart = (e) => {
            e.preventDefault();
            if (gameActive && projectiles.length < 3) {
                projectiles.push(new Projectile(player.x + player.width/2 - 1.5, player.y - 10, -7, '#fff'));
            }
        };

        document.getElementById('start-btn').onclick = init;
        document.getElementById('restart-btn').onclick = init;

        window.onload = resize;
    </script>
</body>
</html>

Media & Assets

Neon Invaders
Resource ID: #00025
Posted: December 22, 2025
© 2025 Your Code Library.