AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA PENAT

This commit is contained in:
Stanley 2025-12-16 10:19:38 +07:00
parent decb897401
commit 88bfd9bd04

205
Script.js
View File

@ -191,8 +191,8 @@ function preRenderAssets() {
mCtx.fillStyle = mg; mCtx.fillStyle = mg;
mCtx.beginPath(); mCtx.beginPath();
mCtx.moveTo(mPad, mPad); mCtx.moveTo(mPad, mPad);
mCtx.lineTo(mPad + 30, mPad + 6); mCtx.lineTo(mPad + 30, mPad + 6);
mCtx.lineTo(mPad, mPad + 12); mCtx.lineTo(mPad, mPad + 12);
mCtx.fill(); mCtx.fill();
} }
@ -201,7 +201,7 @@ window.onload = function () {
}; };
function init() { function init() {
preRenderAssets(); preRenderAssets();
c = document.getElementById("canvas"); c = document.getElementById("canvas");
ctx = c.getContext("2d", { alpha: false }); ctx = c.getContext("2d", { alpha: false });
@ -633,7 +633,7 @@ function drawUI() {
drawNewText(game.level, canvasWidth - 140, 50, "#00ff00", "30px"); drawNewText(game.level, canvasWidth - 140, 50, "#00ff00", "30px");
// Lives (Stacked Icons) // Lives (Stacked Icons)
const lifeSize = 40; const lifeSize = 40;
const lifePadding = 5; const lifePadding = 5;
if (livesImg.complete) { if (livesImg.complete) {
@ -837,7 +837,7 @@ class backgroundObj {
this.height = 900; this.height = 900;
this.img = img; this.img = img;
this.img = img; this.img = img;
this.factor = speed; this.factor = speed;
} }
draw() { draw() {
ctx.save(); ctx.save();
@ -1172,7 +1172,7 @@ class AbilityToken {
constructor(x, y) { constructor(x, y) {
this.x = x; this.x = x;
this.y = y; this.y = y;
this.width = 40; this.width = 40;
this.height = 40; this.height = 40;
this.speed = 4; this.speed = 4;
let r = Math.random(); let r = Math.random();
@ -1355,24 +1355,133 @@ class Explosion {
} }
function drawGameOver() { function drawGameOver() {
ctx.fillStyle = "rgba(53, 0, 0, 0.7)"; // Dark overlay with gradient
const gradient = ctx.createRadialGradient(
canvasWidth / 2,
canvasHeight / 2,
0,
canvasWidth / 2,
canvasHeight / 2,
canvasWidth / 1.5
);
gradient.addColorStop(0, "rgba(10, 0, 0, 0.85)");
gradient.addColorStop(0.5, "rgba(30, 0, 10, 0.92)");
gradient.addColorStop(1, "rgba(0, 0, 0, 0.97)");
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvasWidth, canvasHeight); ctx.fillRect(0, 0, canvasWidth, canvasHeight);
ctx.font = "80px Arial"; // Animated pulsing effect
ctx.fillStyle = "red"; const pulseTime = Date.now() / 1000;
const pulse = Math.sin(pulseTime * 2) * 0.15 + 0.85;
ctx.save();
ctx.textAlign = "center"; ctx.textAlign = "center";
ctx.fillText("GAME OVER", canvasWidth / 2, canvasHeight / 2 - 50);
ctx.font = "40px Arial"; // "GAME OVER" main title with glowing effect
ctx.fillStyle = "white"; ctx.font = "900 100px Orbitron, Arial";
ctx.fillText(
"Final Score: " + player1.score, // Outer glow layers
canvasWidth / 2, for (let i = 30; i > 0; i -= 3) {
canvasHeight / 2 + 20 ctx.shadowColor = `rgba(255, 50, 50, ${(30 - i) / 100})`;
ctx.shadowBlur = i;
ctx.fillStyle = `rgba(255, 0, 0, ${(30 - i) / 100})`;
ctx.fillText("GAME OVER", canvasWidth / 2, canvasHeight / 2 - 120);
}
// Main title gradient
const titleGradient = ctx.createLinearGradient(
canvasWidth / 2 - 300,
0,
canvasWidth / 2 + 300,
0
); );
ctx.fillText("Refresh to Restart", canvasWidth / 2, canvasHeight / 2 + 70); titleGradient.addColorStop(0, "#ff0033");
titleGradient.addColorStop(0.5, "#ff3366");
titleGradient.addColorStop(1, "#ff0033");
ctx.textAlign = "left"; ctx.shadowColor = "rgba(255, 51, 102, 0.8)";
ctx.shadowBlur = 40 * pulse;
ctx.fillStyle = titleGradient;
ctx.fillText("GAME OVER", canvasWidth / 2, canvasHeight / 2 - 120);
// Reset shadow
ctx.shadowBlur = 0;
// Statistics panel background
const panelY = canvasHeight / 2 - 20;
const panelWidth = 500;
const panelHeight = 200;
const panelX = canvasWidth / 2 - panelWidth / 2;
// Panel border glow
ctx.strokeStyle = "rgba(0, 234, 255, 0.6)";
ctx.lineWidth = 3;
ctx.shadowColor = "rgba(0, 234, 255, 0.8)";
ctx.shadowBlur = 20;
ctx.strokeRect(panelX, panelY, panelWidth, panelHeight);
// Panel background
const panelGradient = ctx.createLinearGradient(
panelX,
panelY,
panelX,
panelY + panelHeight
);
panelGradient.addColorStop(0, "rgba(10, 10, 30, 0.85)");
panelGradient.addColorStop(1, "rgba(20, 20, 40, 0.9)");
ctx.fillStyle = panelGradient;
ctx.fillRect(panelX, panelY, panelWidth, panelHeight);
ctx.shadowBlur = 0;
// Statistics text - centered
ctx.textAlign = "center";
// "Your score:" label
ctx.font = "700 28px Orbitron, Arial";
ctx.fillStyle = "#00eaff";
ctx.fillText("Your score:", canvasWidth / 2, panelY + 70);
// Score value
ctx.font = "900 64px Orbitron, Arial";
ctx.shadowColor = "rgba(255, 255, 255, 0.5)";
ctx.shadowBlur = 15;
ctx.fillStyle = "#ffffff";
ctx.fillText(player1.score.toString(), canvasWidth / 2, panelY + 145);
ctx.shadowBlur = 0;
// Restart instruction with pulsing effect
ctx.textAlign = "center";
ctx.font = "700 28px Orbitron, Arial";
const instructionAlpha = Math.sin(pulseTime * 3) * 0.3 + 0.7;
ctx.fillStyle = `rgba(0, 234, 255, ${instructionAlpha})`;
ctx.shadowColor = "rgba(0, 234, 255, 0.6)";
ctx.shadowBlur = 15 * pulse;
ctx.fillText("PRESS F5 TO RESTART", canvasWidth / 2, panelY + panelHeight + 60);
// Additional decorative elements
ctx.shadowBlur = 0;
// Corner decorations (top-left and bottom-right)
const cornerSize = 40;
ctx.strokeStyle = "rgba(255, 51, 102, 0.5)";
ctx.lineWidth = 3;
// Top-left corner
ctx.beginPath();
ctx.moveTo(panelX - 10, panelY - 10 + cornerSize);
ctx.lineTo(panelX - 10, panelY - 10);
ctx.lineTo(panelX - 10 + cornerSize, panelY - 10);
ctx.stroke();
// Bottom-right corner
ctx.beginPath();
ctx.moveTo(panelX + panelWidth + 10, panelY + panelHeight + 10 - cornerSize);
ctx.lineTo(panelX + panelWidth + 10, panelY + panelHeight + 10);
ctx.lineTo(panelX + panelWidth + 10 - cornerSize, panelY + panelHeight + 10);
ctx.stroke();
ctx.restore();
} }
function drawPauseOverlay() { function drawPauseOverlay() {
@ -1423,7 +1532,7 @@ function drawScreenShading() {
let intensity = (game.surge - 1.0) / (7.0 - 1.0); let intensity = (game.surge - 1.0) / (7.0 - 1.0);
if (intensity > 0) { if (intensity > 0) {
ctx.save(); ctx.save();
ctx.globalCompositeOperation = "hard-light"; ctx.globalCompositeOperation = "hard-light";
ctx.fillStyle = "white"; ctx.fillStyle = "white";
ctx.globalAlpha = intensity * 0.4; ctx.globalAlpha = intensity * 0.4;
ctx.fillRect(0, 0, canvasWidth, canvasHeight); ctx.fillRect(0, 0, canvasWidth, canvasHeight);
@ -1433,8 +1542,8 @@ function drawScreenShading() {
} }
function updateSurge() { function updateSurge() {
const RAMP_UP_FRAMES = 240; const RAMP_UP_FRAMES = 240;
const HOLD_FRAMES = 780; const HOLD_FRAMES = 780;
const RAMP_DOWN_FRAMES = 300; const RAMP_DOWN_FRAMES = 300;
const MAX_SURGE_SPEED = 7.0; const MAX_SURGE_SPEED = 7.0;
@ -1549,14 +1658,14 @@ window.addEventListener('DOMContentLoaded', () => {
// === START BUTTON === // === START BUTTON ===
startBtn.addEventListener('click', () => { startBtn.addEventListener('click', () => {
playSound(menuClickSound); playSound(menuClickSound);
// Apply settings to game // Apply settings to game
applySettings(); applySettings();
// Hide menu, show game // Hide menu, show game
mainMenu.style.display = 'none'; mainMenu.style.display = 'none';
gameContainer.style.display = 'block'; gameContainer.style.display = 'block';
// Start the game // Start the game
if (!gameStarted) { if (!gameStarted) {
init(); init();
@ -1573,7 +1682,7 @@ optionBtn.addEventListener('click', () => {
// === EXIT BUTTON === // === EXIT BUTTON ===
exitBtn.addEventListener('click', () => { exitBtn.addEventListener('click', () => {
playSound(menuClickSound); playSound(menuClickSound);
// Create exit confirmation // Create exit confirmation
const confirmExit = document.createElement('div'); const confirmExit = document.createElement('div');
confirmExit.style.cssText = ` confirmExit.style.cssText = `
@ -1590,7 +1699,7 @@ exitBtn.addEventListener('click', () => {
box-shadow: 0 0 40px rgba(0, 234, 255, 0.6); box-shadow: 0 0 40px rgba(0, 234, 255, 0.6);
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
`; `;
confirmExit.innerHTML = ` confirmExit.innerHTML = `
<h3 style=" <h3 style="
color: #00eaff; color: #00eaff;
@ -1648,9 +1757,9 @@ exitBtn.addEventListener('click', () => {
">NO</button> ">NO</button>
</div> </div>
`; `;
document.body.appendChild(confirmExit); document.body.appendChild(confirmExit);
// YES button hover effect // YES button hover effect
const yesBtn = document.getElementById('confirmYes'); const yesBtn = document.getElementById('confirmYes');
yesBtn.addEventListener('mouseenter', () => { yesBtn.addEventListener('mouseenter', () => {
@ -1665,7 +1774,7 @@ exitBtn.addEventListener('click', () => {
yesBtn.style.transform = 'translateY(0) scale(1)'; 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)'; 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 // NO button hover effect
const noBtn = document.getElementById('confirmNo'); const noBtn = document.getElementById('confirmNo');
noBtn.addEventListener('mouseenter', () => { noBtn.addEventListener('mouseenter', () => {
@ -1680,7 +1789,7 @@ exitBtn.addEventListener('click', () => {
noBtn.style.transform = 'translateY(0) scale(1)'; 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)'; 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 // Click handlers
yesBtn.addEventListener('click', () => { yesBtn.addEventListener('click', () => {
window.close(); window.close();
@ -1688,7 +1797,7 @@ exitBtn.addEventListener('click', () => {
window.location.href = 'about:blank'; window.location.href = 'about:blank';
}, 100); }, 100);
}); });
noBtn.addEventListener('click', () => { noBtn.addEventListener('click', () => {
playSound(menuClickSound); playSound(menuClickSound);
document.body.removeChild(confirmExit); document.body.removeChild(confirmExit);
@ -1706,18 +1815,18 @@ backBtn.addEventListener('click', () => {
musicBtns.forEach(btn => { musicBtns.forEach(btn => {
btn.addEventListener('click', () => { btn.addEventListener('click', () => {
playSound(menuClickSound); playSound(menuClickSound);
musicBtns.forEach(b => b.classList.remove('active')); musicBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active'); btn.classList.add('active');
gameSettings.musicEnabled = btn.dataset.music === 'on'; gameSettings.musicEnabled = btn.dataset.music === 'on';
if (typeof currentBGM !== 'undefined') { if (typeof currentBGM !== 'undefined') {
if (gameSettings.musicEnabled) { if (gameSettings.musicEnabled) {
currentBGM.volume = 1; currentBGM.volume = 1;
if (!game.gameOver && gameStarted) { if (!game.gameOver && gameStarted) {
currentBGM.play().catch(() => {}); currentBGM.play().catch(() => { });
} }
} else { } else {
currentBGM.volume = 0; currentBGM.volume = 0;
@ -1731,11 +1840,11 @@ musicBtns.forEach(btn => {
sfxBtns.forEach(btn => { sfxBtns.forEach(btn => {
btn.addEventListener('click', () => { btn.addEventListener('click', () => {
playSound(menuClickSound); playSound(menuClickSound);
sfxBtns.forEach(b => b.classList.remove('active')); sfxBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active'); btn.classList.add('active');
gameSettings.sfxEnabled = btn.dataset.sfx === 'on'; gameSettings.sfxEnabled = btn.dataset.sfx === 'on';
}); });
}); });
@ -1760,7 +1869,7 @@ function applySettings() {
currentBGM.pause(); currentBGM.pause();
} }
} }
if (typeof gameOverBGM !== 'undefined') { if (typeof gameOverBGM !== 'undefined') {
if (gameSettings.musicEnabled) { if (gameSettings.musicEnabled) {
gameOverBGM.volume = 1; gameOverBGM.volume = 1;
@ -1775,7 +1884,7 @@ function playSound(audio) {
if (gameSettings.sfxEnabled) { if (gameSettings.sfxEnabled) {
audio.volume = 0.3; audio.volume = 0.3;
audio.currentTime = 0; audio.currentTime = 0;
audio.play().catch(() => {}); audio.play().catch(() => { });
} }
} }
@ -1789,7 +1898,7 @@ document.addEventListener('keydown', (e) => {
togglePause(); togglePause();
} }
} }
// Enter to start game from main menu // Enter to start game from main menu
if (e.key === 'Enter' && mainMenu.style.display === 'flex') { if (e.key === 'Enter' && mainMenu.style.display === 'flex') {
startBtn.click(); startBtn.click();
@ -1808,7 +1917,7 @@ function returnToMenu() {
gameOverBGM.pause(); gameOverBGM.pause();
currentBGM.currentTime = 0; currentBGM.currentTime = 0;
gameOverBGM.currentTime = 0; gameOverBGM.currentTime = 0;
game.gameOver = false; game.gameOver = false;
game.frames = 0; game.frames = 0;
game.level = 1; game.level = 1;
@ -1817,7 +1926,7 @@ function returnToMenu() {
game.surgePhase = 0; game.surgePhase = 0;
game.surgeTimer = 0; game.surgeTimer = 0;
game.surgeCooldown = 2400; game.surgeCooldown = 2400;
missilesArray = []; missilesArray = [];
playerMissilesArray = []; playerMissilesArray = [];
enemyShipArray = []; enemyShipArray = [];
@ -1825,11 +1934,11 @@ function returnToMenu() {
explosions = []; explosions = [];
abilityTokens = []; abilityTokens = [];
particles = []; particles = [];
player1 = new PlayerObject(100, 300); player1 = new PlayerObject(100, 300);
player1.lives = 6; player1.lives = 1;
player1.score = 0; player1.score = 0;
respawnCounter = 0; respawnCounter = 0;
damageFlash = 0; damageFlash = 0;
currentWave = null; currentWave = null;
@ -1839,7 +1948,7 @@ function returnToMenu() {
cameraY = 0; cameraY = 0;
gameStarted = false; gameStarted = false;
gamePaused = false; gamePaused = false;
if (gameContainer) gameContainer.style.display = 'none'; if (gameContainer) gameContainer.style.display = 'none';
if (mainMenu) mainMenu.style.display = 'flex'; if (mainMenu) mainMenu.style.display = 'flex';
} }