anycoder-3a661735 / index.html
F555's picture
Upload folder using huggingface_hub
c799e7d verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Neon Void: Hyper Space Shooter</title>
<!-- Importing a futuristic font -->
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&display=swap" rel="stylesheet">
<!-- Importing FontAwesome for UI Icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary-color: #00f3ff;
--secondary-color: #bc13fe;
--danger-color: #ff2a6d;
--bg-color: #050505;
--glass-bg: rgba(255, 255, 255, 0.05);
--glass-border: rgba(255, 255, 255, 0.1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
overflow: hidden;
background-color: var(--bg-color);
font-family: 'Orbitron', sans-serif;
color: white;
height: 100vh;
width: 100vw;
}
/* --- Canvas Layer --- */
#gameCanvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
/* --- UI Layer --- */
#ui-layer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 10;
pointer-events: none; /* Let clicks pass through to canvas when playing */
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 20px;
}
/* --- Header / HUD --- */
.hud-top {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.brand-link {
pointer-events: auto;
color: var(--primary-color);
text-decoration: none;
font-size: 0.8rem;
opacity: 0.7;
transition: opacity 0.3s;
text-shadow: 0 0 10px var(--primary-color);
}
.brand-link:hover {
opacity: 1;
text-shadow: 0 0 20px var(--primary-color);
}
.score-board {
text-align: right;
text-shadow: 0 0 10px rgba(255,255,255,0.5);
}
.score-label {
font-size: 0.8rem;
color: #aaa;
letter-spacing: 2px;
}
.score-value {
font-size: 2.5rem;
font-weight: 900;
color: white;
}
/* --- Health Bar --- */
.health-container {
position: absolute;
bottom: 30px;
left: 30px;
width: 300px;
pointer-events: auto;
}
.health-label {
margin-bottom: 5px;
font-size: 0.9rem;
color: var(--danger-color);
text-transform: uppercase;
letter-spacing: 1px;
}
.health-bar-bg {
width: 100%;
height: 10px;
background: rgba(255, 255, 255, 0.1);
border-radius: 5px;
overflow: hidden;
border: 1px solid var(--glass-border);
}
.health-bar-fill {
height: 100%;
width: 100%;
background: linear-gradient(90deg, var(--danger-color), #ff8c00);
box-shadow: 0 0 15px var(--danger-color);
transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
/* --- Screens (Start / Game Over) --- */
.screen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: rgba(5, 5, 5, 0.6);
backdrop-filter: blur(10px);
z-index: 20;
pointer-events: auto;
transition: opacity 0.5s ease;
}
.hidden {
opacity: 0;
pointer-events: none;
}
h1 {
font-size: 4rem;
text-transform: uppercase;
background: linear-gradient(to bottom, #fff, var(--primary-color));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 10px;
text-shadow: 0 0 30px rgba(0, 243, 255, 0.5);
text-align: center;
}
h2 {
font-size: 2.5rem;
color: var(--danger-color);
margin-bottom: 20px;
text-shadow: 0 0 20px var(--danger-color);
}
p.instructions {
margin-bottom: 40px;
color: #ddd;
font-size: 1.1rem;
line-height: 1.6;
text-align: center;
max-width: 600px;
}
.key {
display: inline-block;
padding: 5px 10px;
border: 1px solid var(--primary-color);
border-radius: 4px;
color: var(--primary-color);
font-size: 0.8rem;
margin: 0 5px;
box-shadow: 0 0 5px var(--primary-color);
}
/* --- Buttons --- */
.btn {
background: transparent;
color: white;
font-family: 'Orbitron', sans-serif;
font-size: 1.2rem;
font-weight: bold;
padding: 15px 50px;
border: 2px solid var(--primary-color);
border-radius: 50px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 2px;
box-shadow: 0 0 15px rgba(0, 243, 255, 0.2);
}
.btn:hover {
background: var(--primary-color);
color: black;
box-shadow: 0 0 40px rgba(0, 243, 255, 0.8);
transform: scale(1.05);
}
.btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent);
transition: 0.5s;
}
.btn:hover::before {
left: 100%;
}
/* --- Mobile Controls --- */
.mobile-controls {
display: none; /* Shown via JS on touch devices */
position: absolute;
bottom: 20px;
width: 100%;
justify-content: space-between;
padding: 0 20px;
pointer-events: none;
}
.control-zone {
width: 120px;
height: 120px;
border: 2px solid rgba(255,255,255,0.2);
border-radius: 50%;
pointer-events: auto;
display: flex;
justify-content: center;
align-items: center;
color: rgba(255,255,255,0.5);
font-size: 1.5rem;
backdrop-filter: blur(4px);
}
.control-zone:active {
background: rgba(255,255,255,0.1);
border-color: var(--primary-color);
color: var(--primary-color);
}
@media (max-width: 768px) {
h1 { font-size: 2.5rem; }
.score-value { font-size: 1.8rem; }
.health-container { width: 200px; bottom: 160px; }
.mobile-controls { display: flex; }
.instructions { font-size: 0.9rem; padding: 0 20px; }
}
</style>
</head>
<body>
<!-- Canvas for 3D Rendering -->
<canvas id="gameCanvas"></canvas>
<!-- UI Overlay -->
<div id="ui-layer">
<div class="hud-top">
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="brand-link">
Built with anycoder <i class="fas fa-external-link-alt"></i>
</a>
<div class="score-board">
<div class="score-label">SCORE</div>
<div class="score-value" id="scoreDisplay">0</div>
</div>
</div>
<div class="health-container">
<div class="health-label">Shield Integrity</div>
<div class="health-bar-bg">
<div class="health-bar-fill" id="healthFill"></div>
</div>
</div>
<div class="mobile-controls">
<div class="control-zone" id="btnLeft"><i class="fas fa-arrow-left"></i></div>
<div class="control-zone" id="btnRight"><i class="fas fa-arrow-right"></i></div>
</div>
</div>
<!-- Start Screen -->
<div id="startScreen" class="screen">
<h1>Neon Void</h1>
<p class="instructions">
Pilot your ship through the hyper-speed corridor.<br>
Avoid asteroids and destroy enemy drones.<br><br>
<span class="key"></span> <span class="key"></span> to Move<br>
<span class="key">SPACE</span> or <span class="key">CLICK</span> to Shoot
</p>
<button class="btn" id="startBtn">Initiate Launch</button>
</div>
<!-- Game Over Screen -->
<div id="gameOverScreen" class="screen hidden">
<h2>CRITICAL FAILURE</h2>
<p class="instructions">Final Score: <span id="finalScore" style="color:var(--primary-color); font-weight:bold;">0</span></p>
<button class="btn" id="restartBtn">Reboot System</button>
</div>
<script>
/**
* 3D Space Shooter Logic
* Uses HTML5 Canvas for pseudo-3D rendering.
*/
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d', { alpha: false }); // Optimize for no transparency on bg
// UI Elements
const scoreEl = document.getElementById('scoreDisplay');
const finalScoreEl = document.getElementById('finalScore');
const healthFillEl = document.getElementById('healthFill');
const startScreen = document.getElementById('startScreen');
const gameOverScreen = document.getElementById('gameOverScreen');
const startBtn = document.getElementById('startBtn');
const restartBtn = document.getElementById('restartBtn');
const btnLeft = document.getElementById('btnLeft');
const btnRight = document.getElementById('btnRight');
// Game State
let isPlaying = false;
let score = 0;
let health = 100;
let frameCount = 0;
let speed = 15; // Base speed
let speedMultiplier = 1;
// Input State
const keys = { ArrowLeft: false, ArrowRight: false, Space: false };
let touchInput = 0; // -1 left, 1 right, 0 none
// Dimensions
let width, height, cx, cy;
function resize() {
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
cx = width / 2;
cy = height / 2;
}
window.addEventListener('resize', resize);
resize();
// --- Classes ---
// 1. Starfield (Speed Effect)
class Star {
constructor() {
this.init();
}
init() {
this.x = (Math.random() - 0.5) * width * 2; // Spread wide
this.y = (Math.random() - 0.5) * height * 2;
this.z = Math.random() * 2000 + 500; // Depth
this.pz = this.z; // Previous z for trail effect
}
update(currentSpeed) {
this.z -= currentSpeed;
if (this.z <= 1) {
this.init();
this.z = 2000;
this.pz = 2000;
}
}
draw() {
// Perspective projection
const sx = (this.x / this.z) * width + cx;
const sy = (this.y / this.z) * height + cy;
// Previous position for trail (Speed Lines)
const px = (this.x / this.pz) * width + cx;
const py = (this.y / this.pz) * height + cy;
this.pz = this.z;
// Size based on proximity
const size = (1 - this.z / 2000) * 3;
const alpha = (1 - this.z / 2000);
ctx.beginPath();
ctx.moveTo(px, py);
ctx.lineTo(sx, sy);
ctx.strokeStyle = `rgba(200, 240, 255, ${alpha})`;
ctx.lineWidth = size;
ctx.stroke();
}
}
// 2. Player Ship
class Player {
constructor() {
this.x = 0; // Horizontal position (-1 to 1 range)
this.y = 0.8; // Vertical fixed (near bottom)
this.width = 0.15; // Relative width
this.color = '#00f3ff';
this.bullets = [];
this.cooldown = 0;
}
update() {
// Movement smoothing
if (keys.ArrowLeft || touchInput === -1) this.x -= 0.04;
if (keys.ArrowRight || touchInput === 1) this.x += 0.04;
// Clamp
if (this.x < -1) this.x = -1;
if (this.x > 1) this.x = 1;
// Shooting
if (this.cooldown > 0) this.cooldown--;
if ((keys.Space || touchInput === 2) && this.cooldown <= 0) {
this.shoot();
this.cooldown = 10; // Fire rate
}
// Update Bullets
for (let i = this.bullets.length - 1; i >= 0; i--) {
let b = this.bullets[i];
b.z -= speed * 2.5; // Bullets faster than ship
if (b.z < 0) this.bullets.splice(i, 1);
}
}
shoot() {
// Dual guns
this.bullets.push({ x: this.x - 0.05, y: this.y, z: 100 });
this.bullets.push({ x: this.x + 0.05, y: this.y, z: 100 });
}
draw() {
// Draw Bullets
ctx.shadowBlur = 10;
ctx.shadowColor = this.color;
ctx.fillStyle = '#fff';
this.bullets.forEach(b => {
const sx = (b.x / b.z) * width + cx;
const sy = (b.y / b.z) * height + cy; // Note: y is inverted in 3D usually, but simplified here
// Adjust perspective y to be relative to center
const screenY = height - (b.y * height * 0.5); // Rough approximation for gameplay feel
// Better projection for gameplay objects
const projX = (b.x * width * 0.8) + cx;
const projY = height * 0.8; // Shoot from bottom plane
// Scale bullet size
const scale = 500 / b.z;
if(scale > 0) {
ctx.beginPath();
ctx.arc(projX, projY - (b.z * 0.5), 3 * scale, 0, Math.PI * 2);
ctx.fill();
}
});
// Draw Ship (Simple 3D wireframe-ish look)
const shipX = this.x * width * 0.4 + cx;
const shipY = height * 0.85;
const size = 40;
ctx.shadowBlur = 20;
ctx.shadowColor = this.color;
ctx.strokeStyle = this.color;
ctx.lineWidth = 2;
// Main body triangle
ctx.beginPath();
ctx.moveTo(shipX, shipY - size);
ctx.lineTo(shipX - size, shipY + size);
ctx.lineTo(shipX, shipY + size * 0.7); // Engine indent
ctx.lineTo(shipX + size, shipY + size);
ctx.closePath();
ctx.stroke();
// Engine glow
ctx.fillStyle = `rgba(0, 243, 255, ${Math.random() * 0.5 + 0.5})`;
ctx.beginPath();
ctx.moveTo(shipX - size * 0.5, shipY + size * 0.8);
ctx.lineTo(shipX, shipY + size * 1.5 + Math.random() * 20);
ctx.lineTo(shipX + size * 0.5, shipY + size * 0.8);
ctx.fill();
ctx.shadowBlur = 0;
}
}
// 3. Enemies & Obstacles
class Object3D {
constructor(type) {
this.type = type; // 'asteroid' or 'enemy'
this.x = (Math.random() - 0.5) * 2.5; // Random X
this.y = (Math.random() - 0.5) * 1; // Random Y spread
this.z = 2000;
this.active = true;
this.rotation = Math.random() * Math.PI;
this.rotSpeed = (Math.random() - 0.5) * 0.1;
this.size = Math.random() * 0.5 + 0.5;
}
update() {
this.z -= speed;
this.rotation += this.rotSpeed;
if (this.z < 10) {
this.active = false;
// If it passes player, maybe damage?
if (Math.abs(this.x - player.x) < 0.3 && this.type === 'asteroid') {
takeDamage(10);
createExplosion(0, 0, 0, 'red'); // Screen shake effect essentially
}
}
}
draw() {
const scale = 500 / this.z;
const screenX = (this.x * width * 0.8) + cx;
const screenY = cy + (this.y * height * 0.5); // Center projection
ctx.save();
ctx.translate(screenX, screenY);
ctx.scale(scale * this.size, scale * this.size);
ctx.rotate(this.rotation);
if (this.type === 'asteroid') {
ctx.strokeStyle = '#888';
ctx.fillStyle = '#111';
ctx.lineWidth = 2;
ctx.beginPath();
// Draw a rough polygon
for(let i=0; i<6; i++) {
const angle = (i / 6) * Math.PI * 2;
const r = 30 + Math.sin(i * 3) * 10;
const px = Math.cos(angle) * r;
const py = Math.sin(angle) * r;
if(i===0) ctx.moveTo(px, py);
else ctx.lineTo(px, py);
}
ctx.closePath();
ctx.fill();
ctx.stroke();
} else if (this.type === 'enemy') {
ctx.shadowBlur = 15;
ctx.shadowColor = '#bc13fe';
ctx.fillStyle = '#bc13fe';
// Drone shape
ctx.beginPath();
ctx.moveTo(0, -30);
ctx.lineTo(20, 10);
ctx.lineTo(0, 0);
ctx.lineTo(-20, 10);
ctx.closePath();
ctx.fill();
// Core
ctx.fillStyle = '#fff';
ctx.beginPath();
ctx.arc(0, 0, 5, 0, Math.PI*2);
ctx.fill();
ctx.shadowBlur = 0;
}
ctx.restore();
}
}
// 4. Particles (Explosions)
class Particle {
constructor(x, y, color) {
this.x = x;
this.y = y;
this.vx = (Math.random() - 0.5) * 10;
this.vy = (Math.random() - 0.5) * 10;
this.life = 1.0;
this.color = color;
this.size = Math.random() * 5 + 2;
}
update() {
this.x += this.vx;
this.y += this.vy;
this.life -= 0.03;
this.size *= 0.95;
}
draw() {
ctx.globalAlpha = this.life;
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
ctx.globalAlpha = 1.0;
}
}
// --- Game Logic Setup ---
const stars = Array.from({ length: 300 }, () => new Star());
let player = new Player();
let objects = [];
let particles = [];
let animationId;
function createExplosion(x, y, color) {
for(let i=0; i<15; i++) {
particles.push(new Particle(x, y, color));
}
}
function takeDamage(amount) {
health -= amount;
healthFillEl.style.width = `${health}%`;
// Screen shake effect
canvas.style.transform = `translate(${Math.random()*20-10}px, ${Math.random()*20-10}px)`;
setTimeout(() => canvas.style.transform = 'none', 50);
if (health <= 0) {
endGame();
}
}
function spawnObject() {
// Difficulty curve
const spawnRate = Math.max(20, 60 - Math.floor(score / 500));
if (frameCount % spawnRate === 0) {
const type = Math.random() > 0.7 ? 'enemy' : 'asteroid';
objects.push(new Object3D(type));
}
}
function checkCollisions() {
objects.forEach(obj => {
if (!obj.active) return;
// Bullet Collision
player.bullets.forEach((b, bIndex) => {
if (b.z < obj.z + 50 && b.z > obj.z - 50) {
// Check X distance roughly
// Map bullet relative X (-1 to 1) to Object X range
// Simplified 3D distance check
const dx = b.x - obj.x;
const dy = (player.y - 0.5) - obj.y; // Adjust for player plane
if (Math.sqrt(dx*dx + dy*dy) < 0.3) {
// Hit
obj.active = false;
player.bullets.splice(bIndex, 1);
// Visuals
const sx = (obj.x * width * 0.8) + cx;
const sy = cy + (obj.y * height * 0.5);
createExplosion(sx, sy, obj.type === 'enemy' ? '#bc13fe' : '#aaa');
// Score
if (obj.type === 'enemy') {
score += 200;
scoreEl.innerText = score;
} else {
score += 50;
scoreEl.innerText = score;
}
}
}
});
// Player Collision (Direct hit)
if (obj.z < 150 && obj.z > 50) {
const dx = player.x - obj.x;
if (Math.abs(dx) < 0.2) {
obj.active = false;
createExplosion(cx, height * 0.8, '#ff2a6d');
takeDamage(20);
}
}
});
}
function loop() {
if (!isPlaying) return;
// Clear Canvas
ctx.fillStyle = 'rgba(5, 5, 5, 0.4)'; // Trail effect for motion blur
ctx.fillRect(0, 0, width, height);
frameCount++;
// Increase speed gradually
speed = 15 + (score / 1000);
// Update Stars
stars.forEach(star => {
star.update(speed);
star.draw();
});
// Update Player
player.update();
player.draw();
// Update Objects
objects = objects.filter(obj => obj.active);
objects.forEach(obj => {
obj.update();
obj.draw();
});
// Update Particles
particles = particles.filter(p => p.life > 0);
particles.forEach(p => {
p.update();
p.draw();
});
spawnObject();
checkCollisions();
animationId = requestAnimationFrame(loop);
}
function startGame() {
isPlaying = true;
score = 0;
health = 100;
speed = 15;
objects = [];
particles = [];
player.bullets = [];
player.x = 0;
scoreEl.innerText = '0';
healthFillEl.style.width = '100%';
startScreen.classList.add('hidden');
gameOverScreen.classList.add('hidden');
loop();
}
function endGame() {
isPlaying = false;
cancelAnimationFrame(animationId);
finalScoreEl.innerText = score;
gameOverScreen.classList.remove('hidden');
}
// --- Event Listeners ---
window.addEventListener('keydown', e => {
if (e.code === 'ArrowLeft') keys.ArrowLeft = true;
if (e.code === 'ArrowRight') keys.ArrowRight = true;
if (e.code === 'Space') keys.Space = true;
});
window.addEventListener('keyup', e => {
if (e.code === 'ArrowLeft') keys.ArrowLeft = false;
if (e.code === 'ArrowRight') keys.ArrowRight = false;
if (e.code === 'Space') keys.Space = false;
});
// Mouse/Touch Drag for movement
window.addEventListener('mousedown', () => keys.Space = true);
window.addEventListener('mouseup', () => keys.Space = false);
// Touch Logic for Mobile
btnLeft.addEventListener('touchstart', (e) => { e.preventDefault(); touchInput = -1; });
btnLeft.addEventListener('touchend', (e) => { e.preventDefault(); touchInput = 0; });
btnRight.addEventListener('touchstart', (e) => { e.preventDefault(); touchInput = 1; });
btnRight.addEventListener('touchend', (e) => { e.preventDefault(); touchInput = 0; });
// Tap center to shoot on mobile (simplified)
canvas.addEventListener('touchstart', (e) => {
if(e.touches.length > 0) {
const t = e.touches[0];
if(t.clientX > width * 0.3 && t.clientX < width * 0.7) {
touchInput = 2; // Shoot code
}
}
});
canvas.addEventListener('touchend', (e) => {
touchInput = 0;
});
startBtn.addEventListener('click', startGame);
restartBtn.addEventListener('click', startGame);
// Initial render for background
ctx.fillStyle = '#050505';
ctx.fillRect(0, 0, width, height);
stars.forEach(star => star.draw());
</script>
</body>
</html>