🚀 gpt-4.1-mini

LiteChat Race Result

```runjs
// Clear previous content
litechat.target.replaceChildren();

(async () => {
  // Load three.js and OrbitControls for 3D rendering and interaction
  try {
    const modules = await litechat.utils.loadModules([
      {
        url: 'https://unpkg.com/three@0.170.0/build/three.module.js',
        name: 'THREE',
        globalKey: 'THREE',
        importMap: {
          "three": "https://unpkg.com/three@0.170.0/build/three.module.js",
          "three/addons/": "https://unpkg.com/three@0.170.0/examples/jsm/"
        }
      },
      {
        url: 'https://unpkg.com/three@0.170.0/examples/jsm/controls/OrbitControls.js',
        name: 'OrbitControls',
        globalKey: 'OrbitControls',
        dependencies: ['THREE']
      }
    ]);
    const { THREE, OrbitControls } = modules;

    // Setup container & canvas
    const container = document.createElement('div');
    container.className = 'relative mx-auto mt-6 max-w-4xl bg-gradient-to-br from-purple-600 via-pink-500 to-red-400 rounded-lg shadow-lg p-4 flex flex-col items-center';

    const hud = document.createElement('div');
    hud.className = 'w-full flex justify-between text-white text-lg font-semibold mb-3 select-none';
    container.appendChild(hud);

    const livesDisplay = document.createElement('div');
    livesDisplay.textContent = 'Lives: 3';
    hud.appendChild(livesDisplay);

    const scoreDisplay = document.createElement('div');
    scoreDisplay.textContent = 'Score: 0';
    hud.appendChild(scoreDisplay);

    const bonusesDisplay = document.createElement('div');
    bonusesDisplay.className = 'text-sm text-yellow-100';
    container.appendChild(bonusesDisplay);

    const canvas = document.createElement('canvas');
    canvas.width = 800;
    canvas.height = 600;
    canvas.className = 'rounded-lg shadow-lg border-4 border-white border-opacity-30 bg-black';
    container.appendChild(canvas);

    litechat.target.appendChild(container);

    // Renderer setup
    const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: false });
    renderer.setSize(canvas.width, canvas.height);
    renderer.setClearColor(new THREE.Color(0x1a1a2e), 1);

    // Scene and Camera
    const scene = new THREE.Scene();

    // Orthographic camera for 2D style but using 3D space (comfort + 3D effect)
    const aspect = canvas.width / canvas.height;
    const cameraSize = 12;
    const camera = new THREE.OrthographicCamera(
      -cameraSize * aspect,
      cameraSize * aspect,
      cameraSize,
      -cameraSize,
      0.1,
      1000
    );
    camera.position.set(0, 15, 15);
    camera.lookAt(0, 0, 0);

    // Add subtle ambient light and directional light for poppy 3D shading
    const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
    scene.add(ambientLight);

    const directionalLight = new THREE.DirectionalLight(0xffffff, 0.7);
    directionalLight.position.set(5, 10, 7);
    scene.add(directionalLight);

    // Create a comfy background plane with gradient and subtle grid pattern
    const bgTexture = new THREE.CanvasTexture(() => {
      const size = 256;
      const canvasBg = document.createElement('canvas');
      canvasBg.width = size;
      canvasBg.height = size;
      const ctx = canvasBg.getContext('2d');

      // Create gradient background
      const gradient = ctx.createLinearGradient(0, 0, 0, size);
      gradient.addColorStop(0, '#6b21a8'); // purple
      gradient.addColorStop(1, '#ec4899'); // pink
      ctx.fillStyle = gradient;
      ctx.fillRect(0, 0, size, size);

      // Draw grid lines
      ctx.strokeStyle = 'rgba(255,255,255,0.05)';
      ctx.lineWidth = 2;
      for (let i = 0; i < size; i += 32) {
        ctx.beginPath();
        ctx.moveTo(i, 0);
        ctx.lineTo(i, size);
        ctx.stroke();
        ctx.beginPath();
        ctx.moveTo(0, i);
        ctx.lineTo(size, i);
        ctx.stroke();
      }
      return canvasBg;
    }());

    const bgGeometry = new THREE.PlaneGeometry(cameraSize * aspect * 2, cameraSize * 2);
    const bgMaterial = new THREE.MeshBasicMaterial({ map: bgTexture, depthWrite: false });
    const bgPlane = new THREE.Mesh(bgGeometry, bgMaterial);
    bgPlane.position.set(0, 0, -10);
    scene.add(bgPlane);

    // Game parameters & state
    let lives = 3;
    let score = 0;
    let fireRateBonus = 0; // +10% each bonus
    let bouncyBonus = 0; // number of bounces allowed for bullets
    let gunCount = 1; // 1 to 3
    let extraLivesBonus = 0;

    let enemySpeedMultiplier = 1;
    let enemyHealthMultiplier = 1;

    // Player setup - a colorful "ship" made with triangles
    const playerGroup = new THREE.Group();

    function createPlayerMesh() {
      const playerMat = new THREE.MeshLambertMaterial({ color: 0xffff77, emissive: 0xffdd33 });
      const geom = new THREE.ConeGeometry(1.5, 3, 3);
      const mesh = new THREE.Mesh(geom, playerMat);
      mesh.rotation.x = Math.PI; // point forward (negative z)
      return mesh;
    }
    const playerMesh = createPlayerMesh();
    playerGroup.add(playerMesh);
    playerGroup.position.set(0, 0, 0);
    scene.add(playerGroup);

    // Player movement variables
    const playerSpeed = 0.4;
    const keys = {};
    window.addEventListener('keydown', (e) => {
      keys[e.key.toLowerCase()] = true;
    });
    window.addEventListener('keyup', (e) => {
      keys[e.key.toLowerCase()] = false;
    });

    // Bullet class
    class Bullet {
      constructor(position, direction, speed, bounceCount) {
        this.speed = speed;
        this.direction = direction.clone().normalize();
        this.bounceCount = bounceCount;

        const geom = new THREE.CylinderGeometry(0.15, 0.15, 1, 8);
        const mat = new THREE.MeshLambertMaterial({ color: 0x00ffff, emissive: 0x00ffff });
        this.mesh = new THREE.Mesh(geom, mat);
        this.mesh.rotation.x = Math.PI / 2;
        this.mesh.position.copy(position);
        this.alive = true;
      }
      update() {
        this.mesh.position.addScaledVector(this.direction, this.speed);
        // Bounce if hit horizontal bounds
        if (this.mesh.position.x < -cameraSize * aspect + 1 && this.direction.x < 0) {
          if (this.bounceCount > 0) {
            this.direction.x = -this.direction.x;
            this.bounceCount--;
            // brighten color on bounce
            this.mesh.material.color.setHSL(Math.random(), 1, 0.5);
            this.mesh.material.emissive.setHSL(Math.random(), 1, 0.5);
          } else {
            this.alive = false;
          }
        }
        if (this.mesh.position.x > cameraSize * aspect - 1 && this.direction.x > 0) {
          if (this.bounceCount > 0) {
            this.direction.x = -this.direction.x;
            this.bounceCount--;
            this.mesh.material.color.setHSL(Math.random(), 1, 0.5);
            this.mesh.material.emissive.setHSL(Math.random(), 1, 0.5);
          } else {
            this.alive = false;
          }
        }
        // Remove if out of vertical bounds (top)
        if (this.mesh.position.y > cameraSize) {
          this.alive = false;
        }
      }
    }

    // Enemy class
    class Enemy {
      constructor() {
        this.healthBase = 1;
        this.health = this.healthBase * enemyHealthMultiplier;
        this.speedBase = 0.04;
        this.speed = this.speedBase * enemySpeedMultiplier;

        const size = THREE.MathUtils.randFloat(1.5, 2.5);
        const colors = [0xff0044, 0xffbb00, 0x00ff66, 0x00aaff, 0xff44ff];
        const color = colors[Math.floor(Math.random() * colors.length)];
        const mat = new THREE.MeshLambertMaterial({ color: color, emissive: color * 0.5 });
        const geom = new THREE.IcosahedronGeometry(size, 0);
        this.mesh = new THREE.Mesh(geom, mat);

        this.mesh.position.set(
          THREE.MathUtils.randFloatSpread(cameraSize * aspect * 1.8),
          cameraSize + 3,
          0
        );
        this.alive = true;
      }
      update() {
        this.mesh.position.y -= this.speed;
        if (this.mesh.position.y < -cameraSize) {
          this.alive = false;
          loseLife();
        }
      }
      damage(amount) {
        this.health -= amount;
        if (this.health <= 0) {
          this.alive = false;
          score += 10;
          scoreDisplay.textContent = `Score: ${score}`;
          spawnBonus(this.mesh.position);
        }
      }
    }

    // Bonus class
    class Bonus {
      constructor(type, position) {
        this.type = type;
        this.mesh = new THREE.Mesh(
          new THREE.TorusGeometry(0.8, 0.3, 8, 20),
          new THREE.MeshPhongMaterial({ color: 0xffffff, emissive: 0xffffff, shininess: 100 })
        );
        this.mesh.position.copy(position);
        this.mesh.position.z = 0;
        this.speed = 0.03;
        this.alive = true;

        // Color by type
        switch (type) {
          case 'fireRate':
            this.mesh.material.color.set(0xffa500);
            this.mesh.material.emissive.set(0xffa500);
            break;
          case 'bouncyFire':
            this.mesh.material.color.set(0x00ffff);
            this.mesh.material.emissive.set(0x00ffff);
            break;
          case 'extraGun':
            this.mesh.material.color.set(0xff00ff);
            this.mesh.material.emissive.set(0xff00ff);
            break;
          case 'extraLife':
            this.mesh.material.color.set(0x00ff00);
            this.mesh.material.emissive.set(0x00ff00);
            break;
        }
      }
      update() {
        this.mesh.position.y -= this.speed;
        if (this.mesh.position.y < -cameraSize) {
          this.alive = false;
        }
      }
    }

    // Game state arrays
    const bullets = [];
    const enemies = [];
    const bonuses = [];

    // Fire control
    let canFire = true;
    const baseFireInterval = 400; // ms
    let fireInterval = baseFireInterval;
    let lastFireTime = 0;

    // Spawn enemies timer
    let enemySpawnTimer = 0;
    const enemySpawnIntervalBase = 1200; // ms
    let enemySpawnInterval = enemySpawnIntervalBase;

    // Utility helper - clamp player position inside game area
    function clampPlayerPos() {
      const limitX = cameraSize * aspect - 2;
      if (playerGroup.position.x < -limitX) playerGroup.position.x = -limitX;
      if (playerGroup.position.x > limitX) playerGroup.position.x = limitX;
    }

    // Lose life handler
    function loseLife() {
      lives--;
      livesDisplay.textContent = `Lives: ${lives}`;
      if (lives <= 0) {
        gameOver();
      }
    }

    // Game over display
    let gameEnded = false;
    function gameOver() {
      gameEnded = true;
      const gameOverDiv = document.createElement('div');
      gameOverDiv.className = 'absolute inset-0 flex flex-col items-center justify-center bg-black bg-opacity-80 text-white text-4xl font-extrabold rounded-lg select-none z-10';
      gameOverDiv.textContent = 'Game Over';
      container.appendChild(gameOverDiv);
    }

    // Spawn bonus randomly after enemy killed
    function spawnBonus(position) {
      if (Math.random() < 0.4) { // 40% chance
        const types = ['fireRate', 'bouncyFire', 'extraGun', 'extraLife'];
        const type = types[Math.floor(Math.random() * types.length)];
        const bonus = new Bonus(type, position.clone());
        bonuses.push(bonus);
        scene.add(bonus.mesh);
      }
    }

    // Collect bonus
    function collectBonus(bonus) {
      switch (bonus.type) {
        case 'fireRate':
          fireRateBonus += 0.1;
          fireInterval = baseFireInterval / (1 + fireRateBonus);
          break;
        case 'bouncyFire':
          bouncyBonus++;
          break;
        case 'extraGun':
          if (gunCount < 3) gunCount++;
          break;
        case 'extraLife':
          lives++;
          livesDisplay.textContent = `Lives: ${lives}`;
          break;
      }
      updateBonusesDisplay();
    }

    // Update bonuses HUD display text
    function updateBonusesDisplay() {
      let text = 'Bonuses: ';
      if (fireRateBonus > 0) text += `🔥Fire Rate +${Math.floor(fireRateBonus * 100)}% `;
      if (bouncyBonus > 0) text += `🌀Bouncy x${bouncyBonus} `;
      if (gunCount > 1) text += `🔫 Guns: ${gunCount} `;
      bonusesDisplay.textContent = text.trim();
    }
    updateBonusesDisplay();

    // Player fire function
    function fireBullets() {
      const now = performance.now();
      if (!canFire || now - lastFireTime < fireInterval) return;
      lastFireTime = now;

      const basePos = playerGroup.position.clone();
      const bulletSpeed = 0.7;
      const newBullets = [];

      // Fire patterns based on gunCount
      if (gunCount === 1) {
        newBullets.push(new Bullet(basePos.clone().add(new THREE.Vector3(0, 1.6, 0)), new THREE.Vector3(0, 1, 0), bulletSpeed, bouncyBonus));
      } else if (gunCount === 2) {
        newBullets.push(new Bullet(basePos.clone().add(new THREE.Vector3(-0.6, 1.6, 0)), new THREE.Vector3(0, 1, 0), bulletSpeed, bouncyBonus));
        newBullets.push(new Bullet(basePos.clone().add(new THREE.Vector3(0.6, 1.6, 0)), new THREE.Vector3(0, 1, 0), bulletSpeed, bouncyBonus));
      } else if (gunCount === 3) {
        newBullets.push(new Bullet(basePos.clone().add(new THREE.Vector3(0, 1.6, 0)), new THREE.Vector3(0, 1, 0), bulletSpeed, bouncyBonus));
        newBullets.push(new Bullet(basePos.clone().add(new THREE.Vector3(-0.8, 1.1, 0)), new THREE.Vector3(-0.3, 1, 0), bulletSpeed, bouncyBonus));
        newBullets.push(new Bullet(basePos.clone().add(new THREE.Vector3(0.8, 1.1, 0)), new THREE.Vector3(0.3, 1, 0), bulletSpeed, bouncyBonus));
      }

      newBullets.forEach(b => {
        bullets.push(b);
        scene.add(b.mesh);
      });
    }

    // Enemy speed & health increase over time
    function increaseDifficulty() {
      enemySpeedMultiplier += 0.01;
      enemyHealthMultiplier += 0.005;
      enemySpawnInterval = Math.max(400, enemySpawnIntervalBase / enemySpeedMultiplier);
    }

    // Main game loop
    function animate() {
      if (gameEnded) return;

      // Background subtle rotation for 3D effect
      bgPlane.rotation.z += 0.001;

      // Player movement (A/D or Left/Right)
      if (keys['a'] || keys['arrowleft']) playerGroup.position.x -= playerSpeed;
      if (keys['d'] || keys['arrowright']) playerGroup.position.x += playerSpeed;
      clampPlayerPos();

      // Fire bullets if space or w pressed
      if (keys[' '] || keys['w'] || keys['arrowup']) {
        fireBullets();
      }

      // Update bullets
      bullets.forEach((bullet, i) => {
        bullet.update();

        // Check collision to enemies
        enemies.forEach(enemy => {
          if (!enemy.alive) return;
          const dist = bullet.mesh.position.distanceTo(enemy.mesh.position);
          if (dist < 1.5) {
            enemy.damage(1);
            // Bounce bullet if bouncyBonus > 0 else remove bullet
            if (bullet.bounceCount > 0) {
              bullet.direction.y = -bullet.direction.y;
              bullet.bounceCount--;
              // brighten color on bounce
              bullet.mesh.material.color.setHSL(Math.random(), 1, 0.5);
              bullet.mesh.material.emissive.setHSL(Math.random(), 1, 0.5);
            } else {
              bullet.alive = false;
            }
          }
        });

        if (!bullet.alive) {
          scene.remove(bullet.mesh);
          bullets.splice(i, 1);
        }
      });

      // Update enemies
      enemies.forEach((enemy, i) => {
        enemy.update();
        if (!enemy.alive) {
          scene.remove(enemy.mesh);
          enemies.splice(i, 1);
        }
      });

      // Update bonuses
      bonuses.forEach((bonus, i) => {
        bonus.update();
        // Check player collision
        if (bonus.mesh.position.distanceTo(playerGroup.position) < 2) {
          collectBonus(bonus);
          scene.remove(bonus.mesh);
          bonuses.splice(i, 1);
        } else if (!bonus.alive) {
          scene.remove(bonus.mesh);
          bonuses.splice(i, 1);
        }
      });

      // Spawn enemies logic
      enemySpawnTimer += 16; // approx frame duration ms
      if (enemySpawnTimer > enemySpawnInterval) {
        enemySpawnTimer = 0;
        const enemy = new Enemy();
        enemies.push(enemy);
        scene.add(enemy.mesh);
      }

      // Increase difficulty slowly
      increaseDifficulty();

      // Animate player ship subtle bobbing for comfy feel
      playerGroup.position.y = Math.sin(performance.now() * 0.002) * 0.3;

      // Render scene
      renderer.render(scene, camera);

      requestAnimationFrame(animate);
    }

    animate();

  } catch (error) {
    litechat.utils.log('error', 'Failed to load modules or setup game:', error);
    const errDiv = document.createElement('div');
    errDiv.className = 'text-red-600 p-4 bg-red-100 rounded-md';
    errDiv.textContent = `Error: ${error.message}`;
    litechat.target.appendChild(errDiv);
  }
})();
```
This creates a comfy colorful 2D scroll shooter game with a 3D effect using three.js. You control a ship that moves left/right with A/D or arrow keys, and fires with space/W/arrow up. The ship shoots colorful bullets with variable guns, bouncy bullets, and faster fire rate depending on collected bonuses. Enemies spawn from top and get faster and stronger over time. Random bonuses drop to improve fire rate, add bouncy bullets, increase guns, or give extra lives. Lives and score are displayed in a bright HUD. The background is a subtle purple-pink gradient with a faint grid for a comfy vibe. The player ship gently bobs for a cozy effect.

Try moving, shooting, and collecting bonuses to see the colorful poppy effects in action!