"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" } ]; let currentBGM = new Audio(); let gameOverBGM = new Audio(); 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; } var canvasWidth = 1280; var canvasHeight = 650; 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(?) var game = { level: 1, speed: 1, gameOver: false, frames: 0, timer: 0, }; var keys = { up: false, down: false, left: false, right: false, fire: false, }; var playerShipImg = new Image(); playerShipImg.src = "img/ships2.png"; var bg0 = new Image(); bg0.src = "img/bg_0.png"; var bg1 = new Image(); bg1.src = "img/bg_1.png"; var bg2 = new Image(); bg2.src = "img/bg_2.png"; var enemy1 = new Image(); 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; } }); //Stanley for (var i = 0; i < enemyImgArray.length; i++) { enemyImgArray[i] = new Image(); enemyImgArray[i].src = 'img/alien_' + [i] + '.png'; } var missilesArray = []; var enemyShipArray = []; var laser = document.createElement("audio"); laser.src = "music/laser2.mp3"; var explosion_enemy = document.createElement("audio"); explosion_enemy.src = "music/explosion-small.mp3" var planetImages = []; for (let i = 1; i <= 4; i++) { let img = new Image(); img.src = `img/SpritesPlanet/planet_${i}.png`; planetImages.push(img); } window.onload = function () { init(); }; function init() { c = document.getElementById("canvas"); ctx = c.getContext("2d"); document.addEventListener("keydown", keyDownPressed, false); document.addEventListener("keyup", keyUpPressed, false); gameStarted = true; //randomb bgm yg kita punya we have 3 songs/// pickRandomBGM(); currentBGM.volume = 1; currentBGM.play(); requestAnimationFrame(gameLoop); } //Aku ganti function game loop that follows the 90FPS Cap rule function gameLoop(timestamp) { if (!gameStarted) return; if (game.gameOver) { drawGameOver(); return; } if (timestamp - lastFrameTime >= frameInterval) { lastFrameTime = timestamp; clearGame(); updateGame(); drawGame(); } requestAnimationFrame(gameLoop); } // End of 90fps mark function keyDownPressed(e) { if (e.keyCode == 87) { keys.up = true; } else if (e.keyCode == 83) { keys.down = true; } if (e.keyCode == 65) { keys.left = true; } if (e.keyCode == 68) { keys.right = true; } if (e.keyCode == 32) { keys.fire = true; missilesArray.push(new LaserBullet(player1.x + 150, player1.y + 50)); laser.currentTime = 0; laser.play(); laser.volume = 0.4; } } function keyUpPressed(e) { if (e.keyCode == 87) { keys.up = false; } else if (e.keyCode == 83) { keys.down = false; } if (e.keyCode == 65) { keys.left = false; } if (e.keyCode == 68) { keys.right = false; } if (e.keyCode == 32) { keys.fire = false; } } function clearGame() { ctx.clearRect(0, 0, canvasWidth, canvasHeight); } function updateGame() { addStarField(); addShips(); player1.update(); if (player1.invincible > 0) player1.invincible--; spawnPlanet(); if (currentPlanet) currentPlanet.update(); game.frames++; } function drawGame() { if (currentPlanet) currentPlanet.draw(); player1.draw(); 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; } } } for (var i = 0; i < missilesArray.length; i++) { var m = missilesArray[i]; m.draw(); m.update(); // 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--; } } 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.image = playerShipImg; this.speed = 8; this.lives = 3; this.score = 0; this.health = 100; this.invincible = 0; } draw() { ctx.save(); ctx.drawImage(this.image, this.x, this.y, this.width, this.height); 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; } } if (keys.right) { if (this.x < canvasWidth - this.width) { this.x += this.speed; } } if (keys.left) { if (this.x > 10) { this.x -= this.speed; } } } } let player1 = new PlayerObject(100, 100); function drawNewText(txt, x, y, color) { ctx.font = "20px Arial"; ctx.fillStyle = color; ctx.fillText(txt, x, y); } class backgroundObj { constructor(img, x, y, speed) { this.x = x; this.y = y; this.width = 2000; this.height = 1200; this.img = img; this.speed = speed; } draw() { ctx.save(); ctx.drawImage(this.img, this.x, this.y, this.width, this.height); ctx.restore(); } update() { this.x -= this.speed; if (this.x < -2000) { this.x = 2000; } } } let background1 = new backgroundObj(bg0, 0, 0, game.speed * 3); let background1a = new backgroundObj(bg0, 2000, 0, game.speed * 3); let background2 = new backgroundObj(bg1, 0, 0, game.speed * 2); let background2a = new backgroundObj(bg1, 2000, 0, game.speed * 2); let background3 = new backgroundObj(bg2, 0, 0, game.speed * 1); let background3a = new backgroundObj(bg2, 2000, 0, game.speed * 1); function addStarField() { background3.draw(); background3.update(); background3a.draw(); background3a.update(); background2.draw(); background2.update(); background2a.draw(); background2a.update(); background1.draw(); background1.update(); background1a.draw(); background1a.update(); } class LaserBullet { constructor(x, y) { this.x = x; this.y = y; this.width = 14; this.height = 4; this.speed = 16; } draw() { let g = ctx.createLinearGradient( this.x, this.y, this.x + this.width, this.y ); g.addColorStop(0, "#00e1ff"); g.addColorStop(0.5, "#ffffff"); g.addColorStop(1, "#00e1ff"); ctx.fillStyle = g; ctx.shadowColor = "#00ffff"; ctx.shadowBlur = 15; ctx.fillRect(this.x, this.y, this.width, this.height); ctx.shadowBlur = 0; } update() { this.x += this.speed; } } class EnemyObj { constructor(x, y, speed, img) { this.x = x; this.y = y; this.width = 170; this.height = 105; this.image = img; this.speed = speed; this.health = 100; this.damage = 10; } draw() { ctx.save(); ctx.drawImage(this.image, this.x, this.y, this.width, this.height); ctx.restore(); } update() { this.x -= this.speed; } } let enemy = new EnemyObj(800, 200, 12, enemyImgArray[0]); class Planet { constructor(img) { this.image = img; this.width = 160; this.height = 160; this.x = canvasWidth + 50; this.y = Math.random() * 300 + 50; this.speed = 1.2; this.active = true; } draw() { ctx.drawImage(this.image, this.x, this.y, this.width, this.height); } update() { this.x -= this.speed; if (this.x < -this.width) { this.active = false; } } } let currentPlanet = null; function spawnPlanet() { if (currentPlanet == null || currentPlanet.active === false) { let randomImg = planetImages[Math.floor(Math.random() * planetImages.length)]; currentPlanet = new Planet(randomImg); } } 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])); } } } 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.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); } function crossfadeToGameOver() { let fadeSpeed = 0.02; gameOverBGM.volume = 0; gameOverBGM.play(); let fadeInterval = setInterval(() => { currentBGM.volume -= fadeSpeed; if (currentBGM.volume < 0) currentBGM.volume = 0; gameOverBGM.volume += fadeSpeed; if (gameOverBGM.volume > 1) gameOverBGM.volume = 1; if (currentBGM.volume === 0) { currentBGM.pause(); clearInterval(fadeInterval); } }, 1000 / 30); }