threejsgame / index.html
akhaliq's picture
akhaliq HF Staff
Update index.html
dd36112 verified
raw
history blame
7.53 kB
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>🌟 Cosmic Dodger!</title>
<style>
* { margin: 0; padding: 0; touch-action: manipulation; }
body { overflow: hidden; background: #000; }
#hud {
position: fixed;
top: 15px;
left: 15px;
color: #fff;
font-family: 'Courier New', monospace;
font-size: 24px;
text-shadow: 0 0 10px #00ffff;
z-index: 100;
}
#gameOver {
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-score50%, -50%);
text-align: center;
color: #fff;
background: rgba(0,0,0,0.9);
padding: 20px;
border-radius: 15px;
border: 2px solid #00ff88;
}
#restart {
display: none;
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
padding: 12px 25px;
background: #00ff88;
color: #000;
border: none;
border-radius: 25px;
font-size: 18px;
cursor: pointer;
}
</style>
</head>
<body>
<div id="hud">
<div>SCORE: <span id="score">0</span></div>
<div>LIVES: <span id="lives">3</span></div>
</div>
<div id="gameOver">
<h1 style="color: #ff0066">GAME OVER</h1>
<p>Final Score: <span id="finalscore">0</span></p>
</div>
<button id="restart" onclick="location.reload()">PLAY AGAIN</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
const CONFIG = {
PLAYER_SPEED: 0.3,
ASTEROID_SPAWN: 0.02,
POWERUP_CHANCE: 0.25,
INITIAL_LIVES: 3
};
let score = 0, lives = CONFIG.INITIAL_LIVES, isGameOver = false;
let touchStartX = 0, currentX = 0, speedMultiplier = 1;
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Player (Glowing Cube)
const player = new THREE.Mesh(
new THREE.BoxGeometry(0.8, 0.8, 0.8),
new THREE.MeshStandardMaterial({
color: 0x00ff88,
emissive: 0x00ff88,
emissiveIntensity: 0.5
})
);
player.position.z = 3;
scene.add(player);
// Shield Effect
const shield = new THREE.Mesh(
new THREE.SphereGeometry(1.2, 16, 16),
new THREE.MeshStandardMaterial({
color: 0x00ffff,
transparent: true,
opacity: 0.3
})
);
shield.visible = false;
player.add(shield);
// Starfield
const stars = new THREE.Points(
new THREE.BufferGeometry().setFromPoints(
Array(1500).fill().map(() => new THREE.Vector3(
(Math.random() - 0.5) * 100,
(Math.random() - 0.5) * 100,
(Math.random() - 0.5) * 100
))
),
new THREE.PointsMaterial({
size: 0.1,
color: 0xffffff,
transparent: true,
opacity: 0.8
})
);
scene.add(stars);
// Lighting
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
// Controls
document.addEventListener('touchstart', e => touchStartX = e.touches[0].clientX);
document.addEventListener('touchmove', e => {
if(isGameOver) return;
currentX = (e.touches[0].clientX - touchStartX) * 0.025;
player.position.x = THREE.MathUtils.clamp(currentX, -7, 7);
});
// Game Loop
function animate() {
if(isGameOver) return;
// Spawning
if(Math.random() < CONFIG.ASTEROID_SPAWN + score/50000) spawnObject();
// Difficulty increase
speedMultiplier = 1 + score/5000;
// Visual Updates
stars.rotation.x += 0.0005;
stars.rotation.y += 0.0005;
player.rotation.y += 0.02;
// Collision Detection
scene.children.forEach(obj => {
if(obj.userData?.isHazard && obj.position.distanceTo(player.position) < 1.2) {
if(obj.userData.isPowerUp) {
lives = Math.min(5, lives + 1);
score += 100;
activateShield();
} else {
if(!shield.visible) lives--;
if(lives <= 0) endGame();
}
scene.remove(obj);
updateHUD();
}
});
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
function spawnObject() {
const isPowerUp = Math.random() < CONFIG.POWERUP_CHANCE;
const geometry = isPowerUp ?
new THREE.IcosahedronGeometry(0.6) :
new THREE.OctahedronGeometry(1);
const obj = new THREE.Mesh(
geometry,
new THREE.MeshStandardMaterial({
color: isPowerUp ? 0x00ffff : 0xff4444,
emissive: isPowerUp ? 0x00ffff : 0xff4444,
emissiveIntensity: 0.2
})
);
obj.position.set(
(Math.random() - 0.5) * 14,
(Math.random() - 0.5) * 8,
-50
);
obj.userData = { isHazard: true, isPowerUp };
// Animation
function move() {
obj.position.z += 0.15 * speedMultiplier;
obj.rotation.x += 0.02;
obj.rotation.y += 0.02;
if(obj.position.z > 5) scene.remove(obj);
else requestAnimationFrame(move);
}
scene.add(obj);
move();
}
function activateShield() {
shield.visible = true;
setTimeout(() => shield.visible = false, 2000);
}
function updateHUD() {
document.getElementById('score').textContent = score;
document.getElementById('lives').textContent = lives;
score += speedMultiplier;
}
function endGame() {
isGameOver = true;
document.getElementById('gameOver').style.display = 'block';
document.getElementById('restart').style.display = 'block';
localStorage.setItem('highScore', Math.max(score, localStorage.getItem('highScore') || 0));
}
// Init
camera.position.z = 5;
animate();
updateHUD();
// Restart
document.addEventListener('touchend', () => isGameOver && location.reload());
</script>
</body>
</html>