<!
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3D CS-Lite Offline</title>
<style>
body { margin: 0; overflow: hidden; font-family: sans-serif; }
#crosshair {
position: absolute; top: 50%; left: 50%;
width: 20px; height: 20px;
border: 2px solid #00ff00; border-radius: 50%;
transform: translate(-50%, -50%); pointer-events: none;
#ui {
position: absolute; bottom: 20px; left: 20px;
color: white; font-size: 24px; text-shadow: 2px 2px black;
#instructions {
position: absolute; top: 50%; left: 50%;
transform: translate(-50%, -50%);
color: white; background: rgba(0,0,0,0.8);
padding: 20px; text-align: center; cursor: pointer;
</style>
</head>
<body>
<div id="crosshair"></div>
<div id="ui">Kills: <span id="score">0</span> | HP: <span
id="hp">100</span></div>
<div id="instructions"><h1>CLICK TO START BATTLE</h1><p>(WASD to
Move, Mouse to Aim/Shoot)</p></div>
<script type="importmap">
{ "imports": { "three":
"[Link] } }
</script>
<script type="module">
import * as THREE from 'three';
// --- SETUP ---
const scene = new [Link]();
[Link] = new [Link](0x87ceeb); // Sky blue
const camera = new [Link](75,
[Link] / [Link], 0.1, 1000);
const renderer = new [Link]({ antialias: true });
[Link]([Link], [Link]);
[Link]([Link]);
// --- LIGHTING ---
const light = new [Link](0xffffff, 0x444444, 1);
[Link](light);
// --- GROUND ---
const floor = new [Link](
new [Link](100, 100),
new [Link]({ color: 0x555555 })
);
[Link].x = -[Link] / 2;
[Link](floor);
// --- PLAYER STATE ---
let score = 0;
let hp = 100;
const moveSpeed = 0.15;
const playerVelocity = new THREE.Vector3();
const keys = {};
// --- BOTS & BULLETS ---
const enemies = [];
const bullets = [];
function spawnBot() {
const geometry = new [Link](1, 2, 1);
const material = new [Link]({ color:
0xff0000 });
const bot = new [Link](geometry, material);
[Link]([Link]() * 40 - 20, 1, [Link]() * 40 - 20);
[Link](bot);
[Link](bot);
}
for(let i=0; i<5; i++) spawnBot();
// --- CONTROLS ---
[Link]('keydown', (e) => keys[[Link]] = true);
[Link]('keyup', (e) => keys[[Link]] = false);
const instructions = [Link]('instructions');
[Link]('click', () => {
[Link]();
});
[Link]('pointerlockchange', () => {
[Link] = [Link] ? 'none' :
'block';
});
[Link]('mousemove', (e) => {
if ([Link]) {
[Link].y -= [Link] * 0.002;
[Link].x -= [Link] * 0.002;
[Link].x = [Link](-[Link]/2, [Link]([Link]/2,
[Link].x));
});
// Shooting
[Link]('mousedown', () => {
if (![Link]) return;
// Create bullet
const bGeo = new [Link](0.1);
const bMat = new [Link]({ color: 0xffff00 });
const bullet = new [Link](bGeo, bMat);
[Link]([Link]);
const direction = new THREE.Vector3(0, 0, -
1).applyQuaternion([Link]);
[Link] = [Link](0.8);
[Link](bullet);
[Link](bullet);
});
// --- GAME LOOP ---
function animate() {
requestAnimationFrame(animate);
if ([Link]) {
// Movement logic
const direction = new THREE.Vector3();
if (keys['KeyW']) direction.z -= 1;
if (keys['KeyS']) direction.z += 1;
if (keys['KeyA']) direction.x -= 1;
if (keys['KeyD']) direction.x += 1;
[Link]([Link]);
direction.y = 0; // Keep on ground
[Link]([Link]().multiplyScalar(moveSpeed));
// Update Bullets
[Link]((b, i) => {
[Link]([Link]);
if ([Link]() > 100) {
[Link](b);
[Link](i, 1);
// Bullet hit detection
[Link]((bot, bi) => {
if ([Link]([Link]) < 1.5) {
[Link](bot);
[Link](bi, 1);
[Link](b);
[Link](i, 1);
score++;
[Link]('score').innerText = score;
setTimeout(spawnBot, 2000); // Respawn
}
});
});
// Update Bots (Basic AI)
[Link](bot => {
const dir = new THREE.Vector3().subVectors([Link],
[Link]).normalize();
[Link].x += dir.x * 0.03;
[Link].z += dir.z * 0.03;
// If bot touches player
if ([Link]([Link]) < 1.2) {
hp -= 0.5;
[Link]('hp').innerText = [Link](hp);
if(hp <= 0) alert("GG! Final Score: " + score);
});
[Link](scene, camera);
[Link].y = 1.6; // Human height
[Link] = 'YXZ'; // Essential for FPS look
animate();
</script>
</body>
</html>