diff --git a/Script.js b/Script.js index ad12e03..cf04eac 100644 --- a/Script.js +++ b/Script.js @@ -51,7 +51,7 @@ var game = { surge: 1.0, surgePhase: 0, surgeTimer: 0, - surgeCooldown: 2400, // Start with 40s cooldown + surgeCooldown: 2400, }; var keys = { @@ -75,7 +75,6 @@ laserPickupImg.src = "img/Skills/double-missile.png"; // *** GAMBAR BARU UNTUK PICKUP BOMB *** var bombPickupImg = new Image(); -// Pastikan file gambar bom clay Anda disimpan di sini bombPickupImg.src = "img/Skills/bomb.png"; var livesImg = new Image(); @@ -138,8 +137,6 @@ let currentPlanet = null; let laserSprite, enemyBulletSprite, missileSprite; function preRenderAssets() { - // 1. CACHE LASER BULLET - // Padding for shadowBlur (15px) const lPad = 20; const lW = 13 + lPad * 2; const lH = 4 + lPad * 2; @@ -159,7 +156,6 @@ function preRenderAssets() { lCtx.fillRect(lPad, lPad, 13, 4); - // 2. CACHE ENEMY BULLET const ePad = 15; const eW = 10 + ePad * 2; const eH = 4 + ePad * 2; @@ -168,7 +164,7 @@ function preRenderAssets() { enemyBulletSprite.height = eH; const eCtx = enemyBulletSprite.getContext("2d"); - let eg = eCtx.createLinearGradient(ePad + 10, ePad, ePad, ePad); // Right to Left + let eg = eCtx.createLinearGradient(ePad + 10, ePad, ePad, ePad); eg.addColorStop(0, "#ff9900"); eg.addColorStop(0.5, "#ffffff"); eg.addColorStop(1, "#ff3300"); @@ -179,7 +175,6 @@ function preRenderAssets() { eCtx.fillRect(ePad, ePad, 10, 4); - // 3. CACHE PLAYER MISSILE (Body Only) const mPad = 5; const mW = 30 + mPad * 2; const mH = 12 + mPad * 2; @@ -196,8 +191,8 @@ function preRenderAssets() { mCtx.fillStyle = mg; mCtx.beginPath(); mCtx.moveTo(mPad, mPad); - mCtx.lineTo(mPad + 30, mPad + 6); // height/2 - mCtx.lineTo(mPad, mPad + 12); // height + mCtx.lineTo(mPad + 30, mPad + 6); + mCtx.lineTo(mPad, mPad + 12); mCtx.fill(); } @@ -206,7 +201,7 @@ window.onload = function () { }; function init() { - preRenderAssets(); // Generate sprites before game starts + preRenderAssets(); c = document.getElementById("canvas"); ctx = c.getContext("2d", { alpha: false }); @@ -311,7 +306,6 @@ function fireBullet() { } laser.currentTime = 0; - // IMPORTANT!! EXPERIMENT WITH THIS VALUE laser.volume = 0.2; laser.play(); createParticles( @@ -639,7 +633,7 @@ function drawUI() { drawNewText(game.level, canvasWidth - 140, 50, "#00ff00", "30px"); // Lives (Stacked Icons) - const lifeSize = 40; // Scaled down from 104px source + const lifeSize = 40; const lifePadding = 5; if (livesImg.complete) { @@ -843,7 +837,7 @@ class backgroundObj { this.height = 900; this.img = img; this.img = img; - this.factor = speed; // Rename speed to factor for parallax + this.factor = speed; } draw() { ctx.save(); @@ -938,11 +932,9 @@ class PlayerMissile { draw() { ctx.save(); - // Draw Cached Missile Body const padding = 5; ctx.drawImage(missileSprite, this.x - padding, this.y - padding); - // TRAIL BIRU LANGIT if (Math.random() < 0.5) { createParticles(this.x, this.y + this.height / 2, 2, "#00bfff"); } @@ -1101,7 +1093,6 @@ function addShips() { if (currentWave.spawnTimer <= 0) { spawnEnemyFromWave(currentWave); currentWave.spawned++; - // --- RANDOM SPACING --- let randomSpacing = currentWave.spacing + Math.floor(Math.random() * 30); currentWave.spawnTimer = randomSpacing; @@ -1129,7 +1120,7 @@ function startNewWave() { let baseCount = 3; let scalingCount = Math.floor(game.level / 2); let count = Math.min( - 20, // Max musuh ditingkatkan sedikit untuk kompensasi sebaran + 20, baseCount + scalingCount + Math.floor(Math.random() * 5) ); @@ -1145,15 +1136,12 @@ function startNewWave() { } function spawnEnemyFromWave(wave) { - // --- POSISI BENAR-BENAR ACAK --- - // Tentukan Y sembarang di area layar - // Area aman: 60px dari atas, 100px dari bawah + // --- POSISI MUSUH ACAK --- const minY = 60; const maxY = canvasHeight - 120; const y = Math.random() * (maxY - minY) + minY; - // Random X Offset biar tidak muncul dalam satu garis lurus sempurna const xOffset = Math.random() * 200; const randomShip = Math.floor(Math.random() * enemyImgArray.length); @@ -1162,20 +1150,18 @@ function spawnEnemyFromWave(wave) { let rawSpeed = 3.5 + Math.random() * 2 + game.level * 0.2; const speed = Math.min(rawSpeed, 8); - // --- RANDOM MOVEMENT TYPE --- - // Setiap musuh melempar dadu sendiri untuk menentukan tipe gerakannya - // 30% kemungkinan gerak gelombang (sine), sisanya lurus. + let movementType = Math.random() < 0.3 ? "sine" : "straight"; let enemy = new EnemyObj( - canvasWidth + 50 + xOffset, // X position + random offset + canvasWidth + 50 + xOffset, y, speed, enemyImgArray[randomShip], movementType ); - // BALANCING HEALTH + // ENEMY HEALTH enemy.health = 60 + game.level * 10; enemyShipArray.push(enemy); @@ -1186,10 +1172,9 @@ class AbilityToken { constructor(x, y) { this.x = x; this.y = y; - this.width = 40; // Ukuran sedikit diperbesar untuk gambar + this.width = 40; this.height = 40; this.speed = 4; - // RAND: 0-0.33=Bomb, 0.33-0.66=Double, 0.66-1.0=Missile let r = Math.random(); if (r < 0.33) this.type = "bomb"; else if (r < 0.66) this.type = "double"; @@ -1199,7 +1184,6 @@ class AbilityToken { draw() { ctx.save(); - // --- GAYA METAL SLUG (KOTAK PUTIH TEBAL) UNTUK SEMUA TIPE PICKUP --- ctx.strokeStyle = "#ffffff"; ctx.lineWidth = 3; ctx.strokeRect(this.x, this.y, this.width, this.height); @@ -1212,7 +1196,6 @@ class AbilityToken { } else if (this.type === "double") { imgToDraw = laserPickupImg; } else if (this.type === "bomb") { - // GUNAKAN GAMBAR BOM PICKUP YANG BARU imgToDraw = bombPickupImg; } @@ -1436,14 +1419,12 @@ function drawScreenShading() { } // --- BRIGHTNESS SURGE OVERLAY --- - // Use 'hard-light' or 'screen' to make dark backgrounds brighter if (game.surge > 1.0) { - let intensity = (game.surge - 1.0) / (7.0 - 1.0); // Normalized 0 to 1 + let intensity = (game.surge - 1.0) / (7.0 - 1.0); if (intensity > 0) { ctx.save(); - ctx.globalCompositeOperation = "hard-light"; // Better for space haze + ctx.globalCompositeOperation = "hard-light"; ctx.fillStyle = "white"; - // Intensity 0.0 to 1.0 -> Alpha 0.0 to 0.4 ctx.globalAlpha = intensity * 0.4; ctx.fillRect(0, 0, canvasWidth, canvasHeight); ctx.restore(); @@ -1452,9 +1433,9 @@ function drawScreenShading() { } function updateSurge() { - const RAMP_UP_FRAMES = 240; // 4 seconds - const HOLD_FRAMES = 780; // 13 seconds - const RAMP_DOWN_FRAMES = 300;// 5 seconds + const RAMP_UP_FRAMES = 240; + const HOLD_FRAMES = 780; + const RAMP_DOWN_FRAMES = 300; const MAX_SURGE_SPEED = 7.0; // Phase 0: Cooldown @@ -1726,16 +1707,12 @@ 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; @@ -1755,13 +1732,10 @@ 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'; }); }); @@ -1824,7 +1798,6 @@ document.addEventListener('keydown', (e) => { // === MODIFY EXISTING GAME FUNCTIONS === -// Override window.onload window.onload = function () { console.log('Game Ready - Waiting for menu start...'); };