# Save the full FPS shooting game with all features added as an HTML file
html_code = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Advanced FPS Shooting Game</title>
<style>
body { margin: 0; overflow: hidden; background: #000; }
canvas { display: block; }
#instructions {
position: absolute;
top: 50%;
width: 100%;
text-align: center;
color: white;
font-family: Arial, sans-serif;
font-size: 24px;
}
#hud {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-family: Arial, sans-serif;
font-size: 16px;
}
</style>
</head>
<body>
<div id="instructions">Click to play. Use WASD to move, mouse to look, click to
shoot.</div>
<div id="hud">Ammo: <span id="ammo">10</span> | Health: <span
id="health">100</span> | Score: <span id="score">0</span></div>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r148/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.148.0/examples/js/controls/
PointerLockControls.js"></script>
<script>
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(75,
window.innerWidth/window.innerHeight, 0.1, 1000);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
let controls = new THREE.PointerLockControls(camera, document.body);
const instructions = document.getElementById('instructions');
instructions.addEventListener('click', () => {
controls.lock();
});
controls.addEventListener('lock', () => {
instructions.style.display = 'none';
});
controls.addEventListener('unlock', () => {
instructions.style.display = '';
});
scene.add(controls.getObject());
let floorGeometry = new THREE.PlaneGeometry(100, 100);
let floorMaterial = new THREE.MeshBasicMaterial({color: 0x222222});
let floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.rotation.x = -Math.PI / 2;
scene.add(floor);
let gunGeometry = new THREE.BoxGeometry(0.2, 0.1, 1);
let gunMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
let gun = new THREE.Mesh(gunGeometry, gunMaterial);
gun.position.set(0.3, -0.2, -0.5);
camera.add(gun);
let bullets = [];
let enemies = [];
let ammo = 10;
let health = 100;
let score = 0;
const ammoEl = document.getElementById("ammo");
const healthEl = document.getElementById("health");
const scoreEl = document.getElementById("score");
function shoot() {
if (ammo <= 0) return;
ammo--;
ammoEl.textContent = ammo;
const bullet = new THREE.Mesh(
new THREE.SphereGeometry(0.05, 8, 8),
new THREE.MeshBasicMaterial({ color: 0xffff00 })
);
bullet.position.copy(camera.position);
bullet.velocity = new THREE.Vector3();
camera.getWorldDirection(bullet.velocity);
bullet.velocity.multiplyScalar(1);
scene.add(bullet);
bullets.push(bullet);
}
window.addEventListener('click', shoot);
let move = { forward: false, backward: false, left: false, right: false };
document.addEventListener('keydown', (e) => {
if (e.code === 'KeyW') move.forward = true;
if (e.code === 'KeyS') move.backward = true;
if (e.code === 'KeyA') move.left = true;
if (e.code === 'KeyD') move.right = true;
if (e.code === 'KeyR') {
ammo = 10;
ammoEl.textContent = ammo;
}
});
document.addEventListener('keyup', (e) => {
if (e.code === 'KeyW') move.forward = false;
if (e.code === 'KeyS') move.backward = false;
if (e.code === 'KeyA') move.left = false;
if (e.code === 'KeyD') move.right = false;
});
camera.position.y = 1.6;
function spawnEnemy() {
const enemy = new THREE.Mesh(
new THREE.BoxGeometry(0.5, 1, 0.5),
new THREE.MeshBasicMaterial({ color: 0x00ff00 })
);
enemy.position.set(
(Math.random() - 0.5) * 40,
0.5,
(Math.random() - 0.5) * 40
);
scene.add(enemy);
enemies.push(enemy);
}
setInterval(spawnEnemy, 3000);
function animate() {
requestAnimationFrame(animate);
const speed = 0.1;
if (move.forward) controls.moveForward(speed);
if (move.backward) controls.moveForward(-speed);
if (move.left) controls.moveRight(-speed);
if (move.right) controls.moveRight(speed);
for (let i = 0; i < bullets.length; i++) {
bullets[i].position.add(bullets[i].velocity);
if (bullets[i].position.length() > 100) {
scene.remove(bullets[i]);
bullets.splice(i, 1);
i--;
}
}
// Enemy collision
for (let i = 0; i < enemies.length; i++) {
let enemy = enemies[i];
enemy.lookAt(camera.position);
enemy.position.lerp(camera.position, 0.002);
// Close to player
if (enemy.position.distanceTo(camera.position) < 1) {
health -= 1;
healthEl.textContent = health;
if (health <= 0) {
alert("Game Over! Final Score: " + score);
location.reload();
}
}
// Bullet hits enemy
for (let j = 0; j < bullets.length; j++) {
if (enemy.position.distanceTo(bullets[j].position) < 0.5) {
scene.remove(enemy);
scene.remove(bullets[j]);
enemies.splice(i, 1);
bullets.splice(j, 1);
score += 10;
scoreEl.textContent = score;
break;
}
}
}
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>
"""
# Save as HTML file
file_path = "/mnt/data/fps-shooter-game.html"
with open(file_path, "w") as f:
f.write(html_code)
file_path