LiteChat Model Race Result (RUNJS)
I'll create a colorful 2D scroll shooter with 3D effects using Three.js! This will be a fun, poppy game with all the features you requested.
```runjs
// Clear any previous content
litechat.target.replaceChildren();
async function createScrollShooter() {
try {
litechat.utils.log('info', '🚀 Loading 2D Scroll Shooter with 3D effects...');
// Load Three.js modules
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/"
}
}
]);
const { THREE } = modules;
// Create game container
const gameContainer = document.createElement('div');
gameContainer.className = 'relative bg-gradient-to-b from-purple-900 via-blue-900 to-indigo-900 rounded-lg overflow-hidden';
// Create canvas
const canvas = document.createElement('canvas');
canvas.width = 800;
canvas.height = 600;
canvas.className = 'block mx-auto border-4 border-pink-400 rounded-lg shadow-2xl';
gameContainer.appendChild(canvas);
// Create UI overlay
const uiOverlay = document.createElement('div');
uiOverlay.className = 'absolute top-0 left-0 w-full h-full pointer-events-none';
uiOverlay.innerHTML = `
<div class="p-4 text-white font-bold">
<div class="flex justify-between items-center">
<div>Score: <span id="score" class="text-yellow-400">0</span></div>
<div>Lives: <span id="lives" class="text-red-400">❤️❤️❤️</span></div>
</div>
<div class="mt-2">
<div>Fire Rate: <span id="fireRate" class="text-green-400">100%</span></div>
<div>Guns: <span id="gunCount" class="text-blue-400">1</span> | Bouncy: <span id="bouncy" class="text-purple-400">0</span></div>
</div>
</div>
<div id="gameOver" class="hidden absolute inset-0 bg-black bg-opacity-75 flex items-center justify-center">
<div class="text-center text-white">
<h2 class="text-4xl font-bold mb-4 text-red-400">GAME OVER</h2>
<p class="text-xl mb-4">Final Score: <span id="finalScore" class="text-yellow-400">0</span></p>
<button id="restartBtn" class="px-6 py-3 bg-pink-500 hover:bg-pink-600 text-white font-bold rounded-lg pointer-events-auto cursor-pointer">
PLAY AGAIN
</button>
</div>
</div>
`;
gameContainer.appendChild(uiOverlay);
// Controls info
const controls = document.createElement('div');
controls.className = 'mt-4 p-4 bg-gray-800 text-white rounded-lg text-center';
controls.innerHTML = `
<div class="flex justify-center gap-8 text-sm">
<div>🎮 <strong>WASD</strong> or Arrow Keys to move</div>
<div>🔫 <strong>SPACE</strong> to shoot</div>
<div>🎯 Collect colorful bonuses!</div>
</div>
`;
gameContainer.appendChild(controls);
litechat.target.appendChild(gameContainer);
// Three.js setup
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera(
canvas.width / -2, canvas.width / 2,
canvas.height / 2, canvas.height / -2,
1, 1000
);
camera.position.z = 100;
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
renderer.setSize(canvas.width, canvas.height);
renderer.setClearColor(0x0a0a2e);
// Game state
const gameState = {
score: 0,
lives: 3,
fireRate: 1.0,
gunCount: 1,
bouncyShots: 0,
isGameOver: false,
lastShot: 0,
keys: {},
player: null,
bullets: [],
enemies: [],
bonuses: [],
particles: [],
lastEnemySpawn: 0,
enemySpawnRate: 1000,
difficultyTimer: 0
};
// Bonus types
const bonusTypes = [
{ type: 'fireRate', color: 0xff6b6b, text: '🔥 FIRE RATE +10%' },
{ type: 'bouncy', color: 0x4ecdc4, text: '⚡ BOUNCY SHOTS' },
{ type: 'guns', color: 0x45b7d1, text: '🔫 MORE GUNS' },
{ type: 'life', color: 0x96ceb4, text: '❤️ EXTRA LIFE' },
{ type: 'enemySpeed', color: 0xfeca57, text: '⚠️ ENEMIES FASTER!' }
];
// Create player
function createPlayer() {
const geometry = new THREE.ConeGeometry(15, 30, 3);
const material = new THREE.MeshBasicMaterial({
color: 0x00ff88,
transparent: true,
opacity: 0.9
});
const player = new THREE.Mesh(geometry, material);
player.position.set(0, -canvas.height/2 + 50, 0);
player.rotation.z = Math.PI;
// Add glow effect
const glowGeometry = new THREE.ConeGeometry(20, 35, 3);
const glowMaterial = new THREE.MeshBasicMaterial({
color: 0x00ff88,
transparent: true,
opacity: 0.3
});
const glow = new THREE.Mesh(glowGeometry, glowMaterial);
player.add(glow);
scene.add(player);
return player;
}
// Create bullet
function createBullet(x, y, bounces = 0) {
const geometry = new THREE.SphereGeometry(3, 8, 8);
const material = new THREE.MeshBasicMaterial({
color: bounces > 0 ? 0xff4081 : 0x00ffff,
transparent: true,
opacity: 0.9
});
const bullet = new THREE.Mesh(geometry, material);
bullet.position.set(x, y, 0);
bullet.userData = { speed: 8, bounces, type: 'bullet' };
// Add trail effect
const trailGeometry = new THREE.SphereGeometry(5, 6, 6);
const trailMaterial = new THREE.MeshBasicMaterial({
color: bounces > 0 ? 0xff4081 : 0x00ffff,
transparent: true,
opacity: 0.3
});
const trail = new THREE.Mesh(trailGeometry, trailMaterial);
bullet.add(trail);
scene.add(bullet);
return bullet;
}
// Create enemy
function createEnemy() {
const types = [
{ geometry: new THREE.BoxGeometry(20, 20, 10), color: 0xff3068, health: 1, speed: 2, points: 10 },
{ geometry: new THREE.OctahedronGeometry(15), color: 0x9c88ff, health: 2, speed: 1.5, points: 20 },
{ geometry: new THREE.DodecahedronGeometry(12), color: 0xff9f43, health: 3, speed: 1, points: 30 }
];
const type = types[Math.floor(Math.random() * types.length)];
const material = new THREE.MeshBasicMaterial({
color: type.color,
transparent: true,
opacity: 0.8
});
const enemy = new THREE.Mesh(type.geometry, material);
enemy.position.set(
(Math.random() - 0.5) * (canvas.width - 40),
canvas.height/2 + 20,
0
);
enemy.userData = {
health: type.health,
maxHealth: type.health,
speed: type.speed * (1 + gameState.difficultyTimer * 0.1),
points: type.points,
type: 'enemy'
};
scene.add(enemy);
return enemy;
}
// Create bonus
function createBonus(x, y) {
const bonusType = bonusTypes[Math.floor(Math.random() * bonusTypes.length)];
const geometry = new THREE.StarGeometry(12, 8);
const material = new THREE.MeshBasicMaterial({
color: bonusType.color,
transparent: true,
opacity: 0.9
});
const bonus = new THREE.Mesh(geometry, material);
bonus.position.set(x, y, 0);
bonus.userData = {
type: 'bonus',
bonusType: bonusType.type,
text: bonusType.text,
rotationSpeed: 0.1
};
scene.add(bonus);
return bonus;
}
// Create particle explosion
function createExplosion(x, y, color = 0xffffff, count = 10) {
for (let i = 0; i < count; i++) {
const geometry = new THREE.SphereGeometry(2, 6, 6);
const material = new THREE.MeshBasicMaterial({
color: color + Math.random() * 0x333333,
transparent: true,
opacity: 1
});
const particle = new THREE.Mesh(geometry, material);
particle.position.set(x, y, 0);
const angle = (Math.PI * 2 * i) / count;
const speed = 3 + Math.random() * 4;
particle.userData = {
type: 'particle',
velocity: {
x: Math.cos(angle) * speed,
y: Math.sin(angle) * speed
},
life: 1.0,
decay: 0.02
};
scene.add(particle);
gameState.particles.push(particle);
}
}
// Shoot bullets
function shoot() {
const now = Date.now();
const fireDelay = 150 / gameState.fireRate;
if (now - gameState.lastShot < fireDelay) return;
gameState.lastShot = now;
const playerX = gameState.player.position.x;
const playerY = gameState.player.position.y + 20;
if (gameState.gunCount === 1) {
gameState.bullets.push(createBullet(playerX, playerY, gameState.bouncyShots));
} else if (gameState.gunCount === 2) {
gameState.bullets.push(createBullet(playerX - 15, playerY, gameState.bouncyShots));
gameState.bullets.push(createBullet(playerX + 15, playerY, gameState.bouncyShots));
} else if (gameState.gunCount >= 3) {
gameState.bullets.push(createBullet(playerX, playerY, gameState.bouncyShots));
gameState.bullets.push(createBullet(playerX - 20, playerY, gameState.bouncyShots));
gameState.bullets.push(createBullet(playerX + 20, playerY, gameState.bouncyShots));
}
}
// Apply bonus
function applyBonus(bonusType) {
switch (bonusType.type) {
case 'fireRate':
gameState.fireRate += 0.1;
break;
case 'bouncy':
gameState.bouncyShots += 1;
break;
case 'guns':
gameState.gunCount = Math.min(gameState.gunCount + 1, 3);
break;
case 'life':
gameState.lives = Math.min(gameState.lives + 1, 5);
break;
case 'enemySpeed':
gameState.difficultyTimer += 0.5;
break;
}
// Show bonus text
litechat.utils.toast('success', bonusType.text);
}
// Update UI
function updateUI() {
document.getElementById('score').textContent = gameState.score;
document.getElementById('lives').textContent = '❤️'.repeat(gameState.lives);
document.getElementById('fireRate').textContent = Math.round(gameState.fireRate * 100) + '%';
document.getElementById('gunCount').textContent = gameState.gunCount;
document.getElementById('bouncy').textContent = gameState.bouncyShots;
}
// Game over
function gameOver() {
gameState.isGameOver = true;
document.getElementById('finalScore').textContent = gameState.score;
document.getElementById('gameOver').classList.remove('hidden');
}
// Restart game
function restartGame() {
// Reset game state
gameState.score = 0;
gameState.lives = 3;
gameState.fireRate = 1.0;
gameState.gunCount = 1;
gameState.bouncyShots = 0;
gameState.isGameOver = false;
gameState.difficultyTimer = 0;
// Clear all objects
[...gameState.bullets, ...gameState.enemies, ...gameState.bonuses, ...gameState.particles].forEach(obj => {
scene.remove(obj);
});
gameState.bullets = [];
gameState.enemies = [];
gameState.bonuses = [];
gameState.particles = [];
// Hide game over screen
document.getElementById('gameOver').classList.add('hidden');
updateUI();
}
// Input handling
document.addEventListener('keydown', (e) => {
gameState.keys[e.key.toLowerCase()] = true;
if (e.key === ' ') {
e.preventDefault();
if (!gameState.isGameOver) shoot();
}
});
document.addEventListener('keyup', (e) => {
gameState.keys[e.key.toLowerCase()] = false;
});
// Restart button
document.getElementById('restartBtn').addEventListener('click', restartGame);
// Initialize player
gameState.player = createPlayer();
updateUI();
// Game loop
function gameLoop() {
if (gameState.isGameOver) {
requestAnimationFrame(gameLoop);
return;
}
const now = Date.now();
// Player movement
if (gameState.keys['a'] || gameState.keys['arrowleft']) {
gameState.player.position.x = Math.max(gameState.player.position.x - 5, -canvas.width/2 + 20);
}
if (gameState.keys['d'] || gameState.keys['arrowright']) {
gameState.player.position.x = Math.min(gameState.player.position.x + 5, canvas.width/2 - 20);
}
if (gameState.keys['w'] || gameState.keys['arrowup']) {
gameState.player.position.y = Math.min(gameState.player.position.y + 5, canvas.height/2 - 30);
}
if (gameState.keys['s'] || gameState.keys['arrowdown']) {
gameState.player.position.y = Math.max(gameState.player.position.y - 5, -canvas.height/2 + 30);
}
// Auto-shoot when space is held
if (gameState.keys[' ']) {
shoot();
}
// Player rotation effect
gameState.player.rotation.z = Math.PI + Math.sin(now * 0.01) * 0.1;
// Spawn enemies
if (now - gameState.lastEnemySpawn > gameState.enemySpawnRate) {
gameState.enemies.push(createEnemy());
gameState.lastEnemySpawn = now;
gameState.enemySpawnRate = Math.max(300, 1000 - gameState.difficultyTimer * 50);
}
// Update bullets
gameState.bullets.forEach((bullet, index) => {
bullet.position.y += bullet.userData.speed;
bullet.rotation.z += 0.2;
// Remove bullets that are off-screen
if (bullet.position.y > canvas.height/2 + 20) {
scene.remove(bullet);
gameState.bullets.splice(index, 1);
}
});
// Update enemies
gameState.enemies.forEach((enemy, index) => {
enemy.position.y -= enemy.userData.speed;
enemy.rotation.x += 0.02;
enemy.rotation.y += 0.03;
// Remove enemies that are off-screen
if (enemy.position.y < -canvas.height/2 - 20) {
scene.remove(enemy);
gameState.enemies.splice(index, 1);
return;
}
// Check collision with player
const dx = enemy.position.x - gameState.player.position.x;
const dy = enemy.position.y - gameState.player.position.y;
if (Math.sqrt(dx*dx + dy*dy) < 25) {
createExplosion(enemy.position.x, enemy.position.y, 0xff3068, 15);
scene.remove(enemy);
gameState.enemies.splice(index, 1);
gameState.lives--;
if (gameState.lives <= 0) {
gameOver();
}
updateUI();
}
});
// Update bonuses
gameState.bonuses.forEach((bonus, index) => {
bonus.position.y -= 2;
bonus.rotation.z += bonus.userData.rotationSpeed;
bonus.rotation.y += bonus.userData.rotationSpeed;
// Remove bonuses that are off-screen
if (bonus.position.y < -canvas.height/2 - 20) {
scene.remove(bonus);
gameState.bonuses.splice(index, 1);
return;
}
// Check collision with player
const dx = bonus.position.x - gameState.player.position.x;
const dy = bonus.position.y - gameState.player.position.y;
if (Math.sqrt(dx*dx + dy*dy) < 20) {
createExplosion(bonus.position.x, bonus.position.y, bonus.material.color.getHex(), 8);
applyBonus(bonus.userData);
scene.remove(bonus);
gameState.bonuses.splice(index, 1);
updateUI();
}
});
// Bullet-enemy collisions
gameState.bullets.forEach((bullet, bulletIndex) => {
gameState.enemies.forEach((enemy, enemyIndex) => {
const dx = bullet.position.x - enemy.position.x;
const dy = bullet.position.y - enemy.position.y;
if (Math.sqrt(dx*dx + dy*dy) < 15) {
enemy.userData.health--;
// Enemy hit effect
enemy.material.color.setHex(0xffffff);
setTimeout(() => {
if (enemy.material) enemy.material.color.setHex(enemy.userData.health > 0 ? 0xff3068 : 0x666666);
}, 100);
if (enemy.userData.health <= 0) {
// Enemy destroyed
createExplosion(enemy.position.x, enemy.position.y, enemy.material.color.getHex(), 12);
gameState.score += enemy.userData.points;
// Random bonus drop (20% chance)
if (Math.random() < 0.2) {
gameState.bonuses.push(createBonus(enemy.position.x, enemy.position.y));
}
// Handle bouncy shots
if (bullet.userData.bounces > 0) {
bullet.userData.bounces--;
bullet.material.color.setHex(0xff4081);
bullet.position.y = enemy.position.y;
} else {
scene.remove(bullet);
gameState.bullets.splice(bulletIndex, 1);
}
scene.remove(enemy);
gameState.enemies.splice(enemyIndex, 1);
} else {
// Bullet destroyed but enemy survives
scene.remove(bullet);
gameState.bullets.splice(bulletIndex, 1);
}
updateUI();
}
});
});
// Update particles
gameState.particles.forEach((particle, index) => {
particle.position.x += particle.userData.velocity.x;
particle.position.y += particle.userData.velocity.y;
particle.userData.life -= particle.userData.decay;
particle.material.opacity = particle.userData.life;
particle.scale.setScalar(particle.userData.life);
if (particle.userData.life <= 0) {
scene.remove(particle);
gameState.particles.splice(index, 1);
}
});
// Increase difficulty over time
gameState.difficultyTimer += 0.001;
// Render
renderer.render(scene, camera);
requestAnimationFrame(gameLoop);
}
// Start the game
gameLoop();
litechat.utils.log('info', '🎮 2D Scroll Shooter with 3D effects loaded successfully!');
} catch (error) {
litechat.utils.log('error', '❌ Failed to create scroll shooter:', error.message);
const errorDiv = document.createElement('div');
errorDiv.className = 'p-4 text-red-600 bg-red-100 border border-red-200 rounded-md';
errorDiv.textContent = `Error: ${error.message}`;
litechat.target.appendChild(errorDiv);
}
}
createScrollShooter();
```
I've created a vibrant, colorful 2D scroll shooter with 3D effects! Here's what the game features:
🎮 **Core Gameplay:**
- WASD or Arrow Keys to move your glowing green ship
- SPACE to shoot (hold for continuous fire)
- Enemies spawn from the top with different shapes and health
- Collect colorful star-shaped bonuses
🎯 **Bonus System:**
- **🔥 Fire Rate** - Increases shooting speed by 10% per bonus
- **⚡ Bouncy Shots** - Bullets bounce between enemies
- **🔫 More Guns** - Up to 3 guns firing simultaneously
- **❤️ Extra Life** - Gain additional lives
- **⚠️ Enemies Faster** - Makes enemies more challenging
✨ **Visual Effects:**
- 3D geometric enemies (cubes, octahedrons, dodecahedrons)
- Particle explosion effects when enemies are destroyed
- Glowing player ship with rotation effects
- Colorful trails on bullets
- Gradient background with neon border
🎨 **Comfy Design:**
- Soft purple-to-blue gradient background
- Rounded corners and glowing effects
- Smooth animations and particle effects
- Clear UI showing score, lives, and current bonuses
The game gets progressively harder with faster enemy spawns and movement. The 3D effects give depth while maintaining the classic 2D shooter feel. The colorful, poppy aesthetic makes it visually engaging and fun to play!