LiteChat Race Result
```runjs
// Clear any previous content
litechat.target.replaceChildren();
// Load Three.js and OrbitControls
async function loadThreeJS() {
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']
}
]);
return modules;
}
// Create game container
const container = document.createElement('div');
container.className = 'p-4 bg-gray-900 rounded-lg h-screen w-screen';
litechat.target.appendChild(container);
// Create canvas
const canvas = document.createElement('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.className = 'border border-gray-600 rounded';
container.appendChild(canvas);
// Create UI elements
const uiContainer = document.createElement('div');
uiContainer.className = 'absolute top-4 left-4 text-white text-lg font-bold';
container.appendChild(uiContainer);
const scoreText = document.createElement('div');
scoreText.textContent = 'Score: 0';
uiContainer.appendChild(scoreText);
const healthText = document.createElement('div');
healthText.textContent = 'Health: 3';
uiContainer.appendChild(healthText);
const gunText = document.createElement('div');
gunText.textContent = 'Gun: 1';
uiContainer.appendChild(gunText);
// Initialize Three.js
let scene, camera, renderer, controls;
let player, bullets = [], enemies = [], bonuses = [];
let score = 0, health = 3, gunLevel = 1, fireRate = 300, lastShot = 0;
let enemySpeed = 0.02, enemySpawnTimer = 0;
async function initThreeJS() {
const { THREE, OrbitControls } = await loadThreeJS();
scene = new THREE.Scene();
scene.background = new THREE.Color(0x111111);
camera = new THREE.PerspectiveCamera(75, canvas.width / canvas.height, 0.1, 1000);
camera.position.set(0, 5, 10);
renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
renderer.setSize(canvas.width, canvas.height);
renderer.shadowMap.enabled = true;
controls = new OrbitControls.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.enableZoom = false;
controls.enablePan = false;
// Create player
const playerGeometry = new THREE.BoxGeometry(1, 0.5, 0.5);
const playerMaterial = new THREE.MeshLambertMaterial({ color: 0x00ff00 });
player = new THREE.Mesh(playerGeometry, playerMaterial);
player.position.set(0, 0, 0);
scene.add(player);
// Add lights
const ambient = new THREE.AmbientLight(0x404040, 0.6);
scene.add(ambient);
const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);
dirLight.position.set(10, 10, 5);
dirLight.castShadow = true;
scene.add(dirLight);
// Handle window resize
window.addEventListener('resize', onWindowResize, false);
// Start animation loop
animate();
}
function onWindowResize() {
camera.aspect = canvas.width / canvas.height;
camera.updateProjectionMatrix();
renderer.setSize(canvas.width, canvas.height);
}
function animate() {
requestAnimationFrame(animate);
controls.update();
updateGame();
renderer.render(scene, camera);
}
function updateGame() {
// Update enemy spawn
enemySpawnTimer += 0.1;
if (enemySpawnTimer > 100) {
spawnEnemy();
enemySpawnTimer = 0;
}
// Update bullets
bullets.forEach((bullet, index) => {
bullet.position.z -= 0.1;
if (bullet.position.z < -10) {
scene.remove(bullet);
bullets.splice(index, 1);
}
});
// Update enemies
enemies.forEach((enemy, index) => {
enemy.position.z += enemySpeed;
if (enemy.position.z > 10) {
// Enemy reached bottom - player loses health
health--;
healthText.textContent = `Health: ${health}`;
scene.remove(enemy);
enemies.splice(index, 1);
}
});
// Update bonuses
bonuses.forEach((bonus, index) => {
bonus.position.z += 0.05;
if (bonus.position.z > 10) {
scene.remove(bonus);
bonuses.splice(index, 1);
}
});
// Check collisions
checkCollisions();
}
function checkCollisions() {
// Bullet vs Enemy
for (let i = bullets.length - 1; i >= 0; i--) {
const bullet = bullets[i];
for (let j = enemies.length - 1; j >= 0; j--) {
const enemy = enemies[j];
if (Math.abs(bullet.position.x - enemy.position.x) < 0.5 &&
Math.abs(bullet.position.z - enemy.position.z) < 0.5) {
// Apply bonus
const bonusType = Math.random() > 0.5 ? 'fire' : Math.random() > 0.5 ? 'bouncy' :
Math.random() > 0.5 ? 'gun' : 'life';
spawnBonus(enemy.position, bonusType);
// Remove enemy and bullet
scene.remove(enemy);
enemies.splice(j, 1);
scene.remove(bullet);
bullets.splice(i, 1);
score += 10;
scoreText.textContent = `Score: ${score}`;
break;
}
}
}
// Player vs Bonus
for (let i = bonuses.length - 1; i >= 0; i--) {
const bonus = bonuses[i];
if (Math.abs(player.position.x - bonus.position.x) < 0.5 &&
Math.abs(player.position.z - bonus.position.z) < 0.5) {
applyBonus(bonus.type);
scene.remove(bonus);
bonuses.splice(i, 1);
}
}
}
function spawnEnemy() {
const enemyGeometry = new THREE.BoxGeometry(0.8, 0.4, 0.4);
const colors = [0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff, 0x00ffff];
const enemyMaterial = new THREE.MeshLambertMaterial({ color: colors[Math.floor(Math.random() * colors.length)] });
const enemy = new THREE.Mesh(enemyGeometry, enemyMaterial);
// Random x position
enemy.position.x = (Math.random() - 0.5) * 10;
enemy.position.z = 10;
scene.add(enemy);
enemies.push(enemy);
}
function spawnBonus(position, type) {
const bonusGeometry = new THREE.SphereGeometry(0.3, 8, 8);
const colors = {
fire: 0xffbb33,
bouncy: 0x33ffbb,
gun: 0xff33bb,
life: 0x33bbff
};
const bonusMaterial = new THREE.MeshLambertMaterial({ color: colors[type] });
const bonus = new THREE.Mesh(bonusGeometry, bonusMaterial);
bonus.position.set(position.x, 0, position.z);
bonus.type = type;
scene.add(bonus);
bonuses.push(bonus);
}
function applyBonus(type) {
switch(type) {
case 'fire':
fireRate = Math.max(50, fireRate - 50);
litechat.utils.toast('success', 'Fire rate increased!');
break;
case 'bouncy':
// Implement bouncy fire logic
break;
case 'gun':
gunLevel = Math.min(3, gunLevel + 1);
gunText.textContent = `Gun: ${gunLevel}`;
litechat.utils.toast('success', 'Gun upgraded!');
break;
case 'life':
health = Math.min(5, health + 1);
healthText.textContent = `Health: ${health}`;
litechat.utils.toast('success', 'Extra life!');
break;
}
}
// Handle keyboard input
document.addEventListener('keydown', (e) => {
if (e.code === 'Space') {
shoot();
}
});
document.addEventListener('mousemove', (e) => {
// Move player with mouse
const x = (e.clientX / window.innerWidth) * 10 - 5;
player.position.x = x;
});
function shoot() {
const now = Date.now();
if (now - lastShot < fireRate) return;
lastShot = now;
const bulletGeometry = new THREE.BoxGeometry(0.2, 0.2, 0.2);
const bulletMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff });
const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial);
// Shoot in different patterns based on gun level
const spread = gunLevel === 2 ? 0.5 : gunLevel === 3 ? 1 : 0;
for (let i = 0; i < gunLevel; i++) {
const bulletClone = bullet.clone();
bulletClone.position.set(
player.position.x + (i - (gunLevel - 1)/2) * spread,
player.position.y,
player.position.z + 1
);
scene.add(bulletClone);
bullets.push(bulletClone);
}
}
// Start the game
initThreeJS();
```