Asteroid Blaster

Pasted Oct 22, 2026, 5:02 AM1 file588 lines

Scan to open on your phone

Point a camera at the QR code - it opens this exact paste, no app needed.

https://codepastes.com/zzgspt5yparpx3rq
Asteroid Blaster
<!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, viewport-fit=cover">
    
    <!-- iOS PWA Meta Tags for Web App Installation -->
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="apple-mobile-web-app-title" content="Cosmic Defender">
    
    <title>Cosmic Defender</title>
    <style>
        * {
            box-sizing: border-box;
            user-select: none;
            -webkit-user-select: none;
            margin: 0;
            padding: 0;
        }
        body, html {
            width: 100%;
            height: 100%;
            overflow: hidden;
            background-color: #000;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            position: fixed;
        }
        #gameContainer {
            position: relative;
            width: 100vw;
            height: 100vh;
            background: radial-gradient(circle at center, #0c102b 0%, #010206 100%);
        }
        canvas {
            display: block;
            width: 100%;
            height: 100%;
        }
        
        /* HUD Layout */
        .hud {
            position: absolute;
            top: env(safe-area-inset-top, 20px);
            left: 20px;
            right: 20px;
            display: flex;
            justify-content: space-between;
            color: #fff;
            pointer-events: none;
            font-size: 16px;
            font-weight: bold;
            text-shadow: 0 2px 4px rgba(0,0,0,0.8);
            z-index: 10;
        }
        .health-container {
            width: 140px;
            height: 12px;
            background: rgba(255,255,255,0.2);
            border-radius: 6px;
            overflow: hidden;
            margin-top: 5px;
            border: 1px solid rgba(255,255,255,0.4);
        }
        #healthBar {
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, #ff416c, #ff4b2b);
            transition: width 0.2s ease;
        }

        /* Split Control Interface */
        .control-layer {
            position: absolute;
            bottom: env(safe-area-inset-bottom, 20px);
            left: 0;
            right: 0;
            height: 160px;
            display: flex;
            justify-content: space-between;
            padding: 0 40px;
            pointer-events: none;
            z-index: 20;
        }
        .btn-group {
            display: flex;
            flex-direction: column;
            justify-content: center;
            gap: 15px;
            pointer-events: auto;
        }
        .ctrl-btn {
            width: 70px;
            height: 70px;
            background: rgba(255, 255, 255, 0.12);
            border: 2px solid rgba(255, 255, 255, 0.3);
            border-radius: 50%;
            color: white;
            font-size: 24px;
            display: flex;
            align-items: center;
            justify-content: center;
            backdrop-filter: blur(5px);
            -webkit-backdrop-filter: blur(5px);
        }
        .ctrl-btn:active {
            background: rgba(255, 255, 255, 0.35);
            border-color: #fff;
        }
        
        /* Slider Region */
        .slider-region {
            width: 180px;
            height: 80px;
            background: rgba(255, 255, 255, 0.08);
            border: 2px dashed rgba(255, 255, 255, 0.2);
            border-radius: 40px;
            align-self: center;
            position: relative;
            pointer-events: auto;
            display: flex;
            align-items: center;
            justify-content: center;
            color: rgba(255,255,255,0.4);
            font-size: 12px;
        }
        .slider-handle {
            position: absolute;
            width: 64px;
            height: 64px;
            background: radial-gradient(circle, #4facfe 0%, #00f2fe 100%);
            border-radius: 50%;
            box-shadow: 0 0 15px #00f2fe;
            left: calc(50% - 32px);
            top: calc(50% - 32px);
            touch-action: none;
        }

        /* Action Buttons Right Side */
        .right-actions {
            display: flex;
            align-items: center;
            gap: 20px;
            pointer-events: auto;
        }
        .action-btn {
            width: 80px;
            height: 80px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
            color: #fff;
            box-shadow: 0 4px 15px rgba(0,0,0,0.5);
        }
        #fireBtn {
            background: radial-gradient(circle, #ff0844 0%, #ffb199 100%);
            box-shadow: 0 0 20px #ff0844;
            font-size: 18px;
        }
        #shopBtn {
            background: radial-gradient(circle, #f6d365 0%, #fda085 100%);
            font-size: 14px;
            width: 65px;
            height: 65px;
        }

        /* Shop Modal Layer */
        .modal {
            display: none;
            position: absolute;
            top: 0; left: 0; width: 100%; height: 100%;
            background: rgba(0,0,0,0.85);
            z-index: 100;
            justify-content: center;
            align-items: center;
            color: white;
        }
        .shop-box {
            background: #111625;
            border: 2px solid #4facfe;
            border-radius: 16px;
            padding: 25px;
            width: 85%;
            max-width: 400px;
            text-align: center;
        }
        .shop-title {
            font-size: 24px;
            margin-bottom: 20px;
            color: #00f2fe;
        }
        .shop-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            background: rgba(255,255,255,0.05);
            padding: 12px;
            margin-bottom: 12px;
            border-radius: 8px;
        }
        .shop-item button {
            background: #00f2fe;
            border: none;
            padding: 8px 16px;
            border-radius: 4px;
            font-weight: bold;
            color: #000;
        }
        .close-shop {
            margin-top: 15px;
            background: #ff0844;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 6px;
            font-weight: bold;
        }
    </style>
</head>
<body>

<div id="gameContainer">
    <!-- Game HUD -->
    <div class="hud">
        <div>
            <div id="scoreDisplay">SCORE: 0</div>
            <div class="health-container"><div id="healthBar"></div></div>
        </div>
        <div style="text-align: right;">
            <div id="levelDisplay">LEVEL: 1</div>
            <div id="scrapDisplay">SCRAP: 0</div>
        </div>
    </div>

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

    <!-- Interactive Splits Interface -->
    <div class="control-layer">
        <!-- Left Wing: Fixed Up/Down layout -->
        <div class="btn-group">
            <div class="ctrl-btn" id="upBtn">▲</div>
            <div class="ctrl-btn" id="downBtn">▼</div>
        </div>

        <!-- Center-Right: Axis slider for side-to-side navigation -->
        <div class="slider-region" id="sliderRegion">
            SLIDE
            <div class="slider-handle" id="sliderHandle"></div>
        </div>

        <!-- Far Right Side: Combat & Utility Actions -->
        <div class="right-actions">
            <div class="action-btn" id="shopBtn">SHOP</div>
            <div class="action-btn" id="fireBtn">FIRE</div>
        </div>
    </div>
</div>

<!-- Shop UI Window -->
<div class="modal" id="shopModal">
    <div class="shop-box">
        <div class="shop-title">UPGRADE SHOP</div>
        <div class="shop-item">
            <div>Laser Speed (<span id="laserLvl">1</span>)</div>
            <button id="buyLaser">Cost: 15</button>
        </div>
        <div class="shop-item">
            <div>Max Health (<span id="healthLvl">1</span>)</div>
            <button id="buyHealth">Cost: 20</button>
        </div>
        <button class="close-shop" id="closeShopBtn">BACK TO SPACE</button>
    </div>
</div>

<script>
    // --- Secure Mathematical Integrity State Architecture ---
    const _secureState = {
        _scoreHash: 0,
        _scoreSalt: 4829,
        setScore(val) {
            this._scoreHash = val ^ this._scoreSalt;
        },
        getScore() {
            return this._scoreHash ^ this._scoreSalt;
        }
    };

    const canvas = document.getElementById('gameCanvas');
    const ctx = canvas.getContext('2d');

    // Display scaling normalization
    function resize() {
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
    }
    window.addEventListener('resize', resize);
    resize();

    // Global Systems Configs
    let player = {
        x: canvas.width / 2,
        y: canvas.height * 0.7,
        r: 18,
        hp: 100,
        maxHp: 100,
        speed: 6,
        lastRegenTime: Date.now()
    };

    let scrap = 0;
    let currentLevel = 1;
    let lastFireTime = 0;
    let fireDelay = 400; //ms
    let lastDamageTime = 0;

    let lasers = [];
    let asteroids = [];
    let stars = [];

    // Controller variables
    let moveUp = false;
    let moveDown = false;
    let slideXValue = 0; 

    // Starfield Background Initialization
    for(let i=0; i<60; i++) {
        stars.push({x: Math.random()*canvas.width, y: Math.random()*canvas.height, s: Math.random()*2 + 0.5});
    }

    // --- Dynamic Slider Engine Layout Config ---
    const sliderRegion = document.getElementById('sliderRegion');
    const sliderHandle = document.getElementById('sliderHandle');
    let sliderActive = false;
    let sliderStartX = 0;

Use code with caution.
sliderHandle.addEventListener('touchstart', (e) => {
sliderActive = true;
sliderStartX = e.touches.clientX - sliderHandle.offsetLeft;
});
window.addEventListener('touchmove', (e) => {
if (!sliderActive) return;
let bounds = sliderRegion.getBoundingClientRect();
let clientX = e.touches.clientX;
let relativeX = clientX - bounds.left - 32; // handle half-width center lock
// Strict boundary constraints
let maxLimit = bounds.width - 64;
if(relativeX < 0) relativeX = 0;
if(relativeX > maxLimit) relativeX = maxLimit;
sliderHandle.style.left = relativeX + 'px';
// Map positional parameters directly to scalar speed velocities (-1 to 1)
let midpoint = maxLimit / 2;
slideXValue = (relativeX - midpoint) / midpoint;
});
window.addEventListener('touchend', () => {
if(!sliderActive) return;
sliderActive = false;
sliderHandle.style.left = 'calc(50% - 32px)';
slideXValue = 0; // Return velocity back to baseline axis rest
});
// Fixed Buttons Event Routing
const bindBtn = (el, pressCallback, releaseCallback) => {
el.addEventListener('touchstart', (e) => { e.preventDefault(); pressCallback(); });
el.addEventListener('touchend', (e) => { e.preventDefault(); releaseCallback(); });
};
bindBtn(document.getElementById('upBtn'), () => moveUp = true, () => moveUp = false);
bindBtn(document.getElementById('downBtn'), () => moveDown = true, () => moveDown = false);
// Continuous fire system mapping
let continuousFiring = false;
document.getElementById('fireBtn').addEventListener('touchstart', (e) => { e.preventDefault(); continuousFiring = true; });
document.getElementById('fireBtn').addEventListener('touchend', () => continuousFiring = false);
// --- Upgrade Progression Engine Layout ---
const shopModal = document.getElementById('shopModal');
document.getElementById('shopBtn').addEventListener('click', () => shopModal.style.display = 'flex');
document.getElementById('closeShopBtn').addEventListener('click', () => shopModal.style.display = 'none');
let upgLaserLvl = 1;
let upgHealthLvl = 1;
document.getElementById('buyLaser').addEventListener('click', () => {
let cost = upgLaserLvl * 15;
if(scrap >= cost) {
scrap -= cost;
upgLaserLvl++;
fireDelay = Math.max(150, fireDelay - 60);
document.getElementById('laserLvl').innerText = upgLaserLvl;
document.getElementById('buyLaser').innerText = Cost: ${upgLaserLvl * 15};
updateHUD();
}
});
document.getElementById('buyHealth').addEventListener('click', () => {
let cost = upgHealthLvl * 20;
if(scrap >= cost) {
scrap -= cost;
upgHealthLvl++;
player.maxHp += 25;
player.hp = player.maxHp;
document.getElementById('healthLvl').innerText = upgHealthLvl;
document.getElementById('buyHealth').innerText = Cost: ${upgHealthLvl * 20};
updateHUD();
}
});
function updateHUD() {
document.getElementById('scoreDisplay').innerText = SCORE: ${_secureState.getScore()};
document.getElementById('scrapDisplay').innerText = SCRAP: ${scrap};
document.getElementById('levelDisplay').innerText = LEVEL: ${currentLevel};
document.getElementById('healthBar').style.width = ${(player.hp / player.maxHp) * 100}%;
}
function spawnAsteroid() {
let types = ['Standard', 'Fast', 'Armored', 'Explosive'];
let weights = [0.6, 0.2, 0.1, 0.1];
// Randomly select type based on raw procedural metrics
let rand = Math.random();
let selectedType = 'Standard';
let sum = 0;
for(let i=0; i<types.length; i++) {
sum += weights[i];
if(rand <= sum) { selectedType = types[i]; break; }
}
let radius = 20;
let speed = (Math.random() * 2 + 1.5) * (1 + currentLevel * 0.15);
let hp = 1;
let color = '#a1a8b8';
if(selectedType === 'Fast') {
radius = 12; speed *= 1.8; color = '#38ef7d';
} else if(selectedType === 'Armored') {
radius = 35; speed *= 0.6; hp = 4; color = '#ff9900';
} else if(selectedType === 'Explosive') {
radius = 22; speed *= 1.1; color = '#ff0844';
}
asteroids.push({
x: Math.random() * (canvas.width - 40) + 20,
y: -radius,
r: radius,
speed: speed,
hp: hp,
maxHp: hp,
type: selectedType,
color: color
});
}
function createExplosion(x, y, radius) {
// Trigger damage updates to hazards within immediate proximity metrics
for(let i = asteroids.length - 1; i >= 0; i--) {
let a = asteroids[i];
let dist = Math.hypot(a.x - x, a.y - y);
if(dist < radius + a.r) {
a.hp -= 3;
}
}
}
// --- Processing Game Loop Context ---
function update(dt) {
// Passive Nano Shield Regeneration Check
if(Date.now() - lastDamageTime > 4000) { // 4 seconds of avoiding threat vector
if(player.hp < player.maxHp) {
player.hp = Math.min(player.maxHp, player.hp + 0.12);
updateHUD();
}
}
// Navigation positioning parameters updates
if(moveUp) player.y -= player.speed;
if(moveDown) player.y += player.speed;
player.x += slideXValue * player.speed * 1.3;
// Screen space limits configuration
if(player.x < player.r) player.x = player.r;
if(player.x > canvas.width - player.r) player.x = canvas.width - player.r;
if(player.y < player.r) player.y = player.r;
if(player.y > canvas.height - player.r) player.y = canvas.height - player.r;
// Fire rate evaluation loops
if(continuousFiring && Date.now() - lastFireTime > fireDelay) {
lasers.push({x: player.x, y: player.y - player.r, speed: 9});
lastFireTime = Date.now();
}
// Update standard objects layout arrays
stars.forEach(s => {
s.y += s.s;
if(s.y > canvas.height) s.y = 0;
});
lasers.forEach((l, index) => {
l.y -= l.speed;
if(l.y < 0) lasers.splice(index, 1);
});
// Dynamic difficulty progression calculations
let targetScore = currentLevel * 150;
if(_secureState.getScore() >= targetScore) {
currentLevel++;
updateHUD();
}
if(Math.random() < 0.02 + (currentLevel * 0.005)) {
spawnAsteroid();
}
for (let i = asteroids.length - 1; i >= 0; i--) {
let a = asteroids[i];
a.y += a.speed;
// Handle off screen memory clearance
if(a.y > canvas.height + a.r) {
asteroids.splice(i, 1);
continue;
}
// Object overlapping calculations (Laser to Asteroid)
for(let j = lasers.length - 1; j >= 0; j--) {
let l = lasers[j];
if(Math.hypot(a.x - l.x, a.y - l.y) < a.r) {
lasers.splice(j, 1);
a.hp--;
if(a.hp <= 0) {
if(a.type === 'Explosive') {
createExplosion(a.x, a.y, 120);
}
_secureState.setScore(_secureState.getScore() + (a.maxHp * 10));
scrap += Math.random() > 0.4 ? 1 : 0; // Scrap drop calculation mechanics
asteroids.splice(i, 1);
updateHUD();
break;
}
}
}
// Ship to Hazard Collision calculation loops
if(asteroids[i] && Math.hypot(a.x - player.x, a.y - player.y) < a.r + player.r) {
let dmg = a.type === 'Armored' ? 35 : 15;
player.hp -= dmg;
lastDamageTime = Date.now();
asteroids.splice(i, 1);
updateHUD();
if(player.hp <= 0) {
alert(GAME OVER\nFinal Score: ${_secureState.getScore()});
// State memory recovery back to initial defaults
_secureState.setScore(0);
scrap = 0;
currentLevel = 1;
player.maxHp = 100;
player.hp = 100;
asteroids = [];
lasers = [];
updateHUD();
}
}
}
}
// Visual rendering loop contexts
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw structural elements (Stars Background)
ctx.fillStyle = 'rgba(255,255,255,0.7)';
stars.forEach(s => {
ctx.fillRect(s.x, s.y, s.s, s.s);
});
// Draw combat assets (Lasers)
ctx.fillStyle = '#00f2fe';
lasers.forEach(l => {
ctx.fillRect(l.x - 2, l.y, 4, 12);
});
// Draw structural hazard assets (Asteroids)
asteroids.forEach(a => {
ctx.fillStyle = a.color;
ctx.beginPath();
ctx.arc(a.x, a.y, a.r, 0, Math.PI*2);
ctx.fill();
// Render health indicators on heavily armored rocks
if(a.type === 'Armored' && a.hp < a.maxHp) {
ctx.fillStyle = '#ff0000';
ctx.fillRect(a.x - 15, a.y - a.r - 8, 30, 4);
ctx.fillStyle = '#00ff00';
ctx.fillRect(a.x - 15, a.y - a.r - 8, (a.hp / a.maxHp) * 30, 4);
}
});
// Render Player Avatar Model
ctx.fillStyle = '#ffffff';
ctx.shadowColor = '#4facfe';
ctx.shadowBlur = 10;
ctx.beginPath();
ctx.moveTo(player.x, player.y - player.r);
ctx.lineTo(player.x - player.r, player.y + player.r);
ctx.lineTo(player.x + player.r, player.y + player.r);
ctx.closePath();
ctx.fill();
ctx.shadowBlur = 0; // Clear blur constraints filter for optimization performance
}
function loop() {
update();
draw();
requestAnimationFrame(loop);
}
// Begin main system loops execution context
updateHUD();
loop();

18,052 chars · codepastes.com