diff --git a/Script.js b/Script.js index 2464f33..92b347e 100644 --- a/Script.js +++ b/Script.js @@ -1,11 +1,9 @@ "use strict"; - -// BGM system const bgmList = [ - { normal: "music/Scary.mp3", gameover: "music/ScaryGO.mp3" }, - { normal: "music/Fear.mp3", gameover: "music/FearGO.mp3" }, - { normal: "music/Chill.mp3", gameover: "music/ChillGO.mp3" } + { normal: "music/Scary.mp3", gameover: "music/ScaryGO.mp3" }, + { normal: "music/Fear.mp3", gameover: "music/FearGO.mp3" }, + { normal: "music/Chill.mp3", gameover: "music/ChillGO.mp3" }, ]; let currentBGM = new Audio(); @@ -14,9 +12,9 @@ currentBGM.loop = true; gameOverBGM.loop = true; function pickRandomBGM() { - const bgm = bgmList[Math.floor(Math.random() * bgmList.length)]; - currentBGM.src = bgm.normal; - gameOverBGM.src = bgm.gameover; + const bgm = bgmList[Math.floor(Math.random() * bgmList.length)]; + currentBGM.src = bgm.normal; + gameOverBGM.src = bgm.gameover; } var canvasWidth = 1280; @@ -25,11 +23,9 @@ var c = undefined; var ctx = undefined; var gameStarted = false; var musicMuted = false; -/// 90 FPS (Cause I got motion sickness while playing our game fr) + let lastFrameTime = 0; -const frameInterval = 1000 / 80; // 90 FPS limit right now it's capped at 80 -// 90 FPS mark (change the const x/x to what fps you want) -// Changing FPS actually makes the game slower ya or faster, tergantung(?) +const frameInterval = 1000 / 80; var game = { level: 1, @@ -48,7 +44,7 @@ var keys = { }; var playerShipImg = new Image(); -playerShipImg.src = "img/ships2.png"; +playerShipImg.src = "img/Player/pesawat22.png"; var bg0 = new Image(); bg0.src = "img/bg_0.png"; @@ -65,22 +61,18 @@ enemy1.src = "img/alien_0.png"; var enemyImgArray = []; enemyImgArray.length = 4; -///Key listen let audioStarted = false; window.addEventListener("keydown", () => { - if (!audioStarted) { - currentBGM.play(); - audioStarted = true; - } + if (!audioStarted) { + currentBGM.play(); + audioStarted = true; + } }); - - -//Stanley for (var i = 0; i < enemyImgArray.length; i++) { - enemyImgArray[i] = new Image(); - enemyImgArray[i].src = 'img/alien_' + [i] + '.png'; + enemyImgArray[i] = new Image(); + enemyImgArray[i].src = "img/alien_" + [i] + ".png"; } var missilesArray = []; @@ -90,9 +82,9 @@ var laser = document.createElement("audio"); laser.src = "music/laser2.mp3"; var explosion_enemy = document.createElement("audio"); -explosion_enemy.src = "music/explosion-small.mp3" +explosion_enemy.src = "music/explosion-small.mp3"; -var planetImages = []; +var planetImages = []; for (let i = 1; i <= 4; i++) { let img = new Image(); img.src = `img/SpritesPlanet/planet_${i}.png`; @@ -110,54 +102,53 @@ function init() { document.addEventListener("keydown", keyDownPressed, false); document.addEventListener("keyup", keyUpPressed, false); - gameStarted = true; - //randomb bgm yg kita punya we have 3 songs/// + gameStarted = true; pickRandomBGM(); currentBGM.volume = 1; currentBGM.play(); - requestAnimationFrame(gameLoop); + requestAnimationFrame(gameLoop); } -//Aku ganti function game loop that follows the 90FPS Cap rule function gameLoop(timestamp) { - if (!gameStarted) return; + if (!gameStarted) return; - if (game.gameOver) { - drawGameOver(); - return; - } + if (game.gameOver) { + drawGameOver(); + return; + } - if (timestamp - lastFrameTime >= frameInterval) { - lastFrameTime = timestamp; + if (timestamp - lastFrameTime >= frameInterval) { + lastFrameTime = timestamp; - clearGame(); - updateGame(); - drawGame(); - } + clearGame(); + updateGame(); + drawGame(); + } - requestAnimationFrame(gameLoop); + requestAnimationFrame(gameLoop); } -// End of 90fps mark function keyDownPressed(e) { - if (e.keyCode == 87) { + if (e.keyCode == 87 || e.keyCode == 38) { keys.up = true; - } else if (e.keyCode == 83) { + } else if (e.keyCode == 83 || e.keyCode == 40) { keys.down = true; } - if (e.keyCode == 65) { + if (e.keyCode == 65 || e.keyCode == 37) { keys.left = true; } - if (e.keyCode == 68) { + if (e.keyCode == 68 || e.keyCode == 39) { keys.right = true; } if (e.keyCode == 32) { keys.fire = true; - missilesArray.push(new LaserBullet(player1.x + 150, player1.y + 50)); + missilesArray.push( + new LaserBullet(player1.x + player1.width, player1.y + player1.height / 2) + ); laser.currentTime = 0; laser.play(); @@ -166,17 +157,17 @@ function keyDownPressed(e) { } function keyUpPressed(e) { - if (e.keyCode == 87) { + if (e.keyCode == 87 || e.keyCode == 38) { keys.up = false; - } else if (e.keyCode == 83) { + } else if (e.keyCode == 83 || e.keyCode == 40) { keys.down = false; } - if (e.keyCode == 65) { + if (e.keyCode == 65 || e.keyCode == 37) { keys.left = false; } - if (e.keyCode == 68) { + if (e.keyCode == 68 || e.keyCode == 39) { keys.right = false; } @@ -203,125 +194,191 @@ function updateGame() { } function drawGame() { - if (currentPlanet) currentPlanet.draw(); + if (currentPlanet) currentPlanet.draw(); - player1.draw(); + player1.draw(); - for (var i = 0; i < enemyShipArray.length; i++) { - var s = enemyShipArray[i]; - s.draw(); - s.update(); + for (var i = 0; i < enemyShipArray.length; i++) { + var s = enemyShipArray[i]; + s.draw(); + s.update(); - if (s.x < -200) { - enemyShipArray.splice(i, 1); - i--; - continue; - } - - if (Tabrakan(player1, s)) { - if (player1.invincible <= 0) { - - player1.lives--; - player1.invincible = 60; - //self note: change this later - explosion_enemy.play(); - player1.x = 15; - player1.y = 300; - game.frames = 0; - - enemyShipArray.splice(i, 1); - i--; - - if (player1.lives <= 0) { - game.gameOver = true; - crossfadeToGameOver(); - - } - - continue; - } - } + if (s.x < -200) { + enemyShipArray.splice(i, 1); + i--; + continue; } - for (var i = 0; i < missilesArray.length; i++) { - var m = missilesArray[i]; - m.draw(); - m.update(); + if (Tabrakan(player1, s)) { + if (player1.invincible <= 0) { + player1.lives--; + player1.invincible = 60; + explosion_enemy.play(); + // --- POSISI RESPAWN TENGAH --- + // Menggunakan tinggi player yang sudah dihitung agar pas tengah + player1.x = 100; + player1.y = canvasHeight / 2 - player1.height / 2; + player1.vx = 0; + player1.vy = 0; + game.frames = 0; + enemyShipArray.splice(i, 1); + i--; - - // Hit detecttion - for (var j = 0; j < enemyShipArray.length; j++) { - var en = enemyShipArray[j]; - - if (Tabrakan(m, en)) { - player1.score += 100; - explosion_enemy.play(); - missilesArray.splice(i, 1); - enemyShipArray.splice(j, 1); - } - } - //Hits end - - - - - if (m.x > canvasWidth) { - missilesArray.splice(i, 1); - i--; + if (player1.lives <= 0) { + game.gameOver = true; + crossfadeToGameOver(); } + continue; + } + } + } + + for (var i = 0; i < missilesArray.length; i++) { + var m = missilesArray[i]; + m.draw(); + m.update(); + + for (var j = 0; j < enemyShipArray.length; j++) { + var en = enemyShipArray[j]; + + if (Tabrakan(m, en)) { + player1.score += 100; + explosion_enemy.play(); + missilesArray.splice(i, 1); + enemyShipArray.splice(j, 1); + } } - drawNewText("Score: " + player1.score, 30, 610, "white"); - drawNewText("Player Lives: " + player1.lives, 1100, 610, "white"); + if (m.x > canvasWidth) { + missilesArray.splice(i, 1); + i--; + } + } + + drawNewText("Score: " + player1.score, 30, 610, "white"); + drawNewText("Player Lives: " + player1.lives, 1100, 610, "white"); } class PlayerObject { constructor(x, y) { this.x = x; this.y = y; - this.width = 170; - this.height = 105; + this.width = 100; + this.height = 64; this.image = playerShipImg; - this.speed = 8; + + this.vx = 0; + this.vy = 0; + this.acceleration = 0.8; + this.friction = 0.92; + this.maxSpeed = 10; + this.lives = 3; this.score = 0; this.health = 100; this.invincible = 0; + + this.totalFrames = 5; + this.frameIndex = 2; + this.spriteWidth = 0; + this.sourceHeight = 0; + this.scale = 1.3; + + this.image.onload = () => { + this.spriteWidth = this.image.width / this.totalFrames; + this.sourceHeight = this.image.height; + this.width = this.spriteWidth * this.scale; + this.height = this.sourceHeight * this.scale; + this.y = canvasHeight / 2 - this.height / 2; + }; } + draw() { ctx.save(); - ctx.drawImage(this.image, this.x, this.y, this.width, this.height); + + if (this.invincible > 0 && this.invincible % 4 < 2) { + ctx.globalAlpha = 0.5; + } + + if (this.spriteWidth > 0) { + ctx.drawImage( + this.image, + this.frameIndex * this.spriteWidth, + 0, + this.spriteWidth, + this.sourceHeight, + this.x, + this.y, + this.width, + this.height + ); + } else { + ctx.fillStyle = "red"; + ctx.fillRect(this.x, this.y, 50, 50); + } + ctx.restore(); } update() { if (keys.up) { - if (this.y > 0) { - this.y -= this.speed; - } - } else if (keys.down) { - if (this.x < canvasWidth - this.width) { - this.y += this.speed; - } + this.vy -= this.acceleration; } - - if (keys.right) { - if (this.x < canvasWidth - this.width) { - this.x += this.speed; - } + if (keys.down) { + this.vy += this.acceleration; } - if (keys.left) { - if (this.x > 10) { - this.x -= this.speed; - } + this.vx -= this.acceleration; + } + if (keys.right) { + this.vx += this.acceleration; + } + + this.vx *= this.friction; + this.vy *= this.friction; + + this.x += this.vx; + this.y += this.vy; + + const bleedY = this.height * 0.4; + const bleedX = this.width * 0.4; + + if (this.y < -bleedY) { + this.y = -bleedY; + if (this.vy < 0) this.vy = 0; + } + if (this.y > canvasHeight - this.height + bleedY) { + this.y = canvasHeight - this.height + bleedY; + if (this.vy > 0) this.vy = 0; + } + + if (this.x < -bleedX) { + this.x = -bleedX; + if (this.vx < 0) this.vx = 0; + } + if (this.x > canvasWidth - this.width + bleedX) { + this.x = canvasWidth - this.width + bleedX; + if (this.vx > 0) this.vx = 0; + } + + if (this.vy < -2.5) { + this.frameIndex = 4; + } else if (this.vy < -0.5) { + this.frameIndex = 3; + } else if (this.vy > 2.5) { + this.frameIndex = 0; + } else if (this.vy > 0.5) { + this.frameIndex = 1; + } else { + this.frameIndex = 2; } } } -let player1 = new PlayerObject(100, 100); +// Inisialisasi awal (Posisi Y akan di-override otomatis saat gambar load) +let player1 = new PlayerObject(100, 300); function drawNewText(txt, x, y, color) { ctx.font = "20px Arial"; @@ -447,7 +504,7 @@ class Planet { draw() { ctx.drawImage(this.image, this.x, this.y, this.width, this.height); - } + } update() { this.x -= this.speed; @@ -468,61 +525,60 @@ function spawnPlanet() { } function addShips() { - if (game.frames > 200) { - - if (game.frames % 150 == 0) { - var randomY = Math.floor(Math.random() * 500) + 20; - var randomSpeed = Math.floor(Math.random() * 10) + 1; - var randomShip = Math.floor(Math.random() * enemyImgArray.length); - enemyShipArray.push(new EnemyObj(1300, randomY, randomSpeed, enemyImgArray[randomShip])); - } - + if (game.frames > 200) { + if (game.frames % 150 == 0) { + var randomY = Math.floor(Math.random() * 500) + 20; + var randomSpeed = Math.floor(Math.random() * 10) + 1; + var randomShip = Math.floor(Math.random() * enemyImgArray.length); + enemyShipArray.push( + new EnemyObj(1300, randomY, randomSpeed, enemyImgArray[randomShip]) + ); } + } } -function Tabrakan(o, p){ - if (o.x + o.width > p.x && - o.x < p.x + p.width && - o.y + o.height > p.y && - o.y < p.y + p.height) { - return true; - } - return false; +function Tabrakan(o, p) { + if ( + o.x + o.width > p.x && + o.x < p.x + p.width && + o.y + o.height > p.y && + o.y < p.y + p.height + ) { + return true; + } + return false; } function drawGameOver() { - ctx.fillStyle = "rgba(0,0,0,0.7)"; - ctx.fillRect(0, 0, canvasWidth, canvasHeight); + ctx.fillStyle = "rgba(0,0,0,0.7)"; + ctx.fillRect(0, 0, canvasWidth, canvasHeight); - ctx.font = "80px Arial"; - ctx.fillStyle = "red"; - ctx.textAlign = "center"; - ctx.fillText("GAME OVER", canvasWidth / 2, canvasHeight / 2 - 50); + ctx.font = "80px Arial"; + ctx.fillStyle = "red"; + ctx.textAlign = "center"; + ctx.fillText("GAME OVER", canvasWidth / 2, canvasHeight / 2 - 50); - ctx.font = "40px Arial"; - ctx.fillStyle = "white"; - ctx.fillText("Refresh to Restart", canvasWidth / 2, canvasHeight / 2 + 30); + ctx.font = "40px Arial"; + ctx.fillStyle = "white"; + ctx.fillText("Refresh to Restart", canvasWidth / 2, canvasHeight / 2 + 30); } function crossfadeToGameOver() { - let fadeSpeed = 0.02; + let fadeSpeed = 0.02; - gameOverBGM.volume = 0; - gameOverBGM.play(); + gameOverBGM.volume = 0; + gameOverBGM.play(); - let fadeInterval = setInterval(() => { + let fadeInterval = setInterval(() => { + currentBGM.volume -= fadeSpeed; + if (currentBGM.volume < 0) currentBGM.volume = 0; - currentBGM.volume -= fadeSpeed; - if (currentBGM.volume < 0) currentBGM.volume = 0; + gameOverBGM.volume += fadeSpeed; + if (gameOverBGM.volume > 1) gameOverBGM.volume = 1; - gameOverBGM.volume += fadeSpeed; - if (gameOverBGM.volume > 1) gameOverBGM.volume = 1; - - if (currentBGM.volume === 0) { - currentBGM.pause(); - clearInterval(fadeInterval); - } - - }, 1000 / 30); + if (currentBGM.volume === 0) { + currentBGM.pause(); + clearInterval(fadeInterval); + } + }, 1000 / 30); } - diff --git a/img/Player/pesawat2.png b/img/Player/pesawat2.png new file mode 100644 index 0000000..8b154a2 Binary files /dev/null and b/img/Player/pesawat2.png differ diff --git a/img/Player/pesawat22.png b/img/Player/pesawat22.png new file mode 100644 index 0000000..e412bf2 Binary files /dev/null and b/img/Player/pesawat22.png differ diff --git a/img/fighterShip.png b/img/fighterShip.png deleted file mode 100644 index 21d5849..0000000 Binary files a/img/fighterShip.png and /dev/null differ diff --git a/img/pixelShip.png b/img/pixelShip.png deleted file mode 100644 index eedda0f..0000000 Binary files a/img/pixelShip.png and /dev/null differ diff --git a/img/ships3.png b/img/ships3.png new file mode 100644 index 0000000..9a27245 Binary files /dev/null and b/img/ships3.png differ