XTaylorSpenceX

Code Cascade Citadel

Sep 28th, 2025
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 48.89 KB | None | 0 0
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>Code Cascade Citadel</title>
  7.     <style>
  8.         * {
  9.             margin: 0;
  10.             padding: 0;
  11.             box-sizing: border-box;
  12.         }
  13.  
  14.         body {
  15.             background: linear-gradient(135deg, #0a0e27 0%, #151932 100%);
  16.             color: #00ffcc;
  17.             font-family: 'Courier New', monospace;
  18.             overflow: hidden;
  19.             position: relative;
  20.             height: 100vh;
  21.         }
  22.  
  23.         #gameCanvas {
  24.             position: absolute;
  25.             top: 0;
  26.             left: 0;
  27.             background: radial-gradient(ellipse at center, rgba(0,255,204,0.05) 0%, transparent 70%);
  28.         }
  29.  
  30.         #ui {
  31.             position: absolute;
  32.             top: 10px;
  33.             left: 10px;
  34.             z-index: 100;
  35.             background: rgba(10,14,39,0.9);
  36.             padding: 15px;
  37.             border: 2px solid #00ffcc;
  38.             border-radius: 5px;
  39.             box-shadow: 0 0 20px rgba(0,255,204,0.3);
  40.         }
  41.  
  42.         #ui h2 {
  43.             margin-bottom: 10px;
  44.             text-shadow: 0 0 10px #00ffcc;
  45.         }
  46.  
  47.         .stat {
  48.             margin: 5px 0;
  49.             display: flex;
  50.             justify-content: space-between;
  51.             min-width: 200px;
  52.         }
  53.  
  54.         .stat-value {
  55.             color: #fff;
  56.             font-weight: bold;
  57.         }
  58.  
  59.         #controls {
  60.             position: absolute;
  61.             bottom: 20px;
  62.             left: 50%;
  63.             transform: translateX(-50%);
  64.             display: flex;
  65.             gap: 10px;
  66.             z-index: 100;
  67.         }
  68.  
  69.         button {
  70.             background: linear-gradient(135deg, #00ffcc 0%, #00ccff 100%);
  71.             border: none;
  72.             color: #0a0e27;
  73.             padding: 10px 20px;
  74.             font-family: inherit;
  75.             font-weight: bold;
  76.             cursor: pointer;
  77.             border-radius: 5px;
  78.             transition: all 0.3s;
  79.             box-shadow: 0 0 15px rgba(0,255,204,0.5);
  80.         }
  81.  
  82.         button:hover {
  83.             transform: translateY(-2px);
  84.             box-shadow: 0 5px 20px rgba(0,255,204,0.7);
  85.         }
  86.  
  87.         button:disabled {
  88.             opacity: 0.5;
  89.             cursor: not-allowed;
  90.         }
  91.  
  92.         .code-particle {
  93.             position: absolute;
  94.             color: #00ffcc;
  95.             font-size: 10px;
  96.             pointer-events: none;
  97.             animation: fall 2s linear infinite;
  98.             text-shadow: 0 0 5px currentColor;
  99.         }
  100.  
  101.         @keyframes fall {
  102.             to {
  103.                 transform: translateY(100vh);
  104.                 opacity: 0;
  105.             }
  106.         }
  107.  
  108.         #gameOver {
  109.             position: absolute;
  110.             top: 50%;
  111.             left: 50%;
  112.             transform: translate(-50%, -50%);
  113.             background: rgba(10,14,39,0.95);
  114.             padding: 30px;
  115.             border: 3px solid #ff0066;
  116.             border-radius: 10px;
  117.             text-align: center;
  118.             display: none;
  119.             z-index: 200;
  120.             box-shadow: 0 0 30px rgba(255,0,102,0.5);
  121.         }
  122.  
  123.         #gameOver h2 {
  124.             color: #ff0066;
  125.             margin-bottom: 15px;
  126.             text-shadow: 0 0 10px #ff0066;
  127.         }
  128.  
  129.         .tooltip {
  130.             position: absolute;
  131.             background: rgba(0,0,0,0.9);
  132.             padding: 5px 10px;
  133.             border-radius: 3px;
  134.             font-size: 12px;
  135.             pointer-events: none;
  136.             z-index: 150;
  137.             display: none;
  138.             border: 1px solid #00ffcc;
  139.         }
  140.     </style>
  141. </head>
  142. <body>
  143.     <canvas id="gameCanvas"></canvas>
  144.    
  145.     <div id="ui">
  146.         <h2>Code Cascade Citadel</h2>
  147.         <div class="stat">
  148.             <span>Power:</span>
  149.             <span class="stat-value" id="power">100</span>
  150.         </div>
  151.         <div class="stat">
  152.             <span>Bugs:</span>
  153.             <span class="stat-value" id="bugs">0</span>
  154.         </div>
  155.         <div class="stat">
  156.             <span>Wave:</span>
  157.             <span class="stat-value" id="wave">1</span>
  158.         </div>
  159.         <div class="stat">
  160.             <span>Score:</span>
  161.             <span class="stat-value" id="score">0</span>
  162.         </div>
  163.     </div>
  164.  
  165.     <div id="controls">
  166.         <button onclick="game.buildGate('AND')">AND Gate [10]</button>
  167.         <button onclick="game.buildGate('OR')">OR Gate [15]</button>
  168.         <button onclick="game.buildGate('NOT')">NOT Gate [8]</button>
  169.         <button onclick="game.buildGate('XOR')">XOR Gate [20]</button>
  170.         <button onclick="game.buildBombTower()">Bomb Tower [5]</button>
  171.     </div>
  172.  
  173.     <div id="gameOver">
  174.         <h2>SYSTEM CORRUPTED</h2>
  175.         <p>Final Score: <span id="finalScore">0</span></p>
  176.         <p>Waves Survived: <span id="finalWave">0</span></p>
  177.         <button onclick="location.reload()">Restart</button>
  178.     </div>
  179.  
  180.     <div class="tooltip" id="tooltip"></div>
  181.  
  182.     <script>
  183.         const canvas = document.getElementById('gameCanvas');
  184.         const ctx = canvas.getContext('2d');
  185.         canvas.width = window.innerWidth;
  186.         canvas.height = window.innerHeight;
  187.  
  188.         class CodeParticle {
  189.             constructor(x, y) {
  190.                 this.x = x;
  191.                 this.y = y;
  192.                 this.text = ['if', 'else', 'for', 'while', 'function', 'var', 'let', 'const', '{}', '[]', '=>', '==='][Math.floor(Math.random() * 12)];
  193.                 this.speed = Math.random() * 2 + 1;
  194.                 this.opacity = 1;
  195.                 this.glow = Math.random() * 0.5 + 0.5;
  196.             }
  197.  
  198.             update() {
  199.                 this.y += this.speed;
  200.                 this.opacity -= 0.005;
  201.                 this.glow = Math.sin(Date.now() * 0.001 + this.x) * 0.3 + 0.7;
  202.             }
  203.  
  204.             draw() {
  205.                 ctx.save();
  206.                 ctx.globalAlpha = this.opacity * this.glow;
  207.                 ctx.fillStyle = '#00ffcc';
  208.                 ctx.shadowBlur = 10;
  209.                 ctx.shadowColor = '#00ffcc';
  210.                 ctx.font = '12px Courier New';
  211.                 ctx.fillText(this.text, this.x, this.y);
  212.                 ctx.restore();
  213.             }
  214.         }
  215.  
  216.         class LogicGate {
  217.             constructor(x, y, type) {
  218.                 this.x = x;
  219.                 this.y = y;
  220.                 this.type = type;
  221.                 this.health = 100;
  222.                 this.maxHealth = 100;
  223.                 this.active = true;
  224.                 this.power = this.getPower();
  225.                 this.range = 150;
  226.                 this.cooldown = 0;
  227.                 this.corrupted = false;
  228.                 this.decayRate = this.getDecayRate();
  229.                 this.shots = 0;
  230.                 this.maxShots = this.getMaxShots();
  231.             }
  232.  
  233.             getPower() {
  234.                 const powers = { AND: 5, OR: 7, NOT: 4, XOR: 10 };
  235.                 return powers[this.type] || 5;
  236.             }
  237.  
  238.             getDecayRate() {
  239.                 // Different gates have different durability
  240.                 const decay = { AND: 5, OR: 4, NOT: 8, XOR: 3 };
  241.                 return decay[this.type] || 5;
  242.             }
  243.  
  244.             getMaxShots() {
  245.                 // Maximum shots before breakdown (increased durability)
  246.                 const shots = { AND: 40, OR: 50, NOT: 25, XOR: 60 };
  247.                 return shots[this.type] || 40;
  248.             }
  249.  
  250.             update(bugs) {
  251.                 // Natural decay over time (reduced by 50%)
  252.                 if (this.health > 0) {
  253.                     this.health -= 0.01;  // Was 0.02, now 50% slower
  254.                 }
  255.  
  256.                 if (this.corrupted) {
  257.                     this.health -= 0.25;  // Was 0.5, now 50% slower
  258.                     if (this.health <= 0) {
  259.                        this.active = false;
  260.                        // Create disintegration effect
  261.                        this.createDisintegrationEffect();
  262.                    }
  263.                    return;
  264.                }
  265.  
  266.                if (this.cooldown > 0) {
  267.                     this.cooldown--;
  268.                     return;
  269.                 }
  270.  
  271.                 // Attack nearby bugs
  272.                 for (let bug of bugs) {
  273.                     if (!bug.active) continue;
  274.                     const dist = Math.hypot(bug.x - this.x, bug.y - this.y);
  275.                     if (dist < this.range) {
  276.                        this.attack(bug);
  277.                        this.cooldown = 30;
  278.                        
  279.                        // Decay from usage (reduced by 50%)
  280.                        this.shots++;
  281.                        this.health -= this.decayRate * 0.5;  // Reduced decay rate
  282.                        
  283.                        // Check if gate breaks down
  284.                        if (this.health <= 0 || this.shots >= this.maxShots) {
  285.                             this.active = false;
  286.                             this.createDisintegrationEffect();
  287.                         }
  288.                         break;
  289.                     }
  290.                 }
  291.             }
  292.  
  293.             createDisintegrationEffect() {
  294.                 // Create particle effect for disintegration
  295.                 for (let i = 0; i < 10; i++) {
  296.                    game.effects.push({
  297.                        type: 'particle',
  298.                        x: this.x + Math.random() * 40 - 20,
  299.                        y: this.y + Math.random() * 40 - 20,
  300.                        vx: Math.random() * 4 - 2,
  301.                        vy: Math.random() * -4 - 1,
  302.                        lifetime: 30,
  303.                        color: this.corrupted ? '#ff0066' : '#00ffcc'
  304.                    });
  305.                }
  306.            }
  307.  
  308.            attack(bug) {
  309.                // Draw attack beam
  310.                game.effects.push({
  311.                    type: 'beam',
  312.                    x1: this.x,
  313.                    y1: this.y,
  314.                    x2: bug.x,
  315.                    y2: bug.y,
  316.                    lifetime: 10
  317.                });
  318.                bug.takeDamage(this.power);
  319.            }
  320.  
  321.            draw() {
  322.                if (!this.active) return;
  323.  
  324.                ctx.save();
  325.                
  326.                // Draw range indicator when hovering or dragging
  327.                if (game.hoveredGate === this || draggedObject === this) {
  328.                    ctx.beginPath();
  329.                    ctx.arc(this.x, this.y, this.range, 0, Math.PI * 2);
  330.                    ctx.strokeStyle = 'rgba(0,255,204,0.2)';
  331.                    ctx.stroke();
  332.                }
  333.                
  334.                // Highlight if being dragged
  335.                if (draggedObject === this) {
  336.                    ctx.shadowBlur = 25;
  337.                    ctx.shadowColor = '#00ffff';
  338.                }
  339.  
  340.                // Fade based on health
  341.                const healthRatio = this.health / this.maxHealth;
  342.                ctx.globalAlpha = Math.max(0.4, healthRatio);
  343.  
  344.                // Gate body (show deterioration)
  345.                ctx.fillStyle = this.corrupted ? '#ff0066' : '#00ffcc';
  346.                ctx.strokeStyle = this.corrupted ? '#ff0066' : '#00ffcc';
  347.                
  348.                // Add deterioration visual effect
  349.                if (healthRatio < 0.5) {
  350.                    // Flickering effect when low health
  351.                    if (Math.random() < 0.1) {
  352.                        ctx.strokeStyle = '#ff6600';
  353.                    }
  354.                }
  355.                
  356.                ctx.lineWidth = 2;
  357.                if (!draggedObject || draggedObject !== this) {
  358.                    ctx.shadowBlur = 15 * healthRatio;
  359.                    ctx.shadowColor = this.corrupted ? '#ff0066' : '#00ffcc';
  360.                }
  361.  
  362.                // Different shapes for different gates
  363.                ctx.beginPath();
  364.                switch(this.type) {
  365.                    case 'AND':
  366.                        ctx.moveTo(this.x - 20, this.y - 20);
  367.                        ctx.lineTo(this.x + 10, this.y - 20);
  368.                        ctx.arc(this.x + 10, this.y, 20, -Math.PI/2, Math.PI/2);
  369.                        ctx.lineTo(this.x - 20, this.y + 20);
  370.                        ctx.closePath();
  371.                        break;
  372.                    case 'OR':
  373.                        ctx.moveTo(this.x - 20, this.y - 20);
  374.                        ctx.quadraticCurveTo(this.x + 20, this.y - 20, this.x + 25, this.y);
  375.                        ctx.quadraticCurveTo(this.x + 20, this.y + 20, this.x - 20, this.y + 20);
  376.                        ctx.quadraticCurveTo(this.x - 10, this.y, this.x - 20, this.y - 20);
  377.                        break;
  378.                    case 'NOT':
  379.                        ctx.moveTo(this.x - 20, this.y - 15);
  380.                        ctx.lineTo(this.x + 15, this.y);
  381.                        ctx.lineTo(this.x - 20, this.y + 15);
  382.                        ctx.closePath();
  383.                        ctx.stroke();
  384.                        ctx.beginPath();
  385.                        ctx.arc(this.x + 20, this.y, 5, 0, Math.PI * 2);
  386.                        break;
  387.                    case 'XOR':
  388.                        ctx.moveTo(this.x - 25, this.y - 20);
  389.                        ctx.quadraticCurveTo(this.x - 15, this.y, this.x - 25, this.y + 20);
  390.                        ctx.moveTo(this.x - 20, this.y - 20);
  391.                        ctx.quadraticCurveTo(this.x + 20, this.y - 20, this.x + 25, this.y);
  392.                        ctx.quadraticCurveTo(this.x + 20, this.y + 20, this.x - 20, this.y + 20);
  393.                        ctx.quadraticCurveTo(this.x - 10, this.y, this.x - 20, this.y - 20);
  394.                        break;
  395.                }
  396.                ctx.stroke();
  397.                ctx.globalAlpha = 0.3 * healthRatio;
  398.                ctx.fill();
  399.  
  400.                // Health bar (always visible now)
  401.                ctx.globalAlpha = 1;
  402.                ctx.fillStyle = '#330000';
  403.                ctx.fillRect(this.x - 20, this.y - 35, 40, 4);
  404.                
  405.                // Color changes based on health
  406.                if (healthRatio > 0.6) {
  407.                     ctx.fillStyle = '#00ff66';
  408.                 } else if (healthRatio > 0.3) {
  409.                     ctx.fillStyle = '#ffaa00';
  410.                 } else {
  411.                     ctx.fillStyle = '#ff0066';
  412.                 }
  413.                 ctx.fillRect(this.x - 20, this.y - 35, 40 * healthRatio, 4);
  414.  
  415.                 // Shot counter indicator
  416.                 ctx.font = '8px Courier New';
  417.                 ctx.fillStyle = '#00ffcc';
  418.                 ctx.textAlign = 'center';
  419.                 ctx.globalAlpha = 0.8;
  420.                 ctx.fillText(`${this.maxShots - this.shots}`, this.x, this.y + 25);
  421.  
  422.                 ctx.restore();
  423.             }
  424.         }
  425.  
  426.         class BombTower {
  427.             constructor(x, y) {
  428.                 this.x = x;
  429.                 this.y = y;
  430.                 this.active = true;
  431.                 this.armed = false;
  432.                 this.armTimer = 60; // Takes 1 second to arm
  433.                 this.exploding = false;
  434.                 this.explosionRadius = 120;
  435.                 this.explosionTimer = 0;
  436.                 this.pulsePhase = 0;
  437.                 this.triggered = false;
  438.             }
  439.  
  440.             update(bugs) {
  441.                 if (!this.active || this.exploding) return;
  442.  
  443.                 // Arming phase
  444.                 if (!this.armed) {
  445.                     this.armTimer--;
  446.                     if (this.armTimer <= 0) {
  447.                        this.armed = true;
  448.                    }
  449.                    return;
  450.                }
  451.  
  452.                // Check for nearby bugs to trigger explosion
  453.                for (let bug of bugs) {
  454.                    if (!bug.active) continue;
  455.                    const dist = Math.hypot(bug.x - this.x, bug.y - this.y);
  456.                    if (dist < 40 && !this.triggered) { // Trigger range
  457.                        this.triggered = true;
  458.                        this.explode(bugs);
  459.                        break;
  460.                    }
  461.                }
  462.  
  463.                // Pulsing effect when armed
  464.                this.pulsePhase += 0.1;
  465.            }
  466.  
  467.            explode(bugs) {
  468.                this.exploding = true;
  469.                
  470.                // Damage all bugs in explosion radius
  471.                for (let bug of bugs) {
  472.                    if (!bug.active) continue;
  473.                    const dist = Math.hypot(bug.x - this.x, bug.y - this.y);
  474.                    if (dist < this.explosionRadius) {
  475.                        // Damage falls off with distance
  476.                        const damage = 50 * (1 - dist / this.explosionRadius);
  477.                        bug.takeDamage(damage);
  478.                    }
  479.                }
  480.  
  481.                // Create explosion effect
  482.                game.effects.push({
  483.                    type: 'explosion',
  484.                    x: this.x,
  485.                    y: this.y,
  486.                    radius: this.explosionRadius,
  487.                    lifetime: 30
  488.                });
  489.  
  490.                // Deactivate after explosion
  491.                setTimeout(() => {
  492.                     this.active = false;
  493.                 }, 500);
  494.             }
  495.  
  496.             draw() {
  497.                 if (!this.active) return;
  498.  
  499.                 ctx.save();
  500.  
  501.                 if (this.exploding) {
  502.                     // Draw explosion
  503.                     ctx.globalAlpha = 0.8;
  504.                     const gradient = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.explosionRadius);
  505.                     gradient.addColorStop(0, '#ffffff');
  506.                     gradient.addColorStop(0.3, '#00ffcc');
  507.                     gradient.addColorStop(0.6, '#0099ff');
  508.                     gradient.addColorStop(1, 'transparent');
  509.                     ctx.fillStyle = gradient;
  510.                     ctx.fillRect(this.x - this.explosionRadius, this.y - this.explosionRadius,
  511.                                 this.explosionRadius * 2, this.explosionRadius * 2);
  512.                 } else {
  513.                     // Highlight if being dragged
  514.                     if (draggedObject === this) {
  515.                         ctx.shadowBlur = 30;
  516.                         ctx.shadowColor = '#00ffff';
  517.                     } else {
  518.                         ctx.shadowBlur = 20;
  519.                         ctx.shadowColor = this.armed ? '#00ffcc' : '#ffaa00';
  520.                     }
  521.  
  522.                     // Draw trigger range when hovering or dragging
  523.                     if (draggedObject === this || this.armed) {
  524.                         ctx.globalAlpha = 0.1;
  525.                         ctx.beginPath();
  526.                         ctx.arc(this.x, this.y, 40, 0, Math.PI * 2);
  527.                         ctx.strokeStyle = '#ffaa00';
  528.                         ctx.stroke();
  529.                        
  530.                         // Draw explosion range
  531.                         ctx.globalAlpha = 0.05;
  532.                         ctx.beginPath();
  533.                         ctx.arc(this.x, this.y, this.explosionRadius, 0, Math.PI * 2);
  534.                         ctx.strokeStyle = '#00ffcc';
  535.                         ctx.stroke();
  536.                     }
  537.  
  538.                     ctx.globalAlpha = 1;
  539.                     ctx.fillStyle = this.armed ? '#00ffcc' : '#ffaa00';
  540.                     ctx.strokeStyle = this.armed ? '#00ffcc' : '#ffaa00';
  541.                     ctx.lineWidth = 2;
  542.  
  543.                     // Bomb body (cylindrical shape)
  544.                     ctx.beginPath();
  545.                     ctx.ellipse(this.x, this.y, 20, 15, 0, 0, Math.PI * 2);
  546.                     ctx.stroke();
  547.                     ctx.globalAlpha = 0.3;
  548.                     ctx.fill();
  549.                    
  550.                     // Top details
  551.                     ctx.globalAlpha = 1;
  552.                     ctx.beginPath();
  553.                     ctx.arc(this.x, this.y - 5, 8, 0, Math.PI * 2);
  554.                     ctx.stroke();
  555.                    
  556.                     // Blinking light when armed
  557.                     if (this.armed) {
  558.                         const blink = Math.sin(this.pulsePhase) * 0.5 + 0.5;
  559.                         ctx.fillStyle = `rgba(255, 0, 102, ${blink})`;
  560.                         ctx.beginPath();
  561.                         ctx.arc(this.x, this.y - 5, 4, 0, Math.PI * 2);
  562.                         ctx.fill();
  563.                     } else {
  564.                         // Show arming progress
  565.                         ctx.strokeStyle = '#ffaa00';
  566.                         ctx.lineWidth = 3;
  567.                         ctx.beginPath();
  568.                         ctx.arc(this.x, this.y, 25, -Math.PI/2, -Math.PI/2 + (Math.PI * 2 * (1 - this.armTimer / 60)), false);
  569.                         ctx.stroke();
  570.                     }
  571.  
  572.                     // Warning text if not armed
  573.                     if (!this.armed) {
  574.                         ctx.font = '10px Courier New';
  575.                         ctx.fillStyle = '#ffaa00';
  576.                         ctx.textAlign = 'center';
  577.                         ctx.fillText('ARMING', this.x, this.y + 30);
  578.                     }
  579.                 }
  580.  
  581.                 ctx.restore();
  582.             }
  583.         }
  584.  
  585.         class Bug {
  586.             constructor(x, y, type = null) {
  587.                 this.x = x;
  588.                 this.y = y;
  589.                 this.type = type || this.selectType();
  590.                 this.setupStats();
  591.                 this.active = true;
  592.                 this.glitchOffset = Math.random() * Math.PI * 2;
  593.                 this.movePattern = 0;
  594.                 this.shieldActive = false;
  595.                 this.splitOnDeath = false;
  596.                 this.zigzagPhase = Math.random() * Math.PI * 2;
  597.             }
  598.  
  599.             selectType() {
  600.                 const wave = game ? game.wave : 1;
  601.                 const rand = Math.random();
  602.                
  603.                 // More enemy types appear in later waves
  604.                 if (wave >= 5 && rand < 0.1) return 'boss';
  605.                 if (wave >= 4 && rand < 0.15) return 'splitter';
  606.                 if (wave >= 3 && rand < 0.2) return 'shield';
  607.                 if (wave >= 2 && rand < 0.25) return 'speeder';
  608.                 if (rand < 0.3) return 'glitch';
  609.                if (rand < 0.4) return 'zigzag';
  610.                return 'bug';
  611.            }
  612.  
  613.            setupStats() {
  614.                const stats = {
  615.                    bug: { health: 20, speed: 1.5, size: 8, power: 3, color: '#ff0066' },
  616.                    glitch: { health: 15, speed: 1.8, size: 8, power: 4, color: '#ff00ff' },
  617.                    zigzag: { health: 25, speed: 2, size: 7, power: 4, color: '#ffaa00' },
  618.                    speeder: { health: 10, speed: 4, size: 5, power: 5, color: '#00ffff' },
  619.                    shield: { health: 40, speed: 1, size: 12, power: 7, color: '#6666ff' },
  620.                    splitter: { health: 30, speed: 1.5, size: 10, power: 8, color: '#00ff00' },
  621.                    boss: { health: 100, speed: 0.8, size: 20, power: 15, color: '#ff0000' }
  622.                };
  623.                
  624.                const s = stats[this.type] || stats.bug;
  625.                this.health = s.health;
  626.                this.maxHealth = s.health;
  627.                this.speed = s.speed;
  628.                this.size = s.size;
  629.                this.powerReward = s.power;
  630.                this.color = s.color;
  631.                
  632.                // Special properties
  633.                if (this.type === 'shield') {
  634.                    this.shieldActive = true;
  635.                    this.shieldHealth = 20;
  636.                }
  637.                if (this.type === 'splitter') {
  638.                    this.splitOnDeath = true;
  639.                }
  640.                
  641.                this.vx = 0;
  642.                this.vy = this.speed;
  643.            }
  644.  
  645.            update() {
  646.                if (!this.active) return;
  647.  
  648.                // Move towards citadel (bottom center)
  649.                const targetX = canvas.width / 2;
  650.                const targetY = canvas.height - 100;
  651.                
  652.                const angle = Math.atan2(targetY - this.y, targetX - this.x);
  653.                
  654.                // Different movement patterns for different types
  655.                switch(this.type) {
  656.                    case 'glitch':
  657.                        this.x += Math.cos(angle) * this.speed + Math.sin(Date.now() * 0.01 + this.glitchOffset) * 2;
  658.                        this.y += Math.sin(angle) * this.speed;
  659.                        break;
  660.                    
  661.                    case 'zigzag':
  662.                        this.zigzagPhase += 0.15;
  663.                        this.x += Math.cos(angle) * this.speed + Math.sin(this.zigzagPhase) * 3;
  664.                        this.y += Math.sin(angle) * this.speed;
  665.                        break;
  666.                    
  667.                    case 'speeder':
  668.                        // Burst movement
  669.                        if (Math.random() < 0.05) {
  670.                            this.vx = Math.cos(angle) * this.speed * 2;
  671.                            this.vy = Math.sin(angle) * this.speed * 2;
  672.                        }
  673.                        this.x += this.vx;
  674.                        this.y += this.vy;
  675.                        this.vx *= 0.95;
  676.                        this.vy *= 0.95;
  677.                        break;
  678.                    
  679.                    case 'boss':
  680.                        // Steady, menacing approach
  681.                        this.x += Math.cos(angle) * this.speed;
  682.                        this.y += Math.sin(angle) * this.speed;
  683.                        // Spawn minions occasionally
  684.                        if (Math.random() < 0.01 && game) {
  685.                            game.bugs.push(new Bug(
  686.                                this.x + Math.random() * 40 - 20,
  687.                                this.y + Math.random() * 40 - 20,
  688.                                'bug'
  689.                            ));
  690.                        }
  691.                        break;
  692.                    
  693.                    default:
  694.                        this.x += Math.cos(angle) * this.speed;
  695.                        this.y += Math.sin(angle) * this.speed;
  696.                }
  697.  
  698.                // Check if reached citadel
  699.                if (this.y > canvas.height - 150) {
  700.                     this.active = false;
  701.                     if (game) {
  702.                         game.power -= this.type === 'boss' ? 25 : 10;
  703.                        
  704.                         // Corrupt nearby gates
  705.                         game.gates.forEach(gate => {
  706.                             const dist = Math.hypot(gate.x - this.x, gate.y - this.y);
  707.                             if (dist < 100) {
  708.                                gate.corrupted = true;
  709.                            }
  710.                        });
  711.                    }
  712.                }
  713.            }
  714.  
  715.            takeDamage(amount) {
  716.                // Shield absorbs damage first
  717.                if (this.shieldActive && this.shieldHealth > 0) {
  718.                     this.shieldHealth -= amount;
  719.                     if (this.shieldHealth <= 0) {
  720.                        this.shieldActive = false;
  721.                    }
  722.                    return;
  723.                }
  724.  
  725.                this.health -= amount;
  726.                if (this.health <= 0 && this.active) {
  727.                    this.active = false;
  728.                    
  729.                    if (game) {
  730.                        // Award power and score based on bug type
  731.                        game.score += this.powerReward * 2;
  732.                        game.power += this.powerReward;
  733.                        
  734.                        // Splitter creates smaller bugs
  735.                        if (this.splitOnDeath) {
  736.                            for (let i = 0; i < 2; i++) {
  737.                                const miniGlitch = new Bug(
  738.                                    this.x + Math.random() * 20 - 10,
  739.                                    this.y + Math.random() * 20 - 10,
  740.                                    'glitch'
  741.                                );
  742.                                miniGlitch.health = 10;
  743.                                miniGlitch.maxHealth = 10;
  744.                                miniGlitch.size = 5;
  745.                                game.bugs.push(miniGlitch);
  746.                            }
  747.                        }
  748.                        
  749.                        // Death effect
  750.                        this.createDeathEffect();
  751.                    }
  752.                }
  753.            }
  754.  
  755.            createDeathEffect() {
  756.                if (!game) return;
  757.                for (let i = 0; i < 5; i++) {
  758.                    game.effects.push({
  759.                        type: 'particle',
  760.                        x: this.x,
  761.                        y: this.y,
  762.                        vx: Math.random() * 6 - 3,
  763.                        vy: Math.random() * -6,
  764.                        lifetime: 20,
  765.                        color: this.color
  766.                    });
  767.                }
  768.            }
  769.  
  770.            draw() {
  771.                if (!this.active) return;
  772.  
  773.                ctx.save();
  774.                
  775.                // Draw different shapes for different enemy types
  776.                ctx.fillStyle = this.color;
  777.                ctx.strokeStyle = this.color;
  778.                ctx.shadowBlur = 10;
  779.                ctx.shadowColor = this.color;
  780.  
  781.                switch(this.type) {
  782.                    case 'glitch':
  783.                        // Glitchy squares
  784.                        ctx.globalAlpha = 0.8;
  785.                        for (let i = 0; i < 3; i++) {
  786.                            ctx.fillRect(
  787.                                this.x - this.size + Math.random() * 4,
  788.                                this.y - this.size + Math.random() * 4,
  789.                                this.size * 2, this.size * 2
  790.                            );
  791.                        }
  792.                        break;
  793.                    
  794.                    case 'zigzag':
  795.                        // Triangle
  796.                        ctx.beginPath();
  797.                        ctx.moveTo(this.x, this.y - this.size);
  798.                        ctx.lineTo(this.x - this.size, this.y + this.size);
  799.                        ctx.lineTo(this.x + this.size, this.y + this.size);
  800.                        ctx.closePath();
  801.                        ctx.fill();
  802.                        ctx.stroke();
  803.                        break;
  804.                    
  805.                    case 'speeder':
  806.                        // Diamond with trail
  807.                        ctx.globalAlpha = 0.3;
  808.                        ctx.beginPath();
  809.                        ctx.moveTo(this.x, this.y - this.size * 2);
  810.                        ctx.lineTo(this.x - this.size/2, this.y);
  811.                        ctx.lineTo(this.x, this.y + this.size);
  812.                        ctx.lineTo(this.x + this.size/2, this.y);
  813.                        ctx.closePath();
  814.                        ctx.fill();
  815.                        
  816.                        ctx.globalAlpha = 1;
  817.                        ctx.beginPath();
  818.                        ctx.moveTo(this.x, this.y - this.size);
  819.                        ctx.lineTo(this.x - this.size, this.y);
  820.                        ctx.lineTo(this.x, this.y + this.size);
  821.                        ctx.lineTo(this.x + this.size, this.y);
  822.                        ctx.closePath();
  823.                        ctx.fill();
  824.                        break;
  825.                    
  826.                    case 'shield':
  827.                        // Shield bubble
  828.                        if (this.shieldActive) {
  829.                            ctx.globalAlpha = 0.3;
  830.                            ctx.beginPath();
  831.                            ctx.arc(this.x, this.y, this.size + 8, 0, Math.PI * 2);
  832.                            ctx.fill();
  833.                        }
  834.                        ctx.globalAlpha = 1;
  835.                        ctx.beginPath();
  836.                        ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
  837.                        ctx.fill();
  838.                        ctx.stroke();
  839.                        break;
  840.                    
  841.                    case 'splitter':
  842.                        // Hexagon
  843.                        ctx.beginPath();
  844.                        for (let i = 0; i < 6; i++) {
  845.                            const angle = (Math.PI / 3) * i;
  846.                            const x = this.x + this.size * Math.cos(angle);
  847.                            const y = this.y + this.size * Math.sin(angle);
  848.                            if (i === 0) ctx.moveTo(x, y);
  849.                            else ctx.lineTo(x, y);
  850.                        }
  851.                        ctx.closePath();
  852.                        ctx.fill();
  853.                        ctx.stroke();
  854.                        break;
  855.                    
  856.                    case 'boss':
  857.                        // Large intimidating circle with spikes
  858.                        ctx.globalAlpha = 0.5;
  859.                        ctx.beginPath();
  860.                        ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
  861.                        ctx.fill();
  862.                        
  863.                        ctx.globalAlpha = 1;
  864.                        for (let i = 0; i < 8; i++) {
  865.                            const angle = (Math.PI / 4) * i + Date.now() * 0.001;
  866.                            ctx.beginPath();
  867.                            ctx.moveTo(this.x, this.y);
  868.                            ctx.lineTo(
  869.                                this.x + (this.size + 10) * Math.cos(angle),
  870.                                this.y + (this.size + 10) * Math.sin(angle)
  871.                            );
  872.                            ctx.stroke();
  873.                        }
  874.                        ctx.beginPath();
  875.                        ctx.arc(this.x, this.y, this.size * 0.7, 0, Math.PI * 2);
  876.                        ctx.fill();
  877.                        break;
  878.                    
  879.                    default:
  880.                        // Regular bug - circle
  881.                        ctx.beginPath();
  882.                        ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
  883.                        ctx.fill();
  884.                        ctx.stroke();
  885.                }
  886.  
  887.                // Health bar
  888.                if (this.health < this.maxHealth) {
  889.                    ctx.globalAlpha = 1;
  890.                    ctx.fillStyle = '#330000';
  891.                    ctx.fillRect(this.x - this.size - 5, this.y - this.size - 10, (this.size + 5) * 2, 3);
  892.                    ctx.fillStyle = '#00ff66';
  893.                    ctx.fillRect(this.x - this.size - 5, this.y - this.size - 10, (this.size + 5) * 2 * (this.health / this.maxHealth), 3);
  894.                }
  895.  
  896.                ctx.restore();
  897.            }
  898.        }
  899.  
  900.        class Game {
  901.            constructor() {
  902.                this.power = 100;
  903.                this.wave = 1;
  904.                this.score = 0;
  905.                this.gates = [];
  906.                this.towers = [];
  907.                this.bugs = [];
  908.                this.particles = [];
  909.                this.effects = [];
  910.                this.debugModeActive = false;
  911.                this.hoveredGate = null;
  912.                this.citadelHealth = 100;
  913.                this.waveTimer = 0;
  914.                this.gameRunning = true;
  915.                
  916.                this.init();
  917.            }
  918.  
  919.            init() {
  920.                // Create initial code cascade
  921.                setInterval(() => {
  922.                     if (this.particles.length < 50) {
  923.                        this.particles.push(new CodeParticle(
  924.                            Math.random() * canvas.width,
  925.                            -20
  926.                        ));
  927.                    }
  928.                }, 100);
  929.  
  930.                // Start game loop
  931.                this.gameLoop();
  932.                
  933.                // Start wave spawning
  934.                this.spawnWave();
  935.            }
  936.  
  937.            spawnWave() {
  938.                if (!this.gameRunning) return;
  939.  
  940.                const bugCount = Math.min(5 + this.wave * 2, 20); // Cap at 20 enemies per wave
  941.                for (let i = 0; i < bugCount; i++) {
  942.                    setTimeout(() => {
  943.                         if (!this.gameRunning) return;
  944.                         this.bugs.push(new Bug(
  945.                             Math.random() * canvas.width,
  946.                             Math.random() * -200 - 50
  947.                         ));
  948.                     }, i * 300); // Faster spawning
  949.                 }
  950.  
  951.                 // Schedule next wave
  952.                 setTimeout(() => {
  953.                     this.wave++;
  954.                     document.getElementById('wave').textContent = this.wave;
  955.                     this.spawnWave();
  956.                 }, 12000 + Math.min(this.wave * 500, 5000)); // Shorter waves, caps at 17 seconds
  957.             }
  958.  
  959.             buildGate(type) {
  960.                 const costs = { AND: 10, OR: 15, NOT: 8, XOR: 20 };
  961.                 const cost = costs[type];
  962.                
  963.                 if (this.power < cost) {
  964.                    this.showTooltip('Insufficient power!', canvas.width / 2, canvas.height / 2);
  965.                    return;
  966.                }
  967.                
  968.                // Prevent spending if it would cause game over
  969.                if (this.power - cost <= 0) {
  970.                    this.showTooltip('Cannot spend - would lose the game!', canvas.width / 2, canvas.height / 2);
  971.                    return;
  972.                }
  973.  
  974.                this.power -= cost;
  975.                const x = Math.random() * (canvas.width - 100) + 50;
  976.                const y = Math.random() * (canvas.height - 300) + 150;
  977.                this.gates.push(new LogicGate(x, y, type));
  978.            }
  979.  
  980.            buildBombTower() {
  981.                const cost = 5;
  982.                
  983.                if (this.power < cost) {
  984.                    this.showTooltip('Insufficient power!', canvas.width / 2, canvas.height / 2);
  985.                    return;
  986.                }
  987.                
  988.                // Prevent spending if it would cause game over
  989.                if (this.power - cost <= 0) {
  990.                    this.showTooltip('Cannot spend - would lose the game!', canvas.width / 2, canvas.height / 2);
  991.                    return;
  992.                }
  993.  
  994.                this.power -= cost;
  995.                const x = Math.random() * (canvas.width - 100) + 50;
  996.                const y = Math.random() * (canvas.height - 300) + 150;
  997.                this.towers.push(new BombTower(x, y));
  998.            }
  999.  
  1000.            showTooltip(text, x, y) {
  1001.                const tooltip = document.getElementById('tooltip');
  1002.                tooltip.textContent = text;
  1003.                tooltip.style.left = x + 'px';
  1004.                tooltip.style.top = y + 'px';
  1005.                tooltip.style.display = 'block';
  1006.                
  1007.                setTimeout(() => {
  1008.                     tooltip.style.display = 'none';
  1009.                 }, 2000);
  1010.             }
  1011.  
  1012.             update() {
  1013.                 if (!this.gameRunning) return;
  1014.  
  1015.                 // Update particles
  1016.                 this.particles = this.particles.filter(p => {
  1017.                     p.update();
  1018.                     return p.opacity > 0 && p.y < canvas.height;
  1019.                 });
  1020.  
  1021.                 // Update gates
  1022.                 this.gates = this.gates.filter(gate => {
  1023.                     gate.update(this.bugs);
  1024.                     return gate.active;
  1025.                 });
  1026.  
  1027.                 // Update towers
  1028.                 this.towers = this.towers.filter(tower => {
  1029.                     tower.update(this.bugs);
  1030.                     return tower.active;
  1031.                 });
  1032.  
  1033.                 // Update bugs
  1034.                 this.bugs = this.bugs.filter(bug => {
  1035.                     bug.update();
  1036.                     return bug.active;
  1037.                 });
  1038.  
  1039.                 // Update effects
  1040.                 this.effects = this.effects.filter(effect => {
  1041.                     effect.lifetime--;
  1042.                     return effect.lifetime > 0;
  1043.                 });
  1044.  
  1045.                 // Update UI
  1046.                 document.getElementById('power').textContent = Math.floor(this.power);
  1047.                 document.getElementById('bugs').textContent = this.bugs.filter(b => b.active).length;
  1048.                 document.getElementById('score').textContent = this.score;
  1049.  
  1050.                 // Check game over
  1051.                 if (this.power <= 0) {
  1052.                    this.gameOver();
  1053.                }
  1054.            }
  1055.  
  1056.            draw() {
  1057.                ctx.clearRect(0, 0, canvas.width, canvas.height);
  1058.  
  1059.                // Draw grid
  1060.                ctx.strokeStyle = 'rgba(0,255,204,0.1)';
  1061.                ctx.lineWidth = 0.5;
  1062.                for (let x = 0; x < canvas.width; x += 50) {
  1063.                    ctx.beginPath();
  1064.                    ctx.moveTo(x, 0);
  1065.                    ctx.lineTo(x, canvas.height);
  1066.                    ctx.stroke();
  1067.                }
  1068.                for (let y = 0; y < canvas.height; y += 50) {
  1069.                    ctx.beginPath();
  1070.                    ctx.moveTo(0, y);
  1071.                    ctx.lineTo(canvas.width, y);
  1072.                    ctx.stroke();
  1073.                }
  1074.  
  1075.                // Draw citadel base
  1076.                ctx.save();
  1077.                ctx.fillStyle = '#00ffcc';
  1078.                ctx.strokeStyle = '#00ffcc';
  1079.                ctx.lineWidth = 3;
  1080.                ctx.shadowBlur = 30;
  1081.                ctx.shadowColor = '#00ffcc';
  1082.                
  1083.                const citadelX = canvas.width / 2;
  1084.                const citadelY = canvas.height - 50;
  1085.                
  1086.                ctx.beginPath();
  1087.                ctx.moveTo(citadelX - 100, citadelY);
  1088.                ctx.lineTo(citadelX - 80, citadelY - 50);
  1089.                ctx.lineTo(citadelX - 40, citadelY - 40);
  1090.                ctx.lineTo(citadelX, citadelY - 60);
  1091.                ctx.lineTo(citadelX + 40, citadelY - 40);
  1092.                ctx.lineTo(citadelX + 80, citadelY - 50);
  1093.                ctx.lineTo(citadelX + 100, citadelY);
  1094.                ctx.closePath();
  1095.                ctx.stroke();
  1096.                ctx.globalAlpha = 0.2;
  1097.                ctx.fill();
  1098.                ctx.restore();
  1099.  
  1100.                // Draw particles
  1101.                this.particles.forEach(p => p.draw());
  1102.  
  1103.                 // Draw towers
  1104.                 this.towers.forEach(tower => tower.draw());
  1105.  
  1106.                 // Draw gates
  1107.                 this.gates.forEach(gate => gate.draw());
  1108.  
  1109.                 // Draw bugs
  1110.                 this.bugs.forEach(bug => bug.draw());
  1111.  
  1112.                 // Draw effects
  1113.                 this.effects.forEach(effect => {
  1114.                     if (effect.type === 'beam') {
  1115.                         ctx.save();
  1116.                         ctx.strokeStyle = '#00ffcc';
  1117.                         ctx.lineWidth = 2;
  1118.                         ctx.globalAlpha = effect.lifetime / 10;
  1119.                         ctx.shadowBlur = 10;
  1120.                         ctx.shadowColor = '#00ffcc';
  1121.                         ctx.beginPath();
  1122.                         ctx.moveTo(effect.x1, effect.y1);
  1123.                         ctx.lineTo(effect.x2, effect.y2);
  1124.                         ctx.stroke();
  1125.                         ctx.restore();
  1126.                     } else if (effect.type === 'explosion') {
  1127.                         ctx.save();
  1128.                         ctx.globalAlpha = effect.lifetime / 30;
  1129.                         const gradient = ctx.createRadialGradient(effect.x, effect.y, 0, effect.x, effect.y, effect.radius);
  1130.                         gradient.addColorStop(0, '#ffffff');
  1131.                         gradient.addColorStop(0.2, '#00ffcc');
  1132.                         gradient.addColorStop(0.5, '#0099ff');
  1133.                         gradient.addColorStop(1, 'transparent');
  1134.                         ctx.fillStyle = gradient;
  1135.                         ctx.beginPath();
  1136.                         ctx.arc(effect.x, effect.y, effect.radius * (1 + (30 - effect.lifetime) / 30), 0, Math.PI * 2);
  1137.                         ctx.fill();
  1138.                         ctx.restore();
  1139.                     } else if (effect.type === 'particle') {
  1140.                         ctx.save();
  1141.                         effect.x += effect.vx;
  1142.                         effect.y += effect.vy;
  1143.                         effect.vy += 0.3; // Gravity
  1144.                         ctx.globalAlpha = effect.lifetime / 30;
  1145.                         ctx.fillStyle = effect.color;
  1146.                         ctx.shadowBlur = 5;
  1147.                         ctx.shadowColor = effect.color;
  1148.                         ctx.fillRect(effect.x - 2, effect.y - 2, 4, 4);
  1149.                         ctx.restore();
  1150.                     }
  1151.                 });
  1152.             }
  1153.  
  1154.             gameLoop() {
  1155.                 this.update();
  1156.                 this.draw();
  1157.                
  1158.                 if (this.gameRunning) {
  1159.                     requestAnimationFrame(() => this.gameLoop());
  1160.                 }
  1161.             }
  1162.  
  1163.             gameOver() {
  1164.                 this.gameRunning = false;
  1165.                 document.getElementById('finalScore').textContent = this.score;
  1166.                 document.getElementById('finalWave').textContent = this.wave - 1;
  1167.                 document.getElementById('gameOver').style.display = 'block';
  1168.             }
  1169.         }
  1170.  
  1171.         // Mouse interaction variables
  1172.         let isDragging = false;
  1173.         let draggedObject = null;
  1174.         let dragOffset = { x: 0, y: 0 };
  1175.  
  1176.         // Mouse down - start dragging
  1177.         canvas.addEventListener('mousedown', (e) => {
  1178.             if (!game) return;
  1179.            
  1180.             const mouseX = e.clientX;
  1181.             const mouseY = e.clientY;
  1182.            
  1183.             // Check if clicking on a gate
  1184.             for (let gate of game.gates) {
  1185.                 const dist = Math.hypot(mouseX - gate.x, mouseY - gate.y);
  1186.                 if (dist < 30) {
  1187.                    isDragging = true;
  1188.                    draggedObject = gate;
  1189.                    dragOffset.x = mouseX - gate.x;
  1190.                    dragOffset.y = mouseY - gate.y;
  1191.                    canvas.style.cursor = 'grabbing';
  1192.                    return;
  1193.                }
  1194.            }
  1195.            
  1196.            // Check if clicking on a tower
  1197.            for (let tower of game.towers) {
  1198.                const dist = Math.hypot(mouseX - tower.x, mouseY - tower.y);
  1199.                if (dist < 30) {
  1200.                    isDragging = true;
  1201.                    draggedObject = tower;
  1202.                    dragOffset.x = mouseX - tower.x;
  1203.                    dragOffset.y = mouseY - tower.y;
  1204.                    canvas.style.cursor = 'grabbing';
  1205.                    return;
  1206.                }
  1207.            }
  1208.        });
  1209.  
  1210.        // Mouse move - drag or hover
  1211.        canvas.addEventListener('mousemove', (e) => {
  1212.             if (!game) return;
  1213.            
  1214.             const mouseX = e.clientX;
  1215.             const mouseY = e.clientY;
  1216.            
  1217.             if (isDragging && draggedObject) {
  1218.                // Update position of dragged object
  1219.                draggedObject.x = mouseX - dragOffset.x;
  1220.                 draggedObject.y = mouseY - dragOffset.y;
  1221.                
  1222.                 // Keep objects within canvas bounds
  1223.                 draggedObject.x = Math.max(30, Math.min(canvas.width - 30, draggedObject.x));
  1224.                 draggedObject.y = Math.max(30, Math.min(canvas.height - 100, draggedObject.y));
  1225.             } else {
  1226.                 // Check for hovering over draggable objects
  1227.                 let hoveringObject = false;
  1228.                
  1229.                 // Check gates
  1230.                 game.hoveredGate = null;
  1231.                 for (let gate of game.gates) {
  1232.                     const dist = Math.hypot(mouseX - gate.x, mouseY - gate.y);
  1233.                     if (dist < 30) {
  1234.                        game.hoveredGate = gate;
  1235.                        hoveringObject = true;
  1236.                        break;
  1237.                    }
  1238.                }
  1239.                
  1240.                // Check towers
  1241.                if (!hoveringObject) {
  1242.                    for (let tower of game.towers) {
  1243.                        const dist = Math.hypot(mouseX - tower.x, mouseY - tower.y);
  1244.                        if (dist < 30) {
  1245.                            hoveringObject = true;
  1246.                            break;
  1247.                        }
  1248.                    }
  1249.                }
  1250.                
  1251.                // Update cursor
  1252.                canvas.style.cursor = hoveringObject ? 'grab' : 'default';
  1253.            }
  1254.        });
  1255.  
  1256.        // Mouse up - stop dragging
  1257.        canvas.addEventListener('mouseup', (e) => {
  1258.             if (isDragging) {
  1259.                 isDragging = false;
  1260.                 draggedObject = null;
  1261.                 canvas.style.cursor = 'default';
  1262.             }
  1263.         });
  1264.  
  1265.         // Mouse leave - cancel dragging
  1266.         canvas.addEventListener('mouseleave', (e) => {
  1267.             if (isDragging) {
  1268.                 isDragging = false;
  1269.                 draggedObject = null;
  1270.                 canvas.style.cursor = 'default';
  1271.             }
  1272.         });
  1273.  
  1274.         // Start game
  1275.         const game = new Game();
  1276.  
  1277.         // Handle window resize
  1278.         window.addEventListener('resize', () => {
  1279.             canvas.width = window.innerWidth;
  1280.             canvas.height = window.innerHeight;
  1281.         });
  1282.     </script>
  1283. </body>
  1284. </html>
  1285.  
Advertisement
Add Comment
Please, Sign In to add comment