Update Lobby

This commit is contained in:
Hijau-dev 2025-12-16 08:31:21 +07:00
parent e71b5a73bb
commit 9a0eda6bb8
3 changed files with 780 additions and 98 deletions

View File

@ -6,11 +6,73 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Space Game</title>
<link rel="stylesheet" href="Style.css">
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&display=swap" rel="stylesheet">
</head>
<body>
<div id="game">
<!-- MAIN MENU -->
<div id="mainMenu">
<div class="menu-content">
<h1 class="game-title">
<span class="title-word">SPACE</span>
<span class="title-word">SHOOTER</span>
</h1>
<div class="menu-buttons">
<button class="menu-btn" id="startBtn">
<span class="btn-icon"></span>
<span class="btn-text">START GAME</span>
</button>
<button class="menu-btn" id="optionBtn">
<span class="btn-icon"></span>
<span class="btn-text">OPTIONS</span>
</button>
<button class="menu-btn" id="exitBtn">
<span class="btn-icon"></span>
<span class="btn-text">EXIT</span>
</button>
</div>
<div class="footer-info">
<p>WASD - Move | Space - Fire | Q - Missile | Shift - Bomb | P - Pause</p>
</div>
</div>
</div>
<!-- OPTIONS MENU -->
<div id="optionsMenu" style="display: none;">
<div class="menu-content">
<h2 class="options-title">OPTIONS</h2>
<div class="options-container">
<div class="option-item">
<label>Music</label>
<div class="button-group">
<button class="toggle-btn active" data-music="on">ENABLE</button>
<button class="toggle-btn" data-music="off">DISABLE</button>
</div>
</div>
<div class="option-item">
<label>Sound Effects</label>
<div class="button-group">
<button class="toggle-btn active" data-sfx="on">ENABLE</button>
<button class="toggle-btn" data-sfx="off">DISABLE</button>
</div>
</div>
</div>
<button class="menu-btn back-btn" id="backBtn">
<span class="btn-icon"></span>
<span class="btn-text">BACK</span>
</button>
</div>
</div>
<!-- GAME CANVAS (Hidden initially) -->
<div id="gameContainer" style="display: none;">
<canvas id="canvas"></canvas>
</div>

340
Script.js
View File

@ -1533,3 +1533,343 @@ function crossfadeToGameOver() {
}
}, 1000 / 30);
}
// === GAME SETTINGS ===
const gameSettings = {
musicEnabled: true,
sfxEnabled: true
};
// === DOM ELEMENTS ===
const mainMenu = document.getElementById('mainMenu');
const optionsMenu = document.getElementById('optionsMenu');
const gameContainer = document.getElementById('gameContainer');
const startBtn = document.getElementById('startBtn');
const optionBtn = document.getElementById('optionBtn');
const exitBtn = document.getElementById('exitBtn');
const backBtn = document.getElementById('backBtn');
// Toggle Buttons
const musicBtns = document.querySelectorAll('[data-music]');
const sfxBtns = document.querySelectorAll('[data-sfx]');
// === MENU SOUNDS ===
const menuHoverSound = new Audio();
menuHoverSound.src = 'data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQAAAAA=';
const menuClickSound = new Audio();
menuClickSound.src = 'data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQAAAAA=';
// === PREVENT DEFAULT GAME START ===
window.addEventListener('DOMContentLoaded', () => {
gameStarted = false;
});
// === START BUTTON ===
startBtn.addEventListener('click', () => {
playSound(menuClickSound);
// Apply settings to game
applySettings();
// Hide menu, show game
mainMenu.style.display = 'none';
gameContainer.style.display = 'block';
// Start the game
if (!gameStarted) {
init();
}
});
// === OPTION BUTTON ===
optionBtn.addEventListener('click', () => {
playSound(menuClickSound);
mainMenu.style.display = 'none';
optionsMenu.style.display = 'flex';
});
// === EXIT BUTTON ===
exitBtn.addEventListener('click', () => {
playSound(menuClickSound);
// Create exit confirmation
const confirmExit = document.createElement('div');
confirmExit.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.9);
border: 3px solid #00eaff;
border-radius: 20px;
padding: 50px 60px;
z-index: 1000;
text-align: center;
box-shadow: 0 0 40px rgba(0, 234, 255, 0.6);
backdrop-filter: blur(10px);
`;
confirmExit.innerHTML = `
<h3 style="
color: #00eaff;
font-size: 48px;
margin-bottom: 20px;
font-family: 'Orbitron', sans-serif;
font-weight: 900;
text-shadow:
2px 2px 0px #00bcd4,
4px 4px 0px #009bb0,
0 0 30px #00eaff;
letter-spacing: 3px;
">
EXIT GAME?
</h3>
<p style="
color: #ffffff;
margin-bottom: 40px;
font-size: 18px;
font-family: 'Orbitron', sans-serif;
opacity: 0.8;
">
Are you sure you want to leave?
</p>
<div style="display: flex; gap: 20px; justify-content: center;">
<button id="confirmYes" style="
padding: 15px 50px;
font-family: 'Orbitron', sans-serif;
font-size: 20px;
font-weight: 700;
background: linear-gradient(145deg, #111, #1b1b1b);
color: #ff3366;
border: 2px solid #ff3366;
border-radius: 40px;
cursor: pointer;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 2px;
box-shadow: 0 4px 0 #cc0033, 0 0 12px rgba(255, 51, 102, 0.4), inset 0 0 15px rgba(255, 51, 102, 0.1);
">YES</button>
<button id="confirmNo" style="
padding: 15px 50px;
font-family: 'Orbitron', sans-serif;
font-size: 20px;
font-weight: 700;
background: linear-gradient(145deg, #111, #1b1b1b);
color: #00eaff;
border: 2px solid #00eaff;
border-radius: 40px;
cursor: pointer;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 2px;
box-shadow: 0 4px 0 #00bcd4, 0 0 12px rgba(0, 234, 255, 0.4), inset 0 0 15px rgba(0, 234, 255, 0.2);
">NO</button>
</div>
`;
document.body.appendChild(confirmExit);
// YES button hover effect
const yesBtn = document.getElementById('confirmYes');
yesBtn.addEventListener('mouseenter', () => {
yesBtn.style.background = '#ff3366';
yesBtn.style.color = '#000';
yesBtn.style.transform = 'translateY(-5px) scale(1.08)';
yesBtn.style.boxShadow = '0 10px 20px rgba(255, 51, 102, 0.6), 0 0 30px #ff3366';
});
yesBtn.addEventListener('mouseleave', () => {
yesBtn.style.background = 'linear-gradient(145deg, #111, #1b1b1b)';
yesBtn.style.color = '#ff3366';
yesBtn.style.transform = 'translateY(0) scale(1)';
yesBtn.style.boxShadow = '0 4px 0 #cc0033, 0 0 12px rgba(255, 51, 102, 0.4), inset 0 0 15px rgba(255, 51, 102, 0.1)';
});
// NO button hover effect
const noBtn = document.getElementById('confirmNo');
noBtn.addEventListener('mouseenter', () => {
noBtn.style.background = '#00eaff';
noBtn.style.color = '#000';
noBtn.style.transform = 'translateY(-5px) scale(1.08)';
noBtn.style.boxShadow = '0 10px 20px rgba(0, 234, 255, 0.6), 0 0 30px #00eaff';
});
noBtn.addEventListener('mouseleave', () => {
noBtn.style.background = 'linear-gradient(145deg, #111, #1b1b1b)';
noBtn.style.color = '#00eaff';
noBtn.style.transform = 'translateY(0) scale(1)';
noBtn.style.boxShadow = '0 4px 0 #00bcd4, 0 0 12px rgba(0, 234, 255, 0.4), inset 0 0 15px rgba(0, 234, 255, 0.2)';
});
// Click handlers
yesBtn.addEventListener('click', () => {
window.close();
setTimeout(() => {
window.location.href = 'about:blank';
}, 100);
});
noBtn.addEventListener('click', () => {
playSound(menuClickSound);
document.body.removeChild(confirmExit);
});
});
// === BACK BUTTON ===
backBtn.addEventListener('click', () => {
playSound(menuClickSound);
optionsMenu.style.display = 'none';
mainMenu.style.display = 'flex';
});
// === MUSIC BUTTONS ===
musicBtns.forEach(btn => {
btn.addEventListener('click', () => {
playSound(menuClickSound);
// Remove active from all
musicBtns.forEach(b => b.classList.remove('active'));
// Add active to clicked
btn.classList.add('active');
// Update setting
gameSettings.musicEnabled = btn.dataset.music === 'on';
// Apply immediately if in game
if (typeof currentBGM !== 'undefined') {
if (gameSettings.musicEnabled) {
currentBGM.volume = 1;
if (!game.gameOver && gameStarted) {
currentBGM.play().catch(() => {});
}
} else {
currentBGM.volume = 0;
currentBGM.pause();
}
}
});
});
// === SFX BUTTONS ===
sfxBtns.forEach(btn => {
btn.addEventListener('click', () => {
playSound(menuClickSound);
// Remove active from all
sfxBtns.forEach(b => b.classList.remove('active'));
// Add active to clicked
btn.classList.add('active');
// Update setting
gameSettings.sfxEnabled = btn.dataset.sfx === 'on';
});
});
// === HOVER SOUNDS ===
document.querySelectorAll('.menu-btn, .toggle-btn').forEach(btn => {
btn.addEventListener('mouseenter', () => {
if (gameSettings.sfxEnabled) {
playSound(menuHoverSound);
}
});
});
// === APPLY SETTINGS TO GAME ===
function applySettings() {
// Apply music setting
if (typeof currentBGM !== 'undefined') {
if (gameSettings.musicEnabled) {
currentBGM.volume = 1;
} else {
currentBGM.volume = 0;
currentBGM.pause();
}
}
if (typeof gameOverBGM !== 'undefined') {
if (gameSettings.musicEnabled) {
gameOverBGM.volume = 1;
} else {
gameOverBGM.volume = 0;
}
}
}
// === PLAY SOUND HELPER ===
function playSound(audio) {
if (gameSettings.sfxEnabled) {
audio.volume = 0.3;
audio.currentTime = 0;
audio.play().catch(() => {});
}
}
// === KEYBOARD NAVIGATION ===
document.addEventListener('keydown', (e) => {
// ESC to go back
if (e.key === 'Escape') {
if (optionsMenu.style.display === 'flex') {
backBtn.click();
} else if (gameContainer.style.display === 'block' && typeof togglePause !== 'undefined') {
togglePause();
}
}
// Enter to start game from main menu
if (e.key === 'Enter' && mainMenu.style.display === 'flex') {
startBtn.click();
}
});
// === MODIFY EXISTING GAME FUNCTIONS ===
// Override window.onload
window.onload = function () {
console.log('Game Ready - Waiting for menu start...');
};
// Add return to menu function
function returnToMenu() {
currentBGM.pause();
gameOverBGM.pause();
currentBGM.currentTime = 0;
gameOverBGM.currentTime = 0;
game.gameOver = false;
game.frames = 0;
game.level = 1;
game.speed = 1;
game.surge = 1.0;
game.surgePhase = 0;
game.surgeTimer = 0;
game.surgeCooldown = 2400;
missilesArray = [];
playerMissilesArray = [];
enemyShipArray = [];
enemyBulletsArray = [];
explosions = [];
abilityTokens = [];
particles = [];
player1 = new PlayerObject(100, 300);
player1.lives = 6;
player1.score = 0;
respawnCounter = 0;
damageFlash = 0;
currentWave = null;
waveCooldown = 0;
abilityCharges = 0;
missileAmmo = 0;
cameraY = 0;
gameStarted = false;
gamePaused = false;
if (gameContainer) gameContainer.style.display = 'none';
if (mainMenu) mainMenu.style.display = 'flex';
}
console.log('Menu System Loaded');
console.log('Settings:', gameSettings);

472
Style.css
View File

@ -1,115 +1,395 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
background: radial-gradient(circle at center,
rgb(255, 255, 255) 0%,
rgb(255, 150, 50) 20%,
rgb(255, 40, 0) 35%,
rgb(110, 0, 150) 55%,
rgb(5, 10, 35) 100%
);
margin: 0;
padding: 0;
background-color: #000;
font-family: 'Orbitron', sans-serif;
}
html, body {
height: 100%;
overflow: hidden;
height: 100%;
overflow: hidden;
}
#game {
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
}
#canvas {
width: 100%;
height: 100%;
margin: 0;
background-color: black;
display: block;
}
#startMenu {
position: absolute;
width: 100vw;
height: 100vh;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(6px);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 10;
font-family: 'Poppins', Arial, sans-serif;
animation: fadeIn 1s ease-out;
/* === MAIN MENU & OPTIONS MENU === */
#mainMenu, #optionsMenu {
position: absolute;
width: 100vw;
height: 100vh;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(6px);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 10;
animation: fadeIn 1s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
from { opacity: 0; }
to { opacity: 1; }
}
.title {
font-size: 90px;
margin-bottom: 40px;
color: #ffffff;
letter-spacing: 4px;
font-weight: 900;
text-shadow:
2px 2px 0px #00bcd4,
4px 4px 0px #009bb0,
6px 6px 0px #007a8c,
8px 8px 0px #005a68,
10px 10px 12px rgba(0, 234, 255, 0.7),
0 0 25px #00eaff;
animation: pixelGlow 2s infinite alternate ease-in-out;
/* === STARS CONTAINER (hidden by default, no animation) === */
.stars-container {
display: none;
}
/* === MENU CONTENT === */
.menu-content {
text-align: center;
z-index: 11;
}
/* === GAME TITLE === */
.game-title {
display: flex;
flex-direction: column;
gap: 5px;
margin-bottom: 60px;
}
.title-word {
font-size: 90px;
color: #ffffff;
letter-spacing: 4px;
font-weight: 900;
text-shadow:
2px 2px 0px #00bcd4,
4px 4px 0px #009bb0,
6px 6px 0px #007a8c,
8px 8px 0px #005a68,
10px 10px 12px rgba(0, 234, 255, 0.7),
0 0 25px #00eaff;
animation: pixelGlow 2s infinite alternate ease-in-out;
}
@keyframes pixelGlow {
from {
text-shadow:
2px 2px 0px #00eaff,
4px 4px 0px #00bcd4,
6px 6px 0px #009bb0,
8px 8px 0px #007a8c,
10px 10px 14px rgba(0, 234, 255, 0.9),
0 0 35px #00eaff;
}
to {
text-shadow:
2px 2px 0px #00eaff,
3px 3px 0px #00bcd4,
5px 5px 0px #009bb0,
7px 7px 0px #007a8c,
9px 9px 12px rgba(0, 234, 255, 0.7),
0 0 20px #00eaff;
}
from {
text-shadow:
2px 2px 0px #00eaff,
4px 4px 0px #00bcd4,
6px 6px 0px #009bb0,
8px 8px 0px #007a8c,
10px 10px 14px rgba(0, 234, 255, 0.9),
0 0 35px #00eaff;
}
to {
text-shadow:
2px 2px 0px #00eaff,
3px 3px 0px #00bcd4,
5px 5px 0px #009bb0,
7px 7px 0px #007a8c,
9px 9px 12px rgba(0, 234, 255, 0.7),
0 0 20px #00eaff;
}
}
.menuButton {
font-size: 28px;
padding: 15px 55px;
margin: 12px;
cursor: pointer;
background: linear-gradient(145deg, #111, #1b1b1b);
color: white;
border: 2px solid #00eaff;
border-radius: 40px;
box-shadow:
0 4px 0 #00bcd4,
0 0 12px rgba(0, 234, 255, 0.4),
inset 0 0 15px rgba(0, 234, 255, 0.2);
transition: 0.3s ease-in-out;
/* === MENU BUTTONS CONTAINER === */
.menu-buttons {
display: flex;
flex-direction: column;
gap: 15px;
margin-bottom: 40px;
}
.menuButton:hover {
background: #00eaff;
color: #000;
transform: translateY(-5px) scale(1.08);
box-shadow:
0 10px 20px rgba(0, 234, 255, 0.6),
0 0 30px #00eaff;
/* === MENU BUTTON === */
.menu-btn {
font-size: 28px;
padding: 15px 55px;
margin: 0;
cursor: pointer;
background: linear-gradient(145deg, #111, #1b1b1b);
color: white;
border: 2px solid #00eaff;
border-radius: 40px;
box-shadow:
0 4px 0 #00bcd4,
0 0 12px rgba(0, 234, 255, 0.4),
inset 0 0 15px rgba(0, 234, 255, 0.2);
transition: 0.3s ease-in-out;
font-family: 'Orbitron', sans-serif;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 2px;
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
min-width: 320px;
}
.menu-btn:hover {
background: #00eaff;
color: #000;
transform: translateY(-5px) scale(1.08);
box-shadow:
0 10px 20px rgba(0, 234, 255, 0.6),
0 0 30px #00eaff;
}
.menu-btn:active {
transform: translateY(-2px) scale(1.05);
}
/* === BUTTON ICON & TEXT === */
.btn-icon {
font-size: 24px;
font-weight: bold;
}
.btn-text {
font-size: 22px;
}
/* === FOOTER INFO === */
.footer-info {
margin-top: 50px;
padding: 20px 30px;
background: rgba(0, 0, 0, 0.4);
border: 2px solid rgba(0, 234, 255, 0.3);
border-radius: 15px;
backdrop-filter: blur(4px);
}
.footer-info p {
color: #00eaff;
font-size: 14px;
letter-spacing: 1px;
opacity: 0.9;
text-align: center;
}
/* === OPTIONS TITLE === */
.options-title {
font-size: 70px;
font-weight: 900;
color: #ffffff;
margin-bottom: 50px;
letter-spacing: 4px;
text-shadow:
2px 2px 0px #00bcd4,
4px 4px 0px #009bb0,
6px 6px 0px #007a8c,
8px 8px 0px #005a68,
10px 10px 12px rgba(0, 234, 255, 0.7),
0 0 25px #00eaff;
}
/* === OPTIONS CONTAINER === */
.options-container {
background: rgba(0, 0, 0, 0.5);
border: 2px solid rgba(0, 234, 255, 0.4);
border-radius: 20px;
padding: 40px 50px;
margin-bottom: 40px;
min-width: 600px;
backdrop-filter: blur(5px);
box-shadow:
0 0 20px rgba(0, 234, 255, 0.3),
inset 0 0 20px rgba(0, 234, 255, 0.1);
}
/* === OPTION ITEM === */
.option-item {
margin-bottom: 35px;
text-align: left;
}
.option-item:last-child {
margin-bottom: 0;
}
.option-item label {
display: block;
color: #00eaff;
font-size: 20px;
font-weight: 700;
margin-bottom: 15px;
letter-spacing: 2px;
text-transform: uppercase;
text-shadow: 0 0 10px rgba(0, 234, 255, 0.5);
}
/* === SLIDER CONTAINER === */
.slider-container {
display: flex;
align-items: center;
gap: 20px;
}
/* === RANGE SLIDER === */
input[type="range"] {
flex: 1;
height: 6px;
background: rgba(27, 27, 27, 0.8);
border: 2px solid #00eaff;
border-radius: 10px;
outline: none;
-webkit-appearance: none;
cursor: pointer;
box-shadow: inset 0 0 5px rgba(0, 234, 255, 0.3);
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 24px;
height: 24px;
background: linear-gradient(145deg, #00eaff, #00bcd4);
border-radius: 50%;
cursor: pointer;
box-shadow:
0 0 10px rgba(0, 234, 255, 0.8),
0 2px 4px rgba(0, 0, 0, 0.5);
transition: all 0.2s ease;
border: 2px solid #ffffff;
}
input[type="range"]::-webkit-slider-thumb:hover {
background: #00eaff;
box-shadow:
0 0 20px rgba(0, 234, 255, 1),
0 4px 8px rgba(0, 0, 0, 0.6);
transform: scale(1.15);
}
input[type="range"]::-moz-range-thumb {
width: 24px;
height: 24px;
background: linear-gradient(145deg, #00eaff, #00bcd4);
border-radius: 50%;
cursor: pointer;
border: 2px solid #ffffff;
box-shadow:
0 0 10px rgba(0, 234, 255, 0.8),
0 2px 4px rgba(0, 0, 0, 0.5);
}
/* === SLIDER VALUE TEXT === */
.slider-container span {
color: #ffffff;
font-size: 18px;
font-weight: 700;
min-width: 60px;
text-align: right;
text-shadow: 0 0 8px rgba(0, 234, 255, 0.6);
}
/* === BUTTON GROUP === */
.button-group {
display: flex;
gap: 12px;
}
/* === TOGGLE BUTTON === */
.toggle-btn {
flex: 1;
padding: 12px 25px;
font-family: 'Orbitron', sans-serif;
font-size: 16px;
font-weight: 600;
color: rgba(255, 255, 255, 0.6);
background: linear-gradient(145deg, #111, #1b1b1b);
border: 2px solid rgba(0, 234, 255, 0.4);
border-radius: 10px;
cursor: pointer;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 1px;
box-shadow:
0 2px 0 rgba(0, 188, 212, 0.3),
inset 0 0 10px rgba(0, 234, 255, 0.1);
}
.toggle-btn:hover {
color: #00eaff;
border-color: #00eaff;
background: linear-gradient(145deg, #1b1b1b, #2a2a2a);
box-shadow:
0 2px 0 #00bcd4,
0 0 15px rgba(0, 234, 255, 0.4),
inset 0 0 15px rgba(0, 234, 255, 0.2);
}
.toggle-btn.active {
color: #000;
background: #00eaff;
border-color: #00eaff;
box-shadow:
0 4px 0 #00bcd4,
0 0 20px rgba(0, 234, 255, 0.8),
inset 0 0 10px rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
}
/* === BACK BUTTON === */
.back-btn {
margin-top: 20px;
background: linear-gradient(145deg, #1b1b1b, #111);
border-color: #00eaff;
color: #00eaff;
box-shadow:
0 4px 0 #00bcd4,
0 0 12px rgba(0, 234, 255, 0.4),
inset 0 0 15px rgba(0, 234, 255, 0.2);
}
.back-btn:hover {
background: linear-gradient(145deg, #2a2a2a, #1b1b1b);
border-color: #00eaff;
color: #ffffff;
box-shadow:
0 6px 0 #00bcd4,
0 0 25px rgba(0, 234, 255, 0.6),
inset 0 0 20px rgba(0, 234, 255, 0.3);
}
/* === GAME CONTAINER === */
#gameContainer {
width: 100vw;
height: 100vh;
background: #000;
}
#canvas {
width: 100%;
height: 100%;
margin: 0;
background-color: black;
display: block;
}
/* === RESPONSIVE === */
@media (max-width: 768px) {
.title-word {
font-size: 60px;
}
.menu-btn {
font-size: 20px;
padding: 12px 40px;
min-width: 280px;
}
.options-container {
min-width: 90vw;
padding: 30px;
}
.options-title {
font-size: 50px;
}
.footer-info p {
font-size: 12px;
}
}