<!DOCTYPE html>
<html lang="hi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Sky Fighter 3D - Big Combat</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<style>
:root {
--neon-blue: #00f3ff;
--neon-pink: #ff00ff;
--danger: #ff3366;
--gold: #ffd700;
}
body {
margin: 0; padding: 0; background-color: #000;
font-family: 'Segoe UI', sans-serif; color: white;
overflow: hidden; touch-action: none;
}
#game-container {
position: relative; width: 100vw; height: 100vh;
display: flex; justify-content: center; align-items: center; background: #000;
}
#viewport {
position: relative; width: 100vw; height: calc(100vw * 16 / 9);
max-height: 100vh; max-width: calc(100vh * 9 / 16);
overflow: hidden; box-shadow: 0 0 50px rgba(0, 243, 255, 0.2);
}
canvas { display: block; width: 100%; height: 100%; }
.overlay {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
z-index: 100; background: rgba(0, 0, 0, 0.85);
display: flex; flex-direction: column; align-items: center;
justify-content: center; text-align: center; backdrop-filter: blur(8px);
}
.hidden { display: none !important; }
#game-ui {
position: absolute; top: 20px; width: 100%;
display: flex; flex-direction: column; align-items: center;
gap: 10px; z-index: 50; pointer-events: none;
}
.hud-top {
width: 90%; display: flex; justify-content: space-between;
}
.stat-card {
background: rgba(0, 20, 40, 0.7); padding: 8px 15px;
border-radius: 12px; border: 1px solid var(--neon-blue);
backdrop-filter: blur(5px);
}
#level-alert {
font-size: 1.5rem; color: var(--gold);
text-shadow: 0 0 10px var(--gold); font-weight: bold;
opacity: 0; transition: opacity 0.5s;
}
.controls {
position: absolute; bottom: 40px; width: 100%;
display: flex; justify-content: center; gap: 50px; z-index: 60;
}
.joy-btn {
width: 80px; height: 80px; background: rgba(255, 255, 255, 0.05);
border: 2px solid var(--neon-blue); border-radius: 50%;
display: flex; align-items: center; justify-content: center;
color: white; font-size: 2rem; box-shadow: 0 0 15px rgba(0, 243, 255, 0.3);
}
.joy-btn:active { background: rgba(0, 243, 255, 0.2); transform: scale(0.9); }
.heart { color: var(--danger); font-size: 20px; margin-right: 2px; }
</style>
</head>
<body>
<div id="game-container">
<div id="viewport">
<!-- Splash Screen -->
<div id="splash-screen" class="overlay">
<h1 style="letter-spacing: 8px; font-size: 2.5rem; color: #fff;">SKY ACE PRO</h1>
<p style="color: var(--neon-blue); font-weight: bold;">युद्ध शुरू करने के लिए टैप करें</p>
<div style="font-size: 0.9rem; margin-top: 10px; color: #aaa;">
• बड़े दुश्मन, बड़ा धमाका!<br>
• मिशन: 100 लेवल्स पूरे करें
</div>
</div>
<!-- UI HUD -->
<div id="game-ui" class="hidden">
<div class="hud-top">
<div class="stat-card"><div id="hearts"></div></div>
<div class="stat-card"><div id="level-val" style="color: var(--gold); font-weight: bold;">LVL 1</div></div>
<div class="stat-card"><div id="score-val" style="font-size: 1.2rem; color: var(--neon-blue);">0</div></div>
</div>
<div id="level-alert">LEVEL UP! CHALLENGE INCREASED</div>
</div>
<!-- Controls -->
<div id="controls" class="controls hidden">
<div class="joy-btn" id="btn-l">◀</div>
<div class="joy-btn" id="btn-r">▶</div>
</div>
<!-- Game Over -->
<div id="game-over" class="overlay hidden">
<h1 style="color: var(--danger);">विमान क्रैश!</h1>
<p id="retry-info" style="font-size: 1.1rem; color: #ccc;">चिंता न करें, आप इसी लेवल से जारी रख सकते हैं</p>
<button id="restart-btn" style="padding: 15px 40px; border-radius: 30px; background: var(--gold); color: black; border: none; font-weight: bold; cursor: pointer; margin-top: 10px;">उसी लेवल से शुरू करें</button>
</div>
</div>
</div>
<script>
let scene, camera, renderer, playerShip;
let gameActive = false, score = 0, health = 5, moveDir = 0;
let currentLevel = 1, levelBaseScore = 0;
let enemies = [], bullets = [], enemyBullets = [];
let stars, targetX = 0, currentX = 0;
let gameSpeed = 1.0;
// Sound System
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
function playSound(type) {
if (audioCtx.state === 'suspended') audioCtx.resume();
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
if (type === 'fire') {
osc.type = 'triangle';
osc.frequency.setValueAtTime(440, audioCtx.currentTime);
osc.frequency.exponentialRampToValueAtTime(100, audioCtx.currentTime + 0.1);
gain.gain.setValueAtTime(0.1, audioCtx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.1);
} else if (type === 'hit') {
osc.type = 'sawtooth';
osc.frequency.setValueAtTime(100, audioCtx.currentTime);
osc.frequency.exponentialRampToValueAtTime(10, audioCtx.currentTime + 0.2);
gain.gain.setValueAtTime(0.2, audioCtx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.2);
}
osc.connect(gain);
gain.connect(audioCtx.destination);
osc.start();
osc.stop(audioCtx.currentTime + 0.2);
}
let musicOsc;
function startMusic() {
if (musicOsc) return;
const oscillator = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();
oscillator.type = 'triangle';
oscillator.frequency.setValueAtTime(110, audioCtx.currentTime);
gainNode.gain.setValueAtTime(0.02, audioCtx.currentTime);
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
oscillator.start();
setInterval(() => {
if(!gameActive) return;
oscillator.frequency.exponentialRampToValueAtTime(
[110, 130, 90, 150][Math.floor(Math.random()*4)],
audioCtx.currentTime + 0.1
);
}, 500);
musicOsc = oscillator;
}
function init3D() {
const container = document.getElementById('viewport');
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(container.clientWidth, container.clientHeight);
container.appendChild(renderer.domElement);
scene.add(new THREE.AmbientLight(0xffffff, 0.8));
const sun = new THREE.PointLight(0xffffff, 1.5, 300);
sun.position.set(20, 30, 20);
scene.add(sun);
const starGeo = new THREE.BufferGeometry();
const starCoords = [], starColors = [];
for(let i=0; i<3000; i++) {
starCoords.push((Math.random()-0.5)*200, (Math.random()-0.5)*200, (Math.random()-0.5)*400);
starColors.push(1, 1, 1);
}
starGeo.setAttribute('position', new THREE.Float32BufferAttribute(starCoords, 3));
starGeo.setAttribute('color', new THREE.Float32BufferAttribute(starColors, 3));
stars = new THREE.Points(starGeo, new THREE.PointsMaterial({ size: 0.15, vertexColors: true }));
scene.add(stars);
createPlayer();
camera.position.set(0, 5, 12);
camera.lookAt(0, 1, -10);
}
function createFighter(color, isEnemy = false) {
const group = new THREE.Group();
const mat = new THREE.MeshStandardMaterial({
color, metalness: 0.7, roughness: 0.3,
emissive: color, emissiveIntensity: 0.2
});
const scale = isEnemy ? 1.8 : 1.0;
const body = new THREE.Mesh(new THREE.CylinderGeometry(0.2 * scale, 0.4 * scale, 2.5 * scale, 8), mat);
body.rotation.x = isEnemy ? -Math.PI/2 : Math.PI/2;
group.add(body);
const wings = new THREE.Mesh(new THREE.BoxGeometry(3.5 * scale, 0.1 * scale, 0.8 * scale), mat);
group.add(wings);
const tail = new THREE.Mesh(new THREE.BoxGeometry(0.2 * scale, 0.8 * scale, 0.6 * scale), mat);
tail.position.y = 0.5 * scale; tail.position.z = isEnemy ? 1.0 * scale : -1.0 * scale;
group.add(tail);
return group;
}
function createPlayer() {
if(playerShip) scene.remove(playerShip);
playerShip = createFighter(0x00f3ff);
scene.add(playerShip);
}
function spawnEnemy() {
if(!gameActive) return;
const mesh = createFighter(0xff3366, true);
mesh.position.set((Math.random()-0.5)*10, 0, -120);
scene.add(mesh);
enemies.push({ mesh, lastShot: Date.now() });
let spawnRate = Math.max(500, 2000 - (currentLevel * 15));
setTimeout(spawnEnemy, spawnRate);
}
function fire(pos, isEnemy = false) {
const color = isEnemy ? 0xffaa00 : 0x00f3ff;
const size = isEnemy ? 0.2 : 0.15;
const b = new THREE.Mesh(
new THREE.BoxGeometry(size, size, 1.5),
new THREE.MeshBasicMaterial({ color })
);
b.position.copy(pos);
scene.add(b);
if(isEnemy) enemyBullets.push(b); else {
bullets.push(b);
playSound('fire');
}
}
function checkLevelUp() {
let nextLevelThreshold = currentLevel * 1000;
if(score >= nextLevelThreshold && currentLevel < 100) {
currentLevel++;
levelBaseScore = score;
gameSpeed = 1.0 + (currentLevel * 0.04);
document.getElementById('level-val').innerText = "LVL " + currentLevel;
const alert = document.getElementById('level-alert');
alert.style.opacity = 1;
setTimeout(() => alert.style.opacity = 0, 3000);
}
}
function updateUI() {
document.getElementById('score-val').innerText = score;
const container = document.getElementById('hearts');
container.innerHTML = '<span class="heart">❤</span>'.repeat(Math.max(0, health));
checkLevelUp();
}
function animate() {
if(!gameActive) return;
requestAnimationFrame(animate);
const now = Date.now();
stars.position.z += 2.0 * gameSpeed;
if(stars.position.z > 150) stars.position.z = 0;
targetX += moveDir * 0.3;
targetX = Math.max(-6, Math.min(6, targetX));
currentX += (targetX - currentX) * 0.2;
playerShip.position.x = currentX;
playerShip.rotation.z = (currentX - targetX) * 2;
if(now % 300 < 25) fire(playerShip.position);
bullets.forEach((b, bi) => {
b.position.z -= 3.5 * gameSpeed;
enemies.forEach((e, ei) => {
if(b.position.distanceTo(e.mesh.position) < 2.5) {
scene.remove(e.mesh); enemies.splice(ei, 1);
scene.remove(b); bullets.splice(bi, 1);
score += 100; updateUI();
playSound('hit');
}
});
if(b.position.z < -130) { scene.remove(b); bullets.splice(bi, 1); }
});
enemies.forEach((e, i) => {
e.mesh.position.z += (0.6 + (currentLevel * 0.01)) * gameSpeed;
if(now - e.lastShot > 1800 / gameSpeed) {
fire(e.mesh.position, true);
e.lastShot = now;
}
if(e.mesh.position.z > 20) { scene.remove(e.mesh); enemies.splice(i, 1); }
if(e.mesh.position.distanceTo(playerShip.position) < 2.8) {
health = 0; updateUI(); endGame();
}
});
enemyBullets.forEach((eb, ebi) => {
eb.position.z += 1.5 * gameSpeed;
if(eb.position.distanceTo(playerShip.position) < 1.5) {
scene.remove(eb); enemyBullets.splice(ebi, 1);
health--; updateUI();
if(health <= 0) { playSound('hit'); endGame(); }
}
if(eb.position.z > 25) { scene.remove(eb); enemyBullets.splice(ebi, 1); }
});
renderer.render(scene, camera);
}
function endGame() {
gameActive = false;
document.getElementById('game-over').classList.remove('hidden');
}
function resetForLevel() {
enemies.forEach(e => scene.remove(e.mesh));
bullets.forEach(b => scene.remove(b));
enemyBullets.forEach(eb => scene.remove(eb));
enemies = []; bullets = []; enemyBullets = [];
health = 5;
score = levelBaseScore;
targetX = 0; currentX = 0;
updateUI();
document.getElementById('game-over').classList.add('hidden');
gameActive = true;
animate();
}
document.getElementById('splash-screen').onclick = () => {
document.getElementById('splash-screen').classList.add('hidden');
document.getElementById('game-ui').classList.remove('hidden');
document.getElementById('controls').classList.remove('hidden');
gameActive = true;
startMusic();
updateUI();
spawnEnemy();
animate();
};
document.getElementById('restart-btn').onclick = resetForLevel;
// कंट्रोल सेटअप
const btnL = document.getElementById('btn-l');
const btnR = document.getElementById('btn-r');
const onDown = (dir) => (e) => {
e.preventDefault();
moveDir = dir;
if (audioCtx.state === 'suspended') audioCtx.resume();
};
const onUp = (e) => { e.preventDefault(); moveDir = 0; };
btnL.onpointerdown = onDown(-1);
btnR.onpointerdown = onDown(1);
window.onpointerup = onUp;
window.onload = init3D;
</script>
</body>
</html>