aleste2-deepsite / index.html
af2022's picture
Update index.html
bdc0272 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Aleste 2 Clone</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000;
font-family: 'Courier New', monospace;
}
canvas {
display: block;
width: 100vw;
height: 100vh;
}
#ui {
position: absolute;
top: 10px;
left: 10px;
color: #00FFFF;
font-size: 18px;
text-shadow: 0 0 10px #00FFFF, 0 0 20px #0066FF;
background: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 5px;
border: 1px solid #00FFFF;
}
#gameOver {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #FF0000;
font-size: 48px;
text-align: center;
text-shadow: 0 0 10px #FF0000, 0 0 20px #990000;
display: none;
background: rgba(0, 0, 0, 0.7);
padding: 20px 40px;
border-radius: 10px;
border: 2px solid #FF0000;
}
#loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #00FFFF;
font-size: 24px;
text-align: center;
text-shadow: 0 0 10px #00FFFF;
background: rgba(0, 0, 0, 0.7);
padding: 20px;
border-radius: 10px;
border: 1px solid #00FFFF;
}
#musicControls {
position: absolute;
bottom: 20px;
right: 20px;
display: flex;
gap: 10px;
}
.music-btn {
background: rgba(0, 0, 0, 0.7);
color: #00FFFF;
border: 1px solid #00FFFF;
border-radius: 4px;
padding: 8px 12px;
cursor: pointer;
transition: all 0.3s;
text-shadow: 0 0 5px #00FFFF;
}
.music-btn:hover {
background: rgba(0, 255, 255, 0.3);
box-shadow: 0 0 10px #00FFFF;
}
#powerBar {
position: absolute;
bottom: 20px;
left: 20px;
width: 200px;
height: 20px;
background: rgba(0, 0, 0, 0.5);
border: 1px solid #00FFFF;
border-radius: 3px;
overflow: hidden;
}
#powerFill {
height: 100%;
width: 0%;
background: linear-gradient(90deg, #00FFFF, #0066FF);
transition: width 0.3s;
}
#powerLabel {
position: absolute;
top: -20px;
left: 0;
color: #00FFFF;
font-size: 14px;
}
.glow {
text-shadow: 0 0 5px currentColor;
}
@keyframes pulse {
0% { opacity: 0.7; }
50% { opacity: 1; }
100% { opacity: 0.7; }
}
.pulse {
animation: pulse 2s infinite;
}
</style>
</head>
<body>
<div id="ui">
<div>SCORE: <span id="score" class="glow">0</span></div>
<div>WEAPON: <span id="weapon" class="glow">NORMAL</span></div>
<div>FPS: <span id="fps" class="glow">0</span></div>
</div>
<div id="powerBar">
<div id="powerLabel">POWER</div>
<div id="powerFill"></div>
</div>
<div id="gameOver">
GAME OVER<br>
<span style="font-size: 24px;">Press R to restart</span>
</div>
<div id="loading" class="pulse">
<div>Loading game assets...</div>
<div style="font-size: 14px; margin-top: 10px;">Aleste 2 Clone</div>
</div>
<div id="musicControls">
<button id="playMusic" class="music-btn">▶ Play Music</button>
<button id="stopMusic" class="music-btn">■ Stop Music</button>
</div>
<canvas id="gameCanvas"></canvas>
<audio id="bgMusic" loop>
<source src="https://www.msx.org/sites/default/files/downloads/music/mp3/Meits_Aleste2Area1.mp3" type="audio/mpeg">
</audio>
<script>
// Game constants
const PLAYER_SIZE = 20;
const PROJECTILE_WIDTH = 4;
const PROJECTILE_HEIGHT = 12;
const ENEMY_SIZE = 24;
const SCROLL_SPEED = 2;
const BG_LINE_SPACING = 40;
// Game state
let gameRunning = true;
let score = 0;
let weaponType = 'normal'; // 'normal' or 'power'
let powerLevel = 0;
let assetsLoaded = false;
let lastTime = 0;
let fps = 0;
let frameCount = 0;
let lastFpsUpdate = 0;
// Canvas setup
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Audio elements
const bgMusic = document.getElementById('bgMusic');
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
// Player object
const player = {
x: canvas.width / 2,
y: canvas.height - 60,
width: PLAYER_SIZE,
height: PLAYER_SIZE,
speed: 5,
color: '#00FFFF',
projectiles: [],
shootCooldown: 0,
update: function() {
// Movement
if (keys.ArrowLeft && this.x > 0) this.x -= this.speed;
if (keys.ArrowRight && this.x < canvas.width - this.width) this.x += this.speed;
if (keys.ArrowUp && this.y > 0) this.y -= this.speed;
if (keys.ArrowDown && this.y < canvas.height - this.height) this.y += this.speed;
// Shooting cooldown
if (this.shootCooldown > 0) this.shootCooldown--;
// Shoot when space is pressed and cooldown is 0
if (keys[' '] && this.shootCooldown === 0) {
this.shoot();
this.shootCooldown = weaponType === 'normal' ? 10 : 20;
// Increase power level when shooting
if (powerLevel < 100) {
powerLevel += 1;
document.getElementById('powerFill').style.width = powerLevel + '%';
// Check if weapon should upgrade
if (powerLevel >= 100 && weaponType === 'normal') {
weaponType = 'power';
document.getElementById('weapon').textContent = 'POWER';
playSound('powerUp');
}
}
}
// Update projectiles
for (let i = this.projectiles.length - 1; i >= 0; i--) {
this.projectiles[i].update();
// Remove projectiles that are off screen
if (this.projectiles[i].y + this.projectiles[i].height < 0) {
this.projectiles.splice(i, 1);
}
}
},
shoot: function() {
playSound('shoot');
const projectile = {
x: this.x + this.width / 2 - PROJECTILE_WIDTH / 2,
y: this.y,
width: PROJECTILE_WIDTH,
height: PROJECTILE_HEIGHT,
speed: weaponType === 'normal' ? 10 : 5,
damage: weaponType === 'normal' ? 1 : 3,
color: weaponType === 'normal' ? '#FF0000' : '#FFFF00',
update: function() {
this.y -= this.speed;
},
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
// Add a glow effect for power shots
if (weaponType === 'power') {
ctx.fillStyle = 'rgba(255, 255, 0, 0.3)';
ctx.fillRect(this.x - 2, this.y - 2, this.width + 4, this.height + 4);
}
}
};
this.projectiles.push(projectile);
// Add additional projectiles for power weapon
if (weaponType === 'power') {
const leftProjectile = {...projectile};
leftProjectile.x -= 15;
this.projectiles.push(leftProjectile);
const rightProjectile = {...projectile};
rightProjectile.x += 15;
this.projectiles.push(rightProjectile);
}
},
draw: function() {
// Draw ship body
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
// Draw ship details
ctx.fillStyle = '#FFFFFF';
ctx.fillRect(this.x + 5, this.y + 5, 2, 2);
ctx.fillRect(this.x + this.width - 7, this.y + 5, 2, 2);
// Draw engine glow
const gradient = ctx.createLinearGradient(
this.x + 5, this.y + this.height,
this.x + this.width - 5, this.y + this.height
);
gradient.addColorStop(0, 'rgba(0, 255, 255, 0)');
gradient.addColorStop(0.5, 'rgba(0, 255, 255, 0.8)');
gradient.addColorStop(1, 'rgba(0, 255, 255, 0)');
ctx.fillStyle = gradient;
ctx.fillRect(this.x + 5, this.y + this.height, this.width - 10, 10);
// Draw projectiles
this.projectiles.forEach(projectile => projectile.draw());
}
};
// Enemies array
let enemies = [];
// Enemy spawner
function spawnEnemy() {
const enemyTypes = [
{ health: 1, speed: 1 + Math.random() * 3, color: `hsl(${Math.random() * 60 + 300}, 70%, 50%)` },
{ health: 2, speed: 0.5 + Math.random() * 2, color: `hsl(${Math.random() * 60 + 180}, 70%, 50%)` },
{ health: 3, speed: 0.3 + Math.random() * 1.5, color: `hsl(${Math.random() * 60 + 60}, 70%, 50%)` }
];
const type = enemyTypes[Math.floor(Math.random() * enemyTypes.length)];
const enemy = {
x: Math.random() * (canvas.width - ENEMY_SIZE),
y: -ENEMY_SIZE,
width: ENEMY_SIZE,
height: ENEMY_SIZE,
speed: type.speed,
health: type.health,
color: type.color,
hitFlash: 0,
update: function() {
this.y += this.speed;
// Reduce hit flash timer
if (this.hitFlash > 0) {
this.hitFlash--;
}
// Check collision with player
if (checkCollision(this, player)) {
gameOver();
}
// Check collision with projectiles
for (let i = player.projectiles.length - 1; i >= 0; i--) {
if (checkCollision(this, player.projectiles[i])) {
this.health -= player.projectiles[i].damage;
player.projectiles.splice(i, 1);
this.hitFlash = 5;
playSound('hit');
if (this.health <= 0) {
score += 10 * type.health;
document.getElementById('score').textContent = score;
return false; // Mark for removal
}
}
}
return true; // Keep enemy
},
draw: function() {
// Draw enemy body with flash effect if hit
const flashColor = this.hitFlash > 0 ? '#FFFFFF' : this.color;
ctx.fillStyle = flashColor;
ctx.fillRect(this.x, this.y, this.width, this.height);
// Draw enemy details
ctx.fillStyle = '#000000';
ctx.fillRect(this.x + 8, this.y + 8, 8, 8);
// Draw health indicator for tougher enemies
if (type.health > 1) {
ctx.fillStyle = '#FFFFFF';
ctx.font = '10px Courier New';
ctx.fillText(`${this.health}`, this.x + 12, this.y + 15);
}
}
};
enemies.push(enemy);
}
// Background state
let bgOffset = 0;
// Input handling
const keys = {};
document.addEventListener('keydown', e => {
keys[e.key] = true;
// Toggle weapon with Q
if (e.key === 'q' && powerLevel >= 100) {
weaponType = weaponType === 'normal' ? 'power' : 'normal';
document.getElementById('weapon').textContent = weaponType.toUpperCase();
playSound('weaponSwitch');
}
// Restart game with R when game over
if (!gameRunning && e.key.toLowerCase() === 'r') {
resetGame();
}
});
document.addEventListener('keyup', e => {
keys[e.key] = false;
});
// Collision detection
function checkCollision(obj1, obj2) {
return obj1.x < obj2.x + obj2.width &&
obj1.x + obj1.width > obj2.x &&
obj1.y < obj2.y + obj2.height &&
obj1.y + obj1.height > obj2.y;
}
// Game over function
function gameOver() {
gameRunning = false;
document.getElementById('gameOver').style.display = 'block';
playSound('gameOver');
bgMusic.pause();
}
// Reset game function
function resetGame() {
gameRunning = true;
score = 0;
powerLevel = 0;
weaponType = 'normal';
player.x = canvas.width / 2;
player.y = canvas.height - 60;
player.projectiles = [];
enemies = [];
document.getElementById('score').textContent = '0';
document.getElementById('weapon').textContent = 'NORMAL';
document.getElementById('powerFill').style.width = '0%';
document.getElementById('gameOver').style.display = 'none';
// Start music again
bgMusic.currentTime = 0;
bgMusic.play();
// Spawn initial enemies
for (let i = 0; i < 5; i++) {
setTimeout(spawnEnemy, i * 1000);
}
}
// Sound effects
function playSound(type) {
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
switch (type) {
case 'shoot':
oscillator.type = 'square';
oscillator.frequency.value = 880;
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.1);
oscillator.start();
oscillator.stop(audioContext.currentTime + 0.1);
break;
case 'hit':
oscillator.type = 'sine';
oscillator.frequency.setValueAtTime(440, audioContext.currentTime);
oscillator.frequency.exponentialRampToValueAtTime(110, audioContext.currentTime + 0.2);
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.2);
oscillator.start();
oscillator.stop(audioContext.currentTime + 0.2);
break;
case 'gameOver':
oscillator.type = 'sawtooth';
oscillator.frequency.value = 110;
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.5);
oscillator.start();
oscillator.stop(audioContext.currentTime + 0.5);
break;
case 'powerUp':
oscillator.type = 'sine';
oscillator.frequency.setValueAtTime(220, audioContext.currentTime);
oscillator.frequency.exponentialRampToValueAtTime(880, audioContext.currentTime + 0.3);
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.3);
oscillator.start();
oscillator.stop(audioContext.currentTime + 0.3);
break;
case 'weaponSwitch':
oscillator.type = 'square';
oscillator.frequency.setValueAtTime(440, audioContext.currentTime);
oscillator.frequency.exponentialRampToValueAtTime(880, audioContext.currentTime + 0.1);
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.1);
oscillator.start();
oscillator.stop(audioContext.currentTime + 0.1);
break;
}
}
// Handle window resize
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
// Music control functions
function playMusic() {
bgMusic.play().catch(e => {
console.error("Audio playback failed:", e);
// Show a message to the user that they need to interact first
document.getElementById('loading').textContent = "Click anywhere to start music";
document.addEventListener('click', () => {
bgMusic.play();
document.getElementById('loading').style.display = 'none';
assetsLoaded = true;
}, { once: true });
});
}
function stopMusic() {
bgMusic.pause();
}
// Setup music controls
document.getElementById('playMusic').addEventListener('click', playMusic);
document.getElementById('stopMusic').addEventListener('click', stopMusic);
// Game loop
function gameLoop(timestamp) {
if (!gameRunning || !assetsLoaded) {
requestAnimationFrame(gameLoop);
return;
}
// Calculate delta time and FPS
const deltaTime = timestamp - lastTime;
lastTime = timestamp;
if (deltaTime > 0) {
fps = 1000 / deltaTime;
frameCount++;
// Update FPS display every second
if (timestamp - lastFpsUpdate > 1000) {
document.getElementById('fps').textContent = Math.round(fps);
lastFpsUpdate = timestamp;
frameCount = 0;
}
}
// Clear canvas
ctx.fillStyle = '#000033';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw scrolling background
ctx.strokeStyle = '#0066FF';
ctx.lineWidth = 2;
bgOffset += SCROLL_SPEED;
if (bgOffset >= BG_LINE_SPACING) {
bgOffset = 0;
}
for (let y = -BG_LINE_SPACING + bgOffset; y < canvas.height; y += BG_LINE_SPACING) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(canvas.width, y);
ctx.stroke();
}
// Draw starfield background
for (let i = 0; i < 100; i++) {
const x = (i * 12345) % canvas.width;
const y = (i * 9876 + timestamp / 50) % canvas.height;
const size = (i % 3) + 1;
const opacity = 0.5 + (i % 10) / 20;
ctx.fillStyle = `rgba(255, 255, 255, ${opacity})`;
ctx.fillRect(x, y, size, size);
}
// Update and draw player
player.update();
player.draw();
// Update and draw enemies
for (let i = enemies.length - 1; i >= 0; i--) {
if (!enemies[i].update()) {
enemies.splice(i, 1);
} else {
enemies[i].draw();
}
}
// Spawn new enemies occasionally
if (Math.random() < 0.02) {
spawnEnemy();
}
// Gradually decrease power level when not shooting
if (powerLevel > 0 && !keys[' ']) {
powerLevel -= 0.2;
document.getElementById('powerFill').style.width = powerLevel + '%';
// Check if weapon should downgrade
if (powerLevel <= 0 && weaponType === 'power') {
weaponType = 'normal';
document.getElementById('weapon').textContent = 'NORMAL';
}
}
requestAnimationFrame(gameLoop);
}
// Initialize the game
function initGame() {
// Hide loading screen and start game
document.getElementById('loading').style.display = 'none';
assetsLoaded = true;
// Start music
playMusic();
// Spawn initial enemies
for (let i = 0; i < 5; i++) {
setTimeout(spawnEnemy, i * 1000);
}
// Start game loop
requestAnimationFrame(gameLoop);
}
// Start the initialization process
document.addEventListener('DOMContentLoaded', () => {
// Modern browsers require user interaction before playing audio
document.addEventListener('click', () => {
initGame();
}, { once: true });
document.getElementById('loading').textContent = "Click anywhere to start game";
});
</script>
</body>
</html>