diff --git a/Audio/explosion.wav b/Audio/explosion.wav index bc2a5f7..fdb4c62 100644 Binary files a/Audio/explosion.wav and b/Audio/explosion.wav differ diff --git a/Backgrounds/galaxyAnim.gif b/Backgrounds/galaxyAnim.gif index 54e16f5..4730814 100644 Binary files a/Backgrounds/galaxyAnim.gif and b/Backgrounds/galaxyAnim.gif differ diff --git a/BlueExplosion/blueExplosion.gif b/BlueExplosion/blueExplosion.gif new file mode 100644 index 0000000..634371a Binary files /dev/null and b/BlueExplosion/blueExplosion.gif differ diff --git a/Scripts/asteroids.js b/Scripts/asteroids.js deleted file mode 100644 index 18005a7..0000000 --- a/Scripts/asteroids.js +++ /dev/null @@ -1,102 +0,0 @@ -//all asteroid related functions -function generateAsteroid(asteroid) { - asteroid.x = Math.random() * (astRangeX) + padding; - asteroid.y = Math.random() * (astRangeY) + sBHeight + padding; - givePlayerImmunity(500); - asteroid.exist = true; - asteroid.moving = false; -} - -function moveCheese() { - if (cheese.exist && detectRange(ship, cheese)) { - switch (ship.direction) { - case 1: - cheese.y -= ship.speed * 0.5; - detectCheeseBorderCol(cheese); - break; - case 2: - cheese.x += ship.speed * 0.5; - detectCheeseBorderCol(cheese); - break; - case 3: - cheese.y += ship.speed * 0.5; - detectCheeseBorderCol(cheese); - break; - case 4: - cheese.x -= ship.speed * 0.5; - detectCheeseBorderCol(cheese); - break; - case 5: - cheese.y -= ship.speed * 0.5; - cheese.x += ship.speed * 0.5; - detectCheeseBorderCol(cheese); - break; - case 6: - cheese.y += ship.speed * 0.5; - cheese.x += ship.speed * 0.5; - detectCheeseBorderCol(cheese); - break; - case 7: - cheese.y += ship.speed * 0.5; - cheese.x -= ship.speed * 0.5; - detectCheeseBorderCol(cheese); - break; - case 8: - cheese.y -= ship.speed * 0.5; - cheese.x -= ship.speed * 0.5; - detectCheeseBorderCol(cheese); - break; - } - } -} - -function handleAsteroids() { //moving & drawing asteroids as score goes up - if (cheese.exist) { - cheese.drawAst(); - moveCheese(); - } - if (level == 1 && redAst.exist) { - redAst.drawAst(); - if (!redAst.moving) { - clearInterval(redAst.moveInterval); - redAst.moveInterval = setInterval(() => redAst.move(), 30); - redAst.moving = true; - } - } - if (level == 2 && redAst2.exist) { - redAst.drawAst(); - redAst2.drawAst(); - if (!redAst2.moving) { - clearInterval(redAst2.moveInterval); - redAst2.moveInterval = setInterval(() => redAst2.move(), 30); - redAst2.moving = true; - } - } - if (((level == 3) || (level == 4)) && redAst3.exist) { - redAst.drawAst(); - redAst2.drawAst(); - redAst3.drawAst(); - if (!redAst3.moving) { - clearInterval(redAst3.moveInterval); - redAst3.moveInterval = setInterval(() => redAst3.move(), 30); - redAst3.moving = true; - } - } - if (level == 5 && redAst4.exist) { - redAst.drawAst(); - redAst2.drawAst(); - redAst3.drawAst(); - redAst4.drawAst(); - if (!redAst4.moving) { - clearInterval(redAst4.moveInterval); - redAst4.moveInterval = setInterval(() => redAst4.move(), 30); - redAst4.moving = true; - } - } - if (level > 5) { - redAst.drawAst(); - redAst2.drawAst(); - redAst3.drawAst(); - redAst4.drawAst(); - } -} \ No newline at end of file diff --git a/Scripts/audio.js b/Scripts/audio.js index 67ed84e..4f94a02 100644 --- a/Scripts/audio.js +++ b/Scripts/audio.js @@ -67,6 +67,7 @@ function changeMenuMusic(source) { } function randomizeMenuMusic() { + menuMusic.pause(); menuMusicNumber = Math.floor((Math.random() * 4)); switch (menuMusicNumber) { case 0: @@ -82,44 +83,7 @@ function randomizeMenuMusic() { menuMusic.src = "Audio/stageSelectJJunkala.wav"; break; } -} - -//navigation -function prevMusicPage() { - //if on page 1 go to page 3 - if (!musicPage1.classList.contains("hidden")) { - musicPage1.classList.add("hidden"); - musicPage3.classList.remove("hidden"); - } - //if on page 2 go to page 1 - else if (!musicPage2.classList.contains("hidden")) { - musicPage2.classList.add("hidden"); - musicPage1.classList.remove("hidden"); - } - //if on page 3 go to page 2 - else if (!musicPage3.classList.contains("hidden")) { - musicPage3.classList.add("hidden"); - musicPage2.classList.remove("hidden"); - } - clickSound.play(); -} -function nextMusicPage() { - //if on page 1 go to page 2 - if (!musicPage1.classList.contains("hidden")) { - musicPage1.classList.add("hidden"); - musicPage2.classList.remove("hidden"); - } - //if on page 2 go to page 3 - else if (!musicPage2.classList.contains("hidden")) { - musicPage2.classList.add("hidden"); - musicPage3.classList.remove("hidden"); - } - //if on page 3 go to page 1 - else if (!musicPage3.classList.contains("hidden")) { - musicPage3.classList.add("hidden"); - musicPage1.classList.remove("hidden"); - } - clickSound.play(); + menuMusic.play(); } function updateVolume() { //!!! diff --git a/Scripts/detections.js b/Scripts/detections.js deleted file mode 100644 index b5201df..0000000 --- a/Scripts/detections.js +++ /dev/null @@ -1,126 +0,0 @@ -//collision detection; first "if" is for x-values/domain, second "if" is for y-values/range -var distanceToPlayer; - -// function detectCollision(player, obstacle) { -// if (playerControl && !ship.immunity) { -// // if (player.x > obstacle.x + obstacle.width || -// // player.x + player.width < obstacle.x || -// // player.y > obstacle.y + obstacle.height || -// // player.y + player.height < obstacle.y) { -// // return false; -// // } -// // return true; //use "detectCollision" in an if statement -// } -// } - -function detectCircleCollision(player, obstacle){ - if (playerControl && !ship.immunity) { - distanceToPlayer = Math.sqrt(((player.x+player.radius)-(obstacle.x+obstacle.radius))**2+((player.y+player.radius)-(obstacle.y+obstacle.radius))**2); - //pythagoras: (player centerX - obstacle centerX)^2 + (player centerY - obstacle centerY)^2 - if (distanceToPlayer <= player.radius + obstacle.radius) { - return true; - } - return false; - } -} -//update: added circle collision, updated detectAllCollisions to match -function detectAllCollisions() { - if (detectCircleCollision(ship, ast)) { - generateAsteroid(ast); - score += scoreAmt; - detectLevelUp(); - changeLevelUp(); - popSound.play(); - } - if ((redAst.exist && detectCircleCollision(ship, redAst))) { - gameOver(); - } - if ((redAst2.exist && detectCircleCollision(ship, redAst2))) { - gameOver(); - } - if ((redAst3.exist && detectCircleCollision(ship, redAst3))) { - gameOver(); - } - if ((redAst4.exist && detectCircleCollision(ship, redAst4))) { - gameOver(); - } - if (cheese.exist && detectCircleCollision(ship, cheese)) { - slowDown = true; - cheeseCDFrame = 1; - givePlayerImmunity(300); - score += 5; - detectLevelUp(); - changeLevelUp(); - popSound.play(); - - cheese.x = Math.random() * (astRangeX) + padding; //regenerate cheese coordinates - cheese.y = Math.random() * (astRangeY) + sBHeight + padding; - startSD(); - } -} - -//slowDown effect -function startSD() { - cheese.exist = false; - sDCount = 1; - ship.speed = currentSpeed * (sDCount / 10); - sDInterval = setInterval(sDCounter, 1000); -} - -function sDCounter() { - if (sDCount > 4) { - ship.speed = currentSpeed; - cheeseCDFrame = 4; - slowDown = false; - cheese.exist = true; - clearInterval(sDInterval); - dingSound.play(); - } - else if (sDCount <= 6) { - cheese.exist = false; - sDCount += 2; - ship.speed = currentSpeed * (sDCount / 10); - cheeseCDFrame += 1; - if (cheeseCDFrame > 4) { - cheeseCDFrame = 1; - } - } -} - -// code for cheese to run away -function detectRange(player, obstacle) { - if (playerControl) { - if (player.x > obstacle.x + obstacle.width + tolerance || //same collision code, but adding extra distance to create a range - player.x + player.width + tolerance < obstacle.x || - player.y > obstacle.y + obstacle.height + tolerance || - player.y + player.height + tolerance < obstacle.y) { - return false; - } - return true; - } -} - -function detectBorderCollision(obstacle) { - if (obstacle.x < 1 - obstacle.width) { - obstacle.x = canvas.width; - } - if (obstacle.x > canvas.width) { - obstacle.x = 1 - obstacle.width; - } - if (obstacle.y < 1 - obstacle.height) { - obstacle.y = canvas.height; - } - if (obstacle.y > canvas.height) { - obstacle.y = 1 - obstacle.height; - } -} - -function detectCheeseBorderCol(obstacle) { - if (obstacle.x < 0 || - obstacle.x > canvas.width || - obstacle.y < sBHeight || - obstacle.y > canvas.height) { - obstacle.x = 460; - obstacle.y = 310; - } -} \ No newline at end of file diff --git a/Scripts/functions.js b/Scripts/functions.js index 9261180..6bb72f1 100644 --- a/Scripts/functions.js +++ b/Scripts/functions.js @@ -1,190 +1,168 @@ -//draw functions -function drawCircle(color, obj) { - ctx.fillStyle = color; - ctx.beginPath(); - ctx.arc(obj.x+obj.radius, obj.y+obj.radius, obj.radius, 0, Math.PI*2); - ctx.fill(); - ctx.closePath(); - ctx.stroke(); -} - -// update: moved to player constructor -// function drawShip(img, sX, sY, sW, sH, dX, dY, dW, dH) { -// ctx.fillStyle = "white"; -// ctx.beginPath(); -// ctx.arc(ship.centerX, ship.centerY, ship.radius, 0, Math.PI*2); -// ctx.fill(); -// ctx.closePath(); -// ctx.stroke(); -// ctx.drawImage(img, sX, sY, sW, sH, dX, dY, dW, dH); - -// } -function drawAst(img, dX, dY, dW, dH) { - //drawCircle("gray",ast); - ctx.drawImage(img, dX, dY, dW, dH); -} - -//skin changes -function changeShipSkin(skinName) { - if (window.localStorage.getItem('unlocks') && JSON.parse(window.localStorage.getItem('unlocks')).includes(skinName)) { - currentSkin = skinName; - } else if (defaultUnlocks.includes(skinName)) { - currentSkin = skinName; +//collision detection; first "if" is for x-values/domain, second "if" is for y-values/range +var distanceToPlayer, dX, dY; + +function detectCircleCollision(player, obstacle, tolerance) { + if (playerControl && !ship.immunity) { + dX = (player.x + player.radius) - (obstacle.x + obstacle.radius); + dY = (player.y + player.radius) - (obstacle.y + obstacle.radius); + distanceToPlayer = Math.sqrt(dX ** 2 + dY ** 2) - tolerance; + //pythagoras: (player centerX - obstacle centerX)^2 + (player centerY - obstacle centerY)^2 + if (distanceToPlayer <= player.radius + obstacle.radius) { + return true; + } + return false; } - window.localStorage.setItem('skinName', JSON.stringify(currentSkin)); //JSON needs it to be a string, so this works by stringifying to ensure it's a string - clickSound.play(); -} -function changeBkgSkin(bkgSkinName) { - backgroundImg.src = bkgSkinName; - window.localStorage.setItem('bkgImg', JSON.stringify(backgroundImg.src)); - clickSound.play(); } -function updateUnlocks() { - //check scores - if (!unlocks.includes("Sprites/snakeSS1.png") && scoreArray[0] >= 100) { - unlocks.push("Sprites/snakeSS1.png"); - } - if (!unlocks.includes("Sprites/alphaInvertedSS1.png") && scoreArray[0] >= 150) { - unlocks.push("Sprites/alphaInvertedSS1.png"); - } - if (!unlocks.includes("Sprites/asteroidSS1.png") && scoreArray[0] >= 250) { - unlocks.push("Sprites/asteroidSS1.png"); - } - //update skins to be Unlocked or Greyed - if (unlocks.includes("Sprites/snakeSS1.png")) { - snakeSkin.classList.remove("greyed"); - snakeSkin.src = "Sprites/shipSnake.png"; //html image - window.localStorage.setItem('unlocks', JSON.stringify(unlocks)); - } - else { - snakeSkin.classList.add("greyed"); - snakeSkin.src = "Sprites/shipSnakeLocked.png"; + +function detectBorderCollision(obj) { + if (obj.x < 1 - obj.width) { // passing left border + obj.x = canvas.width; } - if (unlocks.includes("Sprites/alphaInvertedSS1.png")) { - invertedSkin.classList.remove("greyed"); - invertedSkin.src = "Sprites/shipAlphaInverted.png"; - window.localStorage.setItem('unlocks', JSON.stringify(unlocks)); + if (obj.x > canvas.width) { // passing right border + obj.x = 1 - obj.width; } - else { - invertedSkin.classList.add("greyed"); - invertedSkin.src = "Sprites/shipAlphaInvertedLocked.png"; + if (obj.y < 1 - obj.height) { // passing top border + obj.y = canvas.height; } - if (unlocks.includes("Sprites/asteroidSS1.png")) { - asteroidSkin.classList.remove("greyed"); - asteroidSkin.src = "Sprites/asteroid.png"; - window.localStorage.setItem('unlocks', JSON.stringify(unlocks)); + if (obj.y > canvas.height) { // passing bottom border + obj.y = 1 - obj.height; } - else { - asteroidSkin.classList.add("greyed"); - asteroidSkin.src = "Sprites/AsteroidLocked.png"; +} +function detectCheeseBorderCol() { //teleports to middle of screen + if (cheese.x < 0 || cheese.x > canvas.width || cheese.y < sBHeight || cheese.y > canvas.height) { + cheese.x = 460; + cheese.y = 310; } } -//score sorting -function handleScore(newScore) { - scoreArray.push(newScore); //add new score in - document.getElementById("finalScoreDisplay").innerHTML = score; //displays "Final Score:" - scoreArray.sort(function (a, b) { return b - a }); //sort array - for (i = 0; i < 5; ++i) { - if (!scoreArray[i]) { - scoreArray[i] = 0; +function detectAllCollisions() { + //reds; gameover + enemyAstArray.forEach(asteroid => { + if (asteroid.exist && asteroid.moving && detectCircleCollision(ship, asteroid, -ship.breathingRoom)) { + gameOver(); + } else if (asteroid.exist && asteroid.moving && detectCircleCollision(greyAst, asteroid, 0)) { + popSound.play(); + greyAst.generate(); } - document.querySelector('.score' + i).innerHTML = scoreArray[i]; //reset each of the scores in the score screen + }) + //collectibles + if (greyAst.exist && detectCircleCollision(ship, greyAst, 0)) { + score += scoreAmt; + changeLevelUp(); + popSound.play(); + + greyAst.generate(); //move to a new location } - window.localStorage.setItem('scoreArray', JSON.stringify(scoreArray)); - while (scoreArray.length > 5) { - scoreArray.pop(); - window.localStorage.setItem('scoreArray', JSON.stringify(scoreArray)); + if (cheese.exist && detectCircleCollision(ship, cheese, 0)) { + score += scoreAmt * 5; + changeLevelUp(); + popSound.play(); + cheese.exist = false; + + sDCount = 1; + ship.speed = currentSpeed * (sDCount / 7); + clearInterval(sDInterval); + sDInterval = setInterval(sDCounter, 1000); } - updateUnlocks(); } -function givePlayerImmunity(duration) { - ship.immunity = true; - setTimeout(function () { ship.immunity = false }, duration); -} -function cycleExplosionFrame() { - if (ship.exploded && !firstDeath) { - setInterval(function () { - if (ship.explosionFrame < 10) { - ship.explosionFrame++; - } - else { - ship.explosionFrame = 1; - } - }, 100); - ship.exploded = false; - firstDeath = true; - } - else if (ship.exploded && firstDeath) { - ship.exploded = false; + +function changeBkgSkin(bkgSkinName) { + backgroundImg.src = bkgSkinName; + window.localStorage.setItem('bkgImg', JSON.stringify(backgroundImg.src)); + clickSound.play(); +} +//slowDown effect +function sDCounter() { + if (sDCount > 2) { //break out of loop FIRST + sDCount = 4; // cheeseCD image + ship.speed = currentSpeed; // speed + clearInterval(sDInterval); // interval + cheese.generate(); // cheese + dingSound.play(); + } else if (sDCount <= 5) { + //update speed + sDCount += 1; + ship.speed = currentSpeed * (sDCount / 7); } } //animation +//draw functions +function drawCircle(color, obj) { + ctx.fillStyle = color; + ctx.beginPath(); + ctx.arc(obj.x + obj.radius, obj.y + obj.radius, obj.radius, 0, Math.PI * 2); + ctx.fill(); + ctx.closePath(); + ctx.stroke(); +} +function drawScore() { + //Scoreboard rectangle (Drawn after everything so that it's always on top) + ctx.fillStyle = "#cf8619"; //an orange colour to contrast the blue + ctx.fillRect(0, 0, canvas.width, sBHeight); + //Scoreboard border (so there is a nice blue border) + ctx.beginPath(); + ctx.strokeStyle = "rgb(0, 1, 86)"; + ctx.lineWidth = "5"; //same values as the canvas width & border + ctx.rect(0, 0, canvas.width, sBHeight); + ctx.stroke(); + + //Score text ("SCORE=___") + ctx.font = "bold 38px impact"; + ctx.fillStyle = "darkblue"; + ctx.textAlign = "center"; + ctx.fillText("SCORE = " + score, canvas.width / 2, sBHeight - (sBHeight / 5),); +} + + let now, then, elapsed, fpsInterval, startTime; function startAnimating(fps) { fpsInterval = 1000 / fps; then = Date.now(); animate(); } -function animate() { +function animate() { //game update now = Date.now(); elapsed = now - then; - if (elapsed > fpsInterval) { //if frame is at correct time, animate this - then = now - (elapsed % fpsInterval); //reset timer first + if (elapsed > fpsInterval) { //if proper time for framerate has passed + then = now - (elapsed % fpsInterval); //reset timer ctx.clearRect(0, 0, canvas.width, canvas.height); //clear canvas to save memory - - //which skin to display; exploded vs Skin selection - if (gameOverT && skinsMenuScreen.classList.contains('hidden')) { //required for UI to work when opening skin menu - ship.image.src = "BlueExplosion/blue" + JSON.stringify(ship.explosionFrame) + ".png"; - cycleExplosionFrame(); - ship.draw(ship.image.src, 0, 0, 256, 256, ship.x - 50, ship.y - 50, ship.width + 100, ship.height + 100); + //display explosion (called on gameOver()) or selected skin + if (ship.exploded && skinsMenuScreen.classList.contains('hidden')) { //required for UI to work when opening skin menu + ship.image.src = "BlueExplosion/blue" + ship.explosionFrame.toString() + ".png"; + if(ship.image.height == 256) { + ship.draw(ship.image.src, 0, 0, 256, 256, ship.x - 50, ship.y - 50, ship.width + 100, ship.height + 100); + } + ship.cycleExplosionFrame(); } - else { + else if (!skinsMenuScreen.classList.contains('hidden')) { + ship.speed = 0; + ship.move(); + ship.image.src = currentSkin; + ship.draw(ship.image.src, 67 * ship.frameX, 66 * ship.frameY, 67, 66, ship.x, ship.y, ship.width, ship.height); + } else { ship.image.src = currentSkin; ship.draw(ship.image.src, 67 * ship.frameX, 66 * ship.frameY, 67, 66, ship.x, ship.y, ship.width, ship.height); } if (playerControl) { - moveShip(); - drawAst(ast.sprite, ast.x, ast.y, ast.width, ast.height); //grey - handleAsteroids(); //reds - cheeseCD.src = "Sprites/cheeseCooldown" + JSON.stringify(cheeseCDFrame) + ".png"; - drawAst(cheeseCD, 920, 60, 64, 60); + ship.move(); + handleAsteroids(); //grey, red, cheese & plasma asteroids + detectAllCollisions(); if (bkgMusic.ended) { bkgMusic.play(); } - } else if (menuMusic.ended || userInteracted) { + } else if (userInteracted && (menuMusic.ended || menuMusic.paused)) { menuMusic.play(); } - //Scoreboard rectangle (Drawn after everything so that it's always on top) - ctx.fillStyle = "#cf8619"; //an orange colour to contrast the blue - ctx.fillRect(0, 0, canvas.width, sBHeight); - //Scoreboard border (so there is a nice blue border) - ctx.beginPath(); - ctx.strokeStyle = "rgb(0, 1, 86)"; - ctx.lineWidth = "5"; //same values as the canvas width & border - ctx.rect(0, 0, canvas.width, sBHeight); - ctx.stroke(); - - //Score text ("SCORE=___") - if (!mobile) { - ctx.font = "bold 38px impact"; - } - else if (mobile) { - ctx.font = "bold 19px impact"; - } - ctx.fillStyle = "darkblue"; - ctx.textAlign = "center"; - ctx.fillText("SCORE = " + score, canvas.width / 2, sBHeight - (sBHeight / 5),); + drawScore(); + updateVolume(); //sound effects & music volume } - - updateVolume(); requestAnimationFrame(animate); } diff --git a/Scripts/inputs.js b/Scripts/inputs.js deleted file mode 100644 index 4579852..0000000 --- a/Scripts/inputs.js +++ /dev/null @@ -1,313 +0,0 @@ -//keyboard -window.addEventListener("keydown", function (e) { //creates an array to detect keys - keys[e.key] = true; - //console.log(e.key); -}); -window.addEventListener("keyup", function (e) { //deletes any keys in the array to save memory - delete keys[e.key]; -}); -//mobile -mBUp.addEventListener("touchStart", function() { - keys["w"] = true; -}); -mBUp.addEventListener("touchEnd", function() { - delete keys["w"]; -}); -mBLeft.addEventListener("touchStart", function() { - keys["a"] = true; -}); -mBLeft.addEventListener("touchEnd", function() { - delete keys["a"]; -}); -mBDown.addEventListener("touchStart", function() { - keys["s"] = true; -}); -mBDown.addEventListener("touchEnd", function() { - delete keys["s"]; -}); -mBRight.addEventListener("touchStart", function() { - keys["d"] = true; -}); -mBRight.addEventListener("touchEnd", function() { - delete keys["d"]; -}); - -function moveShip() { //keyboard controls WASD & arrow keys; also detects collision with frame border - detectAllCollisions(); - //up - if ((keys["w"] || keys["ArrowUp"]) && ship.y > sBHeight) { //sBHeight is scoreboard height - ship.y -= ship.speed; - ship.direction = 1; - ship.frameX = 0; - ship.frameY = 0; - } - //left - if ((keys["a"] || keys["ArrowLeft"]) && ship.x > 0) { - ship.x -= ship.speed; - ship.direction = 4; - ship.frameX = 3; - ship.frameY = 0; - } - //down - if ((keys["s"] || keys["ArrowDown"]) && ship.y < canvas.height - ship.height) { - ship.y += ship.speed; - ship.direction = 3; - ship.frameX = 2; - ship.frameY = 0; - } - //right - if ((keys["d"] || keys["ArrowRight"]) && ship.x < canvas.width - ship.width) { - ship.x += ship.speed; - ship.direction = 2; - ship.frameX = 1; - ship.frameY = 0; - } - //diagonals; needed to change ship sprites - //Top left - if (((keys["w"] || keys["ArrowUp"]) && ship.y > sBHeight) && ((keys["a"] || keys["ArrowLeft"]) && ship.x > 0)) { - ship.direction = 8; - ship.frameX = 3; - ship.frameY = 1; - } - //Top right - if (((keys["w"] || keys["ArrowUp"]) && ship.y > sBHeight) && ((keys["d"] || keys["ArrowRight"]) && ship.x < canvas.width - ship.width)) { - ship.direction = 5; - ship.frameX = 0; - ship.frameY = 1; - } - //Bottom left - if (((keys["s"] || keys["ArrowDown"]) && ship.y < canvas.height - ship.height) && ((keys["a"] || keys["ArrowLeft"]) && ship.x > 0)) { - ship.direction = 7; - ship.frameX = 2; - ship.frameY = 1; - } - //Bottom right - if (((keys["s"] || keys["ArrowDown"]) && ship.y < canvas.height - ship.height) && ((keys["d"] || keys["ArrowRight"]) && ship.x < canvas.width - ship.width)) { - ship.direction = 6; - ship.frameX = 1; - ship.frameY = 1; - } -} - -//------------------------------LEFT SIDE-------------------------------- -function openHowTo() { - if (howToButton.classList.contains('greyed')) { - showEndGameText(); - } - else if (!howToButton.classList.contains('greyed')) { - playerControl = false; - howToScreen.classList.toggle('hidden'); //toggles how to screen - ship.x = canvas.width / 2 - ship.width / 2; - ship.y = canvas.height / 2 - ship.height / 2; - clickSound.play(); - } -} -function openMusicMenu() { - if (musicButton.classList.contains('greyed')) { - showEndGameText(); - } - else if (!musicButton.classList.contains('greyed')) { - playerControl = false; - musicScreen.classList.toggle('hidden'); - ship.x = canvas.width / 2 - ship.width / 2; - ship.y = canvas.height / 2 - ship.height / 2; - clickSound.play(); - } -} - -//--------------------------RIGHT SIDE------------------------------------ -function changeDevice() { - if (deviceButton.classList.contains('greyed')) { - showEndGameText(); - } - else if (!deviceButton.classList.contains('greyed')) { - if (!mobile) { //if switching to mobile - deviceButton.src = "mobile.png"; - //canvas & css - canvas.width = 500; - canvas.height = 350; - sBHeight = 30; - padding = 20; - tolerance = 30; - keysControl.classList.add('hidden'); - buttonControls.classList.remove('hidden'); - mobileControls.classList.remove('hidden'); - mobileCSS.setAttribute("href", "mobile.css"); - //sprites - currentSpeed = 1.5; - ship.x = canvas.width / 2 - 33, - ship.y = canvas.height / 2 - 33, - ship.width = 32; - ship.height = 32; - ast.speed = 0.5; - ast.width = 24; - ast.height = 24; - astRangeY = (canvas.height - padding) - (sBHeight + padding) - ast.height; //max-min -height of asteroid so it doesn't clip off - astRangeX = (canvas.width - padding) - padding - ast.width; - redAst = new Asteroid("redAst", "enemy", "Sprites/redAsteroid.png", ast.width, ast.height, 0, 0, false, false, 1, -1, 1); - redAst2 = new Asteroid("redAst2", "enemy", "Sprites/redAsteroid.png", ast.width * 2, ast.height * 2, 0, 0, false, false, 0.6, -1, -1); - redAst3 = new Asteroid("redAst3", "enemy", "Sprites/redAsteroid.png", ast.width * 3, ast.height * 3, 0, 0, false, false, 0.3, 1, 1); - redAst4 = new Asteroid("redAst4", "enemy", "Sprites/redAsteroid.png", ast.width * 1.5, ast.height * 1.5, 0, 0, false, false, 1.5, 1, -1); - cheese = new Asteroid("cheese", "friend", "Sprites/cheese.png", ast.width / 2, ast.height / 2, 0, 0, false); - mobile = true; - if (userInteracted) { - clickSound.play(); - } - } - else if (mobile) { //if switching to desktop - deviceButton.src = "desktop.png"; - //canvas - canvas.width = 1000; - canvas.height = 700; - sBHeight = 50; - padding = 30; - tolerance = 60; - keysControl.classList.remove('hidden'); - buttonControls.classList.add('hidden'); - //mobileControls.classList.add('hidden'); - mobileCSS.setAttribute("href", ""); - //sprites - ship.x = canvas.width / 2 - 33, - ship.y = canvas.height / 2 - 33, - ship.width = 64; - ship.height = 64; - ast.width = 48; - ast.height = 48; - astRangeY = (canvas.height - padding) - (sBHeight + padding) - ast.height; //max-min -height of asteroid so it doesn't clip off - astRangeX = (canvas.width - padding) - padding - ast.width; - redAst = new Asteroid("redAst", "enemy", "Sprites/redAsteroid.png", ast.width, ast.height, 0, 0, false, false, 1, -1, 1); - redAst2 = new Asteroid("redAst2", "enemy", "Sprites/redAsteroid.png", ast.width * 2, ast.height * 2, 0, 0, false, false, 0.6, -1, -1); - redAst3 = new Asteroid("redAst3", "enemy", "Sprites/redAsteroid.png", ast.width * 3, ast.height * 3, 0, 0, false, false, 0.3, 1, 1); - redAst4 = new Asteroid("redAst4", "enemy", "Sprites/redAsteroid.png", ast.width * 1.5, ast.height * 1.5, 0, 0, false, false, 1.5, 1, -1); - cheese = new Asteroid("cheese", "friend", "Sprites/cheese.png", ast.width / 2, ast.height / 2, 0, 0, false); - mobile = false; - clickSound.play(); - } - } -} -// update: temp change to stop annoyance -// if (window.innerWidth <= 980) { -// changeDevice(); -// } - -function openSkinsMenu() { - if (skinsButton.classList.contains('greyed')) { - showEndGameText(); - } - else if (!skinsButton.classList.contains('greyed')) { - playerControl = false; - if (skinsMenuScreen.classList.contains('hidden')) { - ship.x = 100; //move ship to side to see skins - ship.y = canvas.height / 2 - ship.height / 2; - ship.frameX = 0; - ship.frameY = 0; - } - if (!skinsMenuScreen.classList.contains('hidden')) { - ship.x = canvas.width / 2 - ship.width / 2; - ship.y = canvas.height / 2 - ship.height / 2; - ship.frameX = 0; - ship.frameY = 0; - } - skinsMenuScreen.classList.toggle('hidden'); - clickSound.play(); - } - updateUnlocks(); -} -function openAudioMenu() { - audioMenu.classList.toggle('hidden'); - clickSound.play(); - //testing spot -} -function toggleSFX() { - if (sFXRange.value > 0) { - sFXRange.value = 0; - } - else if (sFXRange.value == 0) { - sFXRange.value = 100; - clickSound.play(); - } -} -function toggleMusic() { - if (musicRange.value > 0) { - musicRange.value = 0; - } - else if (musicRange.value == 0) { - musicRange.value = 100; - clickSound.play(); - } -} -function clearData() { - window.localStorage.clear(); - scoreArray = []; - unlocks = []; - changeShipSkin('Sprites/alphaSS1.png') - handleScore(0); - explSound.play(); - console.log("Data Successfully Cleared."); - console.log(window.localStorage); -} -function closeAll() { - gameOver(); - //closes all UI - gameOverScreen.classList.add('hidden'); - howToScreen.classList.add('hidden'); - musicScreen.classList.add('hidden'); - audioMenu.classList.add('hidden'); - skinsMenuScreen.classList.add('hidden'); - menuMusic.pause(); - randomizeMenuMusic(); - menuMusic.play(); -} - -//-------------------------HIGHSCORES---------------------------------- -function toggleScores() { - if (scoreDisplayOpen) { - rightButton.style.left = "98%"; - scoreDisplay.style.left = "100%"; - scoreDisplayOpen = false; - clickSound.play(); - } - else if (!scoreDisplayOpen) { - rightButton.style.left = "78.8%"; - scoreDisplay.style.left = "80%"; - scoreDisplayOpen = true; - clickSound.play(); - } -} -//-------------------------OTHER------------------------------- -function showEndGameText() { - clearInterval(eGTInterval); - eGTCount = 0; - eGTFlash(); - eGTInterval = setInterval(eGTFlash, 600); -} -function eGTFlash() { - if (eGTCount > 3) { - clearInterval(eGTInterval); - endGameText.classList.add('hidden'); - } - else if (eGTCount % 2 == 0) { - endGameText.classList.remove('hidden'); - eGTCount += 1; - } - else if (eGTCount % 2 != 0) { - endGameText.classList.add('hidden'); - eGTCount += 1; - } -} - -startButton.addEventListener('click', startGame); -startButton.addEventListener('touchstart', startGame); -closeButton.addEventListener('click', closeAll); - -howToButton.addEventListener('click', openHowTo); -musicButton.addEventListener('click', openMusicMenu); -prevPageButton.addEventListener('click', prevMusicPage); -nextPageButton.addEventListener('click', nextMusicPage); - -deviceButton.addEventListener('click', changeDevice); -skinsButton.addEventListener('click', openSkinsMenu); -audioButton.addEventListener('click', openAudioMenu); - -rightButton.addEventListener('click', toggleScores); -scoreDisplay.addEventListener('click', toggleScores); \ No newline at end of file diff --git a/Scripts/levels.js b/Scripts/levels.js index 4e5b887..82f8831 100644 --- a/Scripts/levels.js +++ b/Scripts/levels.js @@ -1,175 +1,161 @@ -//level up detection & values -function detectLevelUp() { - if (score >= 0 && score < 5) { - level = 0; - } - else if (score >= 5 && score < 10) { - level = 1; - } - else if (score >= 10 && score < 20) { - level = 2; - } - else if (score >= 20 && score < 30) { - level = 3; - } - else if (score >= 30 && score < 50) { - level = 4; - } - else if (score >= 50 && score < 100) { - level = 5; - } - else if (score >= 100 && score < 150) { - level = 6; - } - else if (score >= 150 && score < 250) { - level = 7; - } - else if (score >= 250 && score < 500) { - level = 8; - } - else if (score >= 500 && score < 1000) { - level = 9; - } - else if (score >= 1000) { - level = 10; - } -} - //Changes to ship & asteroids as score increases +let phases = [5, 10, 15, 25, 50, 75, 100, 150, 250, 500, 1000]; +let speeds = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + function changeLevelUp() { - if (level == 0) { - if (!mobile) { currentSpeed = 3; } - else if (mobile) { currentSpeed = 1.5; } //starting values - ship.speed = currentSpeed; - if (!mobile) {ast.speed = 1;} - else if (mobile) {ast.speed = 0.5;} - } - if (level == 1 && !redAst.exist) { - currentSpeed = 4; - ship.speed = currentSpeed; - if (!redAst.exist) { - generateAsteroid(redAst); - lvlUpSound.play(); - } + if (score < phases[0]) { // <5 + if (currentSpeed < speeds[0]) { currentSpeed = speeds[0]; ship.speed = currentSpeed; } } - if (level == 2 && !redAst2.exist) { - currentSpeed = 5; - ship.speed = currentSpeed; - ast.speed = 1.5; - if (!redAst.exist) { - generateAsteroid(redAst); - lvlUpSound.play(); - } - if (!redAst2.exist) { - generateAsteroid(redAst2); - lvlUpSound.play(); - } + if ((phases[0] <= score)) { // 5+ + if (currentSpeed < speeds[1]) { currentSpeed = speeds[1]; ship.speed = currentSpeed; } + redAst.spawn(); } - if (level == 3 && !redAst3.exist) { - currentSpeed = 6; - ship.speed = currentSpeed; - ast.speed = 2; - if (!redAst.exist) { - generateAsteroid(redAst); - lvlUpSound.play(); - } - if (!redAst2.exist) { - generateAsteroid(redAst2); - lvlUpSound.play(); - } - if (!redAst3.exist) { - generateAsteroid(redAst3); - lvlUpSound.play(); - } + if ((phases[1] <= score)) { // 10+ + if (currentSpeed < speeds[2]) { currentSpeed = speeds[2]; ship.speed = currentSpeed; } + redAst2.spawn(); } - if (level == 4 && !cheese.exist) { - currentSpeed = 7; - ship.speed = currentSpeed; - ast.speed = 3; - if (!redAst.exist) { - generateAsteroid(redAst); - lvlUpSound.play(); - } - if (!redAst2.exist) { - generateAsteroid(redAst2); - lvlUpSound.play(); - } - if (!redAst3.exist) { - generateAsteroid(redAst3); - lvlUpSound.play(); - } - if (!cheese.exist && !slowDown) { - generateAsteroid(cheese); - cheeseCDFrame = 4; - lvlUpSound.play(); - } - + if ((phases[2] <= score)) { //15+ + if (currentSpeed < speeds[3]) { currentSpeed = speeds[3]; ship.speed = currentSpeed; } + redAst3.spawn(); } - if (level == 5 && !redAst4.exist) { - currentSpeed = 8; - if (cheese.exist) { //if cheese exists; slowdown not in effect - ship.speed = currentSpeed; - } - ast.speed = 4; - if (!redAst4.exist) { - generateAsteroid(redAst4); - lvlUpSound.play(); + if ((phases[3] <= score)) { //25+ + if (!sDInterval) { + if (currentSpeed < speeds[4]) { currentSpeed = speeds[4]; ship.speed = currentSpeed; } + cheese.spawn(); } } - if (level == 6 && !tripleDigit1) { - currentSpeed = 9; - if (cheese.exist) { //if cheese exists; slowdown not in effect - ship.speed = currentSpeed; - } - ast.speed = 5; - if (!tripleDigit1) { + if ((phases[4] <= score)) { // 50+ + if (!sDInterval && currentSpeed < speeds[5]) { currentSpeed = speeds[5]; ship.speed = currentSpeed; } + redAst4.spawn(); + } + if ((phases[5] <= score)) { // 75+ + if (!sDInterval && currentSpeed < speeds[6]) { currentSpeed = speeds[6]; ship.speed = currentSpeed; } + if (!hasUnlockedSnake) { unlocks = ["snake"]; - tripleDigit1 = true; + hasUnlockedSnake = true; lvlUpSound.play(); } } - if (level == 7 && !tripleDigit2) { - currentSpeed = 10; - if (cheese.exist) { //if cheese exists; slowdown not in effect - ship.speed = currentSpeed; - } - ast.speed = 6; - if (!tripleDigit2) { + if ((phases[6] <= score)) { // 100+ + if (!sDInterval && currentSpeed < speeds[7]) { currentSpeed = speeds[7]; ship.speed = currentSpeed; } + if (!hasUnlockedInverted) { unlocks = ["snake", "inverted"]; - tripleDigit2 = true; + hasUnlockedInverted = true; lvlUpSound.play(); } } - if (level == 8 && !tripleDigit3) { - currentSpeed = 12; - if (cheese.exist) { //if cheese exists; slowdown not in effect - ship.speed = currentSpeed; - } - ast.speed = 7; - if (!tripleDigit3) { + if ((phases[7] <= score)) { // 150+ + if (!sDInterval && currentSpeed < speeds[8]) { currentSpeed = speeds[8]; ship.speed = currentSpeed; } + if (!hasUnlockedAsteroid) { unlocks = ["snake", "inverted", "asteroid"]; - tripleDigit3 = true; + hasUnlockedAsteroid = true; lvlUpSound.play(); } } - if (level == 9 && !legendaryScore) { - currentSpeed *= 1.05; //every collection onwards will multiply speed by 105% - if (cheese.exist) { //if cheese exists; slowdown not in effect - ship.speed = currentSpeed; - } - ast.speed = 8; + if ((phases[8] <= score)) { // 250+ + if (!sDInterval && currentSpeed < speeds[9]) { currentSpeed = speeds[9]; ship.speed = currentSpeed; } if (!legendaryScore) { legendaryScore = true; lvlUpSound.play(); } } - if (level == 10) { - currentSpeed *= 1.1; //every collection onwards will multiply speed by 110% - if (cheese.exist) { //if cheese exists; slowdown not in effect + if (phases[9] <= score) { // 500+ + if (!sDInterval) { + currentSpeed *= 1.1; ship.speed = currentSpeed; - } - ast.speed = 9; + } //every collection onwards will multiply speed by 110% lvlUpSound.play(); console.log("game breaking score"); } +} + +function moveToAway(player, obstacle, speedFactor) { + // positive speedFactor is away, negative speedFactor is towards + dX = (player.x + player.radius) - (obstacle.x + obstacle.radius); + dY = (player.y + player.radius) - (obstacle.y + obstacle.radius); + //ship is on right + if (dX > tolerance / 4) { obstacle.x -= player.speed * speedFactor; } + //ship is on left + else if (dX < -tolerance / 4) { obstacle.x += player.speed * speedFactor; } + //ship is below + if (dY > tolerance / 4) { obstacle.y -= player.speed * speedFactor; } + //ship is above + else if (dY < -tolerance / 4) { obstacle.y += player.speed * speedFactor; } + detectCheeseBorderCol(); +} + +function handleAsteroids() { //moving & drawing asteroids as score goes up, every frame + drawAstArray.forEach(asteroid => { + if (asteroid.exist) { + asteroid.update(); + } + }); + if (cheese.exist) { + if (detectCircleCollision(ship, cheese, tolerance)) { + moveToAway(ship, cheese, 0.2); //unique move function + } + } + cheeseCD.src = "Sprites/cheeseCooldown" + JSON.stringify(sDCount) + ".png"; //!!! + ctx.drawImage(cheeseCD, cheeseCDx, cheeseCDy); + +} + +function updateUnlocks() { + //check scores + if (!unlocks.includes("Sprites/snakeSS1.png") && scoreArray[0] >= 100) { + unlocks.push("Sprites/snakeSS1.png"); + } + if (!unlocks.includes("Sprites/alphaInvertedSS1.png") && scoreArray[0] >= 150) { + unlocks.push("Sprites/alphaInvertedSS1.png"); + } + if (!unlocks.includes("Sprites/asteroidSS1.png") && scoreArray[0] >= 250) { + unlocks.push("Sprites/asteroidSS1.png"); + } + //update skins to be Unlocked or Greyed + if (unlocks.includes("Sprites/snakeSS1.png")) { + snakeSkin.classList.remove("greyed"); + snakeSkin.src = "Sprites/shipSnake.png"; //html image + window.localStorage.setItem('unlocks', JSON.stringify(unlocks)); + } + else { + snakeSkin.classList.add("greyed"); + snakeSkin.src = "Sprites/shipSnakeLocked.png"; + } + if (unlocks.includes("Sprites/alphaInvertedSS1.png")) { + invertedSkin.classList.remove("greyed"); + invertedSkin.src = "Sprites/shipAlphaInverted.png"; + window.localStorage.setItem('unlocks', JSON.stringify(unlocks)); + } + else { + invertedSkin.classList.add("greyed"); + invertedSkin.src = "Sprites/shipAlphaInvertedLocked.png"; + } + if (unlocks.includes("Sprites/asteroidSS1.png")) { + asteroidSkin.classList.remove("greyed"); + asteroidSkin.src = "Sprites/asteroid.png"; + window.localStorage.setItem('unlocks', JSON.stringify(unlocks)); + } + else { + asteroidSkin.classList.add("greyed"); + asteroidSkin.src = "Sprites/AsteroidLocked.png"; + } +} + +//score sorting +function handleScore(newScore) { + scoreArray.push(newScore); //add new score in + document.getElementById("finalScoreDisplay").innerHTML = score; //displays "Final Score:" + scoreArray.sort(function (a, b) { return b - a }); //sort array + for (i = 0; i <= 4; i++) { + if (!scoreArray[i]) { + scoreArray[i] = "000"; + } + document.querySelector('.score' + i).innerHTML = scoreArray[i]; //reset each of the scores in the score screen + } + window.localStorage.setItem('scoreArray', JSON.stringify(scoreArray)); + while (scoreArray.length > 5) { + scoreArray.pop(); + window.localStorage.setItem('scoreArray', JSON.stringify(scoreArray)); + } + updateUnlocks(); } \ No newline at end of file diff --git a/Scripts/setup.js b/Scripts/setup.js index d17361f..01a5941 100644 --- a/Scripts/setup.js +++ b/Scripts/setup.js @@ -17,98 +17,62 @@ canvas.height = 700; //general values let sBHeight = 50; //scoreBoard Height let padding = 30; //distance from borders for Grey & Red Asteroid generation -let tolerance = 60; //for cheese movement and range detection +let tolerance = 80; //for cheese movement and range detection //Scores let score = 0; -let scoreAmt = 5; //easily adjust grey asteroid points +let scoreAmt = 1; //easily adjust grey asteroid points let scoreArray = []; //levels & unlock detections let level = 0; -let tripleDigit1 = false; //level-ups to store in localStorage for skin unlocks & sound effect -let tripleDigit2 = false; -let tripleDigit3 = false; +let hasUnlockedSnake = false; //level-ups to store in localStorage for skin unlocks & sound effect +let hasUnlockedInverted = false; +let hasUnlockedAsteroid = false; let legendaryScore = false; let unlocks = []; -let defaultUnlocks = ['Sprites/alphaSS1.png', 'Sprites/betaSS1.png', 'Sprites/ufoSS1.png'] +let defaultUnlocks = ['Sprites/alphaSS1.png', 'Sprites/betaSS1.png', 'Sprites/ufoSS1.png']; //-------------------------------BUTTONS & SCREENS------------------------------- -//RIGHT SIDE -//how-to -let howToButton = document.querySelector('.howToButton'); -let howToScreen = document.querySelector('.howToScreen'); -//music selection -let musicButton = document.querySelector('.musicButton'); -let musicScreen = document.querySelector('.musicScreen'); -let musicPage1 = document.querySelector('.musicPage1'); -let musicPage2 = document.querySelector('.musicPage2'); -let musicPage3 = document.querySelector('.musicPage3'); -let prevPageButton = document.querySelector('.prevPageButton'); -let nextPageButton = document.querySelector('.nextPageButton'); +//ALL UI ELEMENTS (listed by Class or by ID) +let uIButtonsByClassList = ['.howToButton', '.musicButton', + '.deviceButton', '.keyControls', '.skinsButton', '.snakeSkin', '.invertedSkin', '.asteroidSkin', '.audioButton', '.musicToggleButton', '.sFXButton', '.closeButton', + '.startButton', '.leftHexButton', '.rightHexButton', '.scoreDisplay', '.backgroundImg']; +let uIScreensByClassList = ['.howToScreen', '.skinsMenuScreen', '.audioMenu', '.startScreen', '.gameOverScreen', '.endGameFirstText']; +// '.musicScreen', +let uIScreensByClass = []; +uIButtonsByClassList.forEach(element => { + window[element.substring(1)] = document.querySelector(element); +}); //links all UI elements to JS file by class +uIScreensByClassList.forEach(element => { + window[element.substring(1)] = document.querySelector(element); + uIScreensByClass.push(window[element.substring(1)]); +}); -//LEFT SIDE -//Device Button & Controls -let deviceButton = document.querySelector('.deviceButton'); -let mobileCSS = document.querySelector('.mobileCSS'); -let mobile = false; -let keysControl = document.querySelector('.keyControls'); -let keys = []; -let buttonControls = document.querySelector('.buttonControls'); -let mobileControls = document.querySelector('.mobileControls'); -let mBUp = document.querySelector('.mBUp'); -let mBRight = document.querySelector('.mBRight'); -let mBLeft = document.querySelector('.mBLeft'); -let mBDown = document.querySelector('.mBDown'); -//skin menu -let skinsButton = document.querySelector('.skinsButton'); -let skinsMenuScreen = document.querySelector('.skinsMenuScreen'); -//unlockable skins -let snakeSkin = document.querySelector('.snakeSkin'); -let invertedSkin = document.querySelector('.invertedSkin'); -let asteroidSkin = document.querySelector('.asteroidSkin'); -//audio & audio menu -let audioButton = document.querySelector('.audioButton'); -let audioMenu = document.querySelector('.audioMenu'); -let sFXButton = document.querySelector('.sFXButton'); -let sFXRange = document.getElementById('sFXRange'); -let musicToggleButton = document.querySelector('.musicToggleButton'); -let musicRange = document.getElementById('musicRange'); -//Close all -let closeButton = document.querySelector('.closeButton'); +let uIElementsByID = ['sFXRange', 'musicRange']; +uIElementsByID.forEach(element => { + window[element] = document.getElementById(element); +}); -//OTHER BUTTONS & SCREENS -let startButton = document.querySelector('.startButton'); -let startScreen = document.querySelector('.startScreen'); -let gameOverScreen = document.querySelector('.gameOverScreen'); +let keys = []; //style elements -let paragraphs = document.getElementsByTagName('p'); //'end the current game first!' Flashing text -let endGameText = document.querySelector('.endGameText'); let eGTCount = 0; let eGTInterval; //Highscores menu -let rightButton = document.querySelector('.rightButton'); -rightButton.style.left = "98%"; -let scoreDisplay = document.querySelector('.scoreDisplay'); +rightHexButton.style.left = "98%"; scoreDisplay.style.left = "100%"; -let scoreDisplayOpen = false; +let scoreDisplayOpen = false; //to move the score button & display together //Booleans let userInteracted = false; //chrome update for bkg music let playerControl = false; //for player control & menu control -let gameOverT = false; //needs changes -let firstDeath = false; //for Explosion to begin cycling; needs changes //-------------------------------BACKGROUNDS------------------------------- -let backgroundImg = document.querySelector('.background-img'); -let blueSpace = "Backgrounds/blueSpace.jpg"; -let purpleSpace = "Backgrounds/purpleSpace.jpg"; -let JamesWebb = "Backgrounds/JamesWebb.jpg"; -let orbit = "Backgrounds/Orbit.jpg"; -let hatSpace = "Backgrounds/hatSpace.png"; -let galaxyAnim = "Backgrounds/galaxyAnim.gif"; -let purpleAnim = "Backgrounds/purpleAnim.gif"; -let blueNebula = "Backgrounds/blueNebulaAnim.gif"; +let bkgArray = ["blueSpace.jpg", "purpleSpace.jpg", "JamesWebb.jpg", "Orbit.jpg", "hatSpace.png", + "galaxyAnim.gif", "purpleAnim.gif", "blueNebulaAnim.gif"]; +bkgArray.forEach(element => { + window[element.slice(0, -4)] = "Backgrounds/" + element; +}); -//-------------------------------LOAD-IN----------------------------------- +//-------------------------------RETRIEVAL----------------------------------- //BKG RETRIEVAL if (window.localStorage.getItem('bkgImg')) { backgroundImg.src = JSON.parse(window.localStorage.getItem('bkgImg')); @@ -117,73 +81,113 @@ if (window.localStorage.getItem('bkgImg')) { window.localStorage.setItem('bkgImg', JSON.stringify(backgroundImg.src)); } //SCORE RETRIEVAL +//window.localStorage.setItem('scoreArray','[1,2,3,4,5]'); //debug if (window.localStorage.getItem('scoreArray')) { scoreArray = JSON.parse(window.localStorage.getItem('scoreArray')); for (i = 0; i < 5; ++i) { - if (!scoreArray[i]) { + if (!scoreArray[i] || scoreArray[i] == 0) { scoreArray[i] = "000"; } document.querySelector('.score' + i).innerHTML = scoreArray[i]; } - console.log("Highscores retrieved."); - console.log(window.localStorage.getItem('scoreArray')); + console.log("Highscores retrieved. " + window.localStorage.getItem('scoreArray')); } -//MENU MUSIC -//--------------------------------SPRITES------------------------------- +//-------------------------------SPRITES & OBJECTS---------------------------- // SHIP let currentSpeed = 3; //speed variable that will change -class Player { - constructor(source, width, height, x, y, frameX, frameY, speed, dir, imm, exp, expFrame) { //speedF = speed factor - this.image = new Image(); - this.image.src = source; - this.width = width; - this.height = height; - this.x = x; - this.y = y; - this.frameX = frameX; - this.frameY = frameY; - this.radius = width / 2; - this.speed = speed; - this.direction = dir; - this.immunity = imm; - this.exploded = exp; - this.explosionFrame = expFrame; - } - move() { - this.x += ast.speed * this.xF * this.dirX; - this.y += ast.speed * this.yF * this.dirY; - detectBorderCollision(this); //collision with edge of screen - } +let ship = { + image: new Image(), + width: 67, + height: 66, + x: canvas.width / 2 - 33, + y: canvas.height / 2 - 33, + frameX: 0, + frameY: 0, + radius: 67 / 2, + speed: currentSpeed, + direction: "", + immunity: false, + breathingRoom: 5, + exploded: false, + explosionInterval: null, + explosionFrame: 1, draw(img, sX, sY, sW, sH, dX, dY, dW, dH) { - this.image.src=img; - //drawCircle("white", this); + this.image.src = img; + //drawCircle("white", this); //debug ctx.drawImage(this.image, sX, sY, sW, sH, dX, dY, dW, dH); - } - resetPos() { - this.x = canvas.width/2-33; - this.y = canvas.width/2-33; + }, + resetPos() { ship.x = canvas.width / 2 - ship.width / 2; ship.y = canvas.height / 2 - ship.height / 2; }, + getImmunity(duration) { ship.immunity = true; setTimeout(function () { ship.immunity = false }, duration); }, + changeSkin(skinName) { + if (window.localStorage.getItem('unlocks') && JSON.parse(window.localStorage.getItem('unlocks')).includes(skinName)) { + currentSkin = skinName; + } else if (defaultUnlocks.includes(skinName)) { + currentSkin = skinName; + } + window.localStorage.setItem('skinName', JSON.stringify(currentSkin)); + clickSound.play(); + }, + upPressed() { return ((keys["w"] || keys["ArrowUp"]) && ship.y > sBHeight); }, + downPressed() { return ((keys["s"] || keys["ArrowDown"]) && ship.y < canvas.height - ship.height); }, + leftPressed() { return ((keys["a"] || keys["ArrowLeft"]) && ship.x > 0); }, + rightPressed() { return ((keys["d"] || keys["ArrowRight"]) && ship.x < canvas.width - ship.width); }, + move() { + if (this.upPressed()) { //up, left right center + if (this.leftPressed()) { + ship.y -= ship.speed / Math.sqrt(2); + ship.x -= ship.speed / Math.sqrt(2); + ship.frameX = 3; + ship.frameY = 1; + } else if (this.rightPressed()) { + ship.y -= ship.speed / Math.sqrt(2); + ship.x += ship.speed / Math.sqrt(2); + ship.frameX = 0; + ship.frameY = 1; + } else { + ship.y -= ship.speed; + ship.frameX = 0; + ship.frameY = 0; + } + } else if (this.downPressed()) { //down, left right center + if (this.leftPressed()) { + ship.y += ship.speed / Math.sqrt(2); + ship.x -= ship.speed / Math.sqrt(2); + ship.frameX = 2; + ship.frameY = 1; + } else if (this.rightPressed()) { + ship.y += ship.speed / Math.sqrt(2); + ship.x += ship.speed / Math.sqrt(2); + ship.frameX = 1; + ship.frameY = 1; + } else { + ship.y += ship.speed; + ship.frameX = 2; + ship.frameY = 0; + } + } else if (this.leftPressed()) { //left + ship.x -= ship.speed; + ship.frameX = 3; + ship.frameY = 0; + } else if (this.rightPressed()) { //right + ship.x += ship.speed; + ship.frameX = 1; + ship.frameY = 0; + } + }, + cycleExplosionFrame() { + if (!ship.explosionInterval) { + ship.explosionInterval = setInterval(function () { + if (ship.explosionFrame < 10) { + ship.explosionFrame++; + } + else { + ship.explosionFrame = 1; + } + }, 100); + } } } -let ship = new Player("Sprites/shipAlpha.png", 67, 66, canvas.width/2-33, canvas.height/2-33, 0, 0, currentSpeed, 1, false, false, 1); -// update: moved to constructor -// let ship = { -// sprite: new Image(), -// frameX: 0, -// frameY: 0, -// width: 67, -// height: 66, -// radius: 32, -// x: canvas.width / 2 - 33, -// y: canvas.height / 2 - 33, -// speed: currentSpeed, -// direction: 1, -// immunity: false, -// exploded: false, -// explosionFrame: 1, -// } -let explode1 = new Image(); -explode1.src = "BlueExplosion/blue" + JSON.stringify(ship.explosionFrame) + ".png"; // SHIP SPRITE RETRIEVAL (has to be below) let currentSkin = JSON.parse(window.localStorage.getItem('skinName')) @@ -198,99 +202,112 @@ if (JSON.parse(window.localStorage.getItem('unlocks'))) { ship.image.src = currentSkin; // ASTEROIDS -let ast = { - name: "greyAst", - sprite: new Image(), - width: 48, - height: 48, - radius: 24, - x: 0, - y: 0, - exist: false, - speed: 1, - moving: false, -} -ast.sprite.src = "Sprites/Asteroid.png"; -let astRangeY = (canvas.height - padding) - (sBHeight + padding) - ast.height; //max-min -height of asteroid so it doesn't clip off -let astRangeX = (canvas.width - padding) - padding - ast.width; +let astWidth = 48; +let astHeight = 48; +let astRangeY = (canvas.height - padding) - (sBHeight + padding) - astHeight; //max-min -height of asteroid so it doesn't clip off +let astRangeX = (canvas.width - padding) - padding - astWidth; class Asteroid { - constructor(name, type, source, width, height, exist, moving, speedF, dirX, dirY) { //speedF = speed factor - this.name = name; - this.type = type; + constructor(source, width, height, exist, speed, dirX, dirY, genTime) { this.image = new Image(); this.image.src = source; this.width = width; this.height = height; - // may cause glitches so they are set to null - // this.x = Math.random() * (astRangeX) + padding; - // this.y = Math.random() * (astRangeY) + sBHeight + padding; - this.x = null; + this.x = null; //defined by other functions that generate this.y = null; this.radius = width / 2; + this.exist = exist; - this.moving = moving; - this.xF = Math.random() * speedF; //x multiplication factor; random to create new vectors - this.yF = Math.random() * speedF; //(vector = new diagonal angles) + this.moving; + this.speed = speed; + this.xF = Math.random() * this.speed; //x multiplication factor; random to create new vectors + this.yF = Math.random() * this.speed; //(vector = new diagonal angles) this.dirX = dirX; this.dirY = dirY; + + this.genTime = genTime; + this.genCount = 0; this.moveInterval; } + spawn() { //first time generated + if (!this.exist) { + this.generate(); + lvlUpSound.play(); + } + } + generate() { + this.x = Math.random() * (astRangeX) + padding; + this.y = Math.random() * (astRangeY) + sBHeight + padding; + ship.getImmunity(300); + + this.genCount = 0; + this.moving = false; + this.exist = true; + } + update() { + ctx.save(); //save all other canvas elements + //first do the alpha change & spawning given genTime + if (this.genCount < this.genTime) { + ctx.globalAlpha = Math.round((this.genCount / this.genTime) * 10) / 10; + this.genCount += 1; + } else if (this.genCount >= this.genTime) { //then move on subsequent updates + this.moving = true; + this.move(); + } + this.draw(); + ctx.restore(); //restore all other canvas elements + } move() { - this.x += ast.speed * this.xF * this.dirX; - this.y += ast.speed * this.yF * this.dirY; + this.x += this.speed * this.xF * this.dirX; + this.y += this.speed * this.yF * this.dirY; detectBorderCollision(this); //collision with edge of screen } - drawAst() { - //drawCircle("red", this); + draw() { + //drawCircle('red',this); //debug ctx.drawImage(this.image, this.x, this.y, this.width, this.height); } } +let greyAst = new Asteroid("Sprites/Asteroid.png", astWidth, astHeight, false, 0, 0, 0, 30) // Red Enemies -let redAst = new Asteroid("redAst", "enemy", "Sprites/redAsteroid.png", ast.width, ast.height, false, false, 1, -1, 1); -let redAst2 = new Asteroid("redAst2", "enemy", "Sprites/redAsteroid.png", ast.width * 2, ast.height * 2, false, false, 0.6, -1, -1); -let redAst3 = new Asteroid("redAst3", "enemy", "Sprites/redAsteroid.png", ast.width * 3, ast.height * 3, false, false, 0.3, 1, 1); -let redAst4 = new Asteroid("redAst4", "enemy", "Sprites/redAsteroid.png", ast.width * 1.5, ast.height * 1.5, false, false, 1.5, 1, -1); +let redAst = new Asteroid("Sprites/redAsteroid.png", astWidth, astHeight, false, 2, -1, 1, 50); +let redAst2 = new Asteroid("Sprites/redAsteroid.png", astWidth * 2, astHeight * 2, false, 1.5, -1, -1, 50); +let redAst3 = new Asteroid("Sprites/redAsteroid.png", astWidth * 3, astHeight * 3, false, 1, 1, 1, 100); +let redAst4 = new Asteroid("Sprites/redAsteroid.png", astWidth * 1.5, astHeight * 1.5, false, 3, 1, -1, 100); // Yellow Slowdown High Reward -let cheese = new Asteroid("cheese", "friend", "Sprites/cheese.png", ast.width / 2, ast.height / 2, 0, 0, false); +let cheese = new Asteroid("Sprites/cheese.png", astWidth / 2, astHeight / 2, false, 0, 0, 0, 30); // slowDown effect -let cheeseCDFrame = 1; let cheeseCD = new Image(); -cheeseCD.src = "Sprites/cheeseCooldown" + JSON.stringify(cheeseCDFrame) + ".png"; -let slowDown = false; +let cheeseCDx = 900; +let cheeseCDy = 80; let sDCount = 1; let sDInterval; +cheeseCD.src = "Sprites/cheeseCooldown" + JSON.stringify(sDCount) + ".png"; // Blue Powerup !!! -let plasma = new Asteroid("plasma", "friend", "Sprites/cheese.png", ast.width / 3, ast.height / 3, 0, 0, false, false, 1, Math.random() * 2 - 1, Math.random() * 2 - 1); +//let plasma = new Asteroid("Sprites/cheese.png", astWidth / 3, astHeight / 3, false); // shield effect -let shieldImg = new Image(); + +let drawAstArray = [greyAst, redAst, redAst2, redAst3, redAst4, cheese]; +let enemyAstArray = [redAst, redAst2, redAst3, redAst4]; //start & end functions function startGame() { //reset values score = 0; - level = 0; - playerControl = true; //maybe i can merge these two - gameOverT = false; + playerControl = true; //Reset ship ship.image.src = currentSkin; - ship.x = canvas.width / 2 - ship.width / 2; - ship.y = canvas.height / 2 - ship.height / 2; + ship.resetPos(); currentSpeed = 3; ship.speed = currentSpeed; ship.immunity = false; - slowDown = false; - clearInterval(sDInterval); + ship.exploded = false; //reset levelup changes - ast.speed = 1; - redAst.exist = false; - redAst2.exist = false; - redAst3.exist = false; - redAst4.exist = false; - cheese.exist = false; - tripleDigit1 = false; - tripleDigit2 = false; - tripleDigit3 = false; + drawAstArray.forEach(asteroid => { + asteroid.exist = false; + }) + hasUnlockedSnake = false; //!!! + hasUnlockedInverted = false; + hasUnlockedAsteroid = false; legendaryScore = false; //hide ui @@ -300,23 +317,25 @@ function startGame() { //reset values //grey out buttons howToButton.classList.add('greyed'); musicButton.classList.add('greyed'); - deviceButton.classList.add('greyed'); skinsButton.classList.add('greyed'); - //start the music! + //deviceButton.classList.add('greyed'); + //start the music menuMusic.pause(); bkgMusic.play(); //generate Asteroid - generateAsteroid(ast); + greyAst.generate(); } function gameOver() { playerControl = false; - gameOverT = true; ship.exploded = true; + explSound.play(); + bkgMusic.pause(); menuMusic.play(); - explSound.play(); + clearInterval(sDInterval); + sDCount = 1; handleScore(score); //display UI startButton.classList.remove('hidden'); @@ -324,10 +343,6 @@ function gameOver() { //allow button presses howToButton.classList.remove('greyed'); musicButton.classList.remove('greyed'); - deviceButton.classList.remove('greyed'); skinsButton.classList.remove('greyed'); + //deviceButton.classList.remove('greyed'); } - -document.addEventListener('click', function () { - userInteracted = true; -}) \ No newline at end of file diff --git a/Scripts/ui.js b/Scripts/ui.js new file mode 100644 index 0000000..e03242c --- /dev/null +++ b/Scripts/ui.js @@ -0,0 +1,342 @@ + + + +function openAudioMenu() { + audioMenu.classList.toggle('hidden'); + clickSound.play(); + //debug +} +function toggleSFX() { + if (sFXRange.value > 0) { + sFXRange.value = 0; + } + else if (sFXRange.value == 0) { + sFXRange.value = 100; + clickSound.play(); + } +} +function toggleMusic() { + if (musicRange.value > 0) { + musicRange.value = 0; + } + else if (musicRange.value == 0) { + musicRange.value = 100; + clickSound.play(); + } +} +function clearData() { + window.localStorage.clear(); + scoreArray = []; + for (i = 0; i <= 4; i++) { + scoreArray[i] = "000"; + document.querySelector('.score' + i.toString()).innerHTML = scoreArray[i]; + } + unlocks = []; + ship.changeSkin('Sprites/alphaSS1.png'); + backgroundImg.src = blueSpace; + + explSound.play(); + updateUnlocks(); + + console.log("Data Successfully Cleared."); + console.log(window.localStorage); +} +function closeAll() { + gameOver(); + //closes all UI + uIScreensByClass.forEach(element => { + element.classList.add('hidden'); + }); + + randomizeMenuMusic(); +} + +//-------------------------HIGHSCORES---------------------------------- +function toggleScores() { + if (scoreDisplayOpen) { + rightHexButton.style.left = "98%"; + scoreDisplay.style.left = "100%"; + scoreDisplayOpen = false; + clickSound.play(); + } + else if (!scoreDisplayOpen) { + rightHexButton.style.left = "78.8%"; + scoreDisplay.style.left = "80%"; + scoreDisplayOpen = true; + clickSound.play(); + } +} +//-------------------------OTHER------------------------------- +function showEndGameFirstText() { + clearInterval(eGTInterval); + eGTCount = 0; + eGTFlash(); + eGTInterval = setInterval(eGTFlash, 600); +} +function eGTFlash() { + if (eGTCount > 3) { + clearInterval(eGTInterval); + endGameFirstText.classList.add('hidden'); + } + else if (eGTCount % 2 == 0) { + endGameFirstText.classList.remove('hidden'); + eGTCount += 1; + } + else if (eGTCount % 2 != 0) { + endGameFirstText.classList.add('hidden'); + eGTCount += 1; + } +} + +// All event Listeners +startButton.addEventListener('click', startGame); +//startButton.addEventListener('touchstart', startGame); +closeButton.addEventListener('click', closeAll); + +howToButton.addEventListener('click', () => openMenu(howToButton, howToScreen)); + +// ------------------------ +function openMenu(button, screen) { + if (button.classList.contains('greyed')) { + showEndGameFirstText(); + } + else if (!button.classList.contains('greyed')) { + if (screen.classList.contains('skinsMenuScreen') && screen.classList.contains('hidden')) { + ship.x = 100; //move ship to side to see skins + ship.y = canvas.height / 2 - ship.height / 2; + ship.frameX = 0; + ship.frameY = 0; + updateUnlocks(); + } else if (!screen.classList.contains('hidden')) { + ship.resetPos(); + } + screen.classList.toggle('hidden'); //toggles screen + clickSound.play(); + } +} +//navigation +function prevMusicPage() { + //if on page 1 go to page 3 + if (!musicPage1.classList.contains("hidden")) { + musicPage1.classList.add("hidden"); + musicPage3.classList.remove("hidden"); + } + //if on page 2 go to page 1 + else if (!musicPage2.classList.contains("hidden")) { + musicPage2.classList.add("hidden"); + musicPage1.classList.remove("hidden"); + } + //if on page 3 go to page 2 + else if (!musicPage3.classList.contains("hidden")) { + musicPage3.classList.add("hidden"); + musicPage2.classList.remove("hidden"); + } + clickSound.play(); +} +function nextMusicPage() { + //if on page 1 go to page 2 + if (!musicPage1.classList.contains("hidden")) { + musicPage1.classList.add("hidden"); + musicPage2.classList.remove("hidden"); + } + //if on page 2 go to page 3 + else if (!musicPage2.classList.contains("hidden")) { + musicPage2.classList.add("hidden"); + musicPage3.classList.remove("hidden"); + } + //if on page 3 go to page 1 + else if (!musicPage3.classList.contains("hidden")) { + musicPage3.classList.add("hidden"); + musicPage1.classList.remove("hidden"); + } + clickSound.play(); +} +//-------------- +const musicData = { + page1: [ + { + icon: '👾', + title: 'Raining Bits (default)', + artist: 'Gundatsch', + url: 'https://soundcloud.com/gundatsch', + src: 'Audio/rainingBitsGundatsch.ogg' + }, + // { + // icon: '🔫', + // title: 'NES Shooter - Boss', + // artist: 'SketchyLogic', + // url: 'https://soundcloud.com/sketchylogic', + // src: 'Audio/NESBossIntroSketchyLogic.wav' + // }, !!! + { + icon: '?', + title: 'WIP (no sound)', + artist: 'N/A', + url: '', + src: 'Audio/pop.ogg' + }, + { + icon: '👹', + title: 'Lines of Code', + artist: 'Trevor Lentz', + url: 'https://open.spotify.com/artist/3AjWA7sRmeZSKqr7PoKL6k', + src: 'Audio/linesOfCodeTLentz.mp3' + }, + { + icon: '🎼', + title: 'Cyber Sonata', + artist: 'Joth', + url: 'https://opengameart.org/users/joth', + src: 'Audio/cyberSonataJoth.mp3' + }, + { + icon: '🏎', + title: 'Hyper Ultra-Racing', + artist: 'cynicmusic', + url: 'https://cynicmusic.com', + src: 'Audio/hyperUltraRacingcynicmusic.wav' + }, + { + icon: '🌠', + title: 'Lunar Arrow', + artist: 'mmry', + url: 'https://soundcloud.com/mmry/', + src: 'Audio/lunarArrowmmry.mp3' + }, + ], + page2: [ + { + icon: '☕', + title: 'Bossa Nova', + artist: 'Joth', + url: 'https://opengameart.org/users/joth', + src: 'Audio/bossaNovaJoth.mp3' + }, + { + icon: '🌊', + title: 'Enchanted Tiki 86', + artist: 'cynicmusic', + url: 'https://cynicmusic.com', + src: 'Audio/ET86cynicmusic.mp3' + }, + { + icon: '⭐', + title: 'Chiptune Adventures', + artist: 'Juhani Junkala', + url: 'https://juhanijunkala.com/', + src: 'Audio/chiptunesJJunkala.wav' + }, + { + icon: '🛸', + title: 'Thrust Sequence', + artist: 'matthewpablo', + url: 'https://www.matthewpablo.com', + src: 'Audio/thrustSequenceMPablo.mp3' + }, + { + icon: '🌑', + title: 'Orbital Colossus', + artist: 'matthewpablo', + url: 'https://www.matthewpablo.com', + src: 'Audio/orbitalColossusMPablo.mp3' + }, + { + icon: '🎸', + title: 'The Recon Mission', + artist: 'Zander Noriega', + url: 'https://twitter.com/ZanderNoriega', + src: 'Audio/theReconMissionZNoriega.mp3' + }, + ] +}; +function createMusicTile(song) { + return ` +
+
${song.icon}
+
${song.title}
+

${song.artist}

+
+ `; +} + +function createMusicPage(pageNumber) { + if (pageNumber == 3) { + + } else { + const pageSongs = musicData[`page${pageNumber}`]; + const row1 = pageSongs.slice(0, 3); + const row2 = pageSongs.slice(3, 6); + return ` +
+ ${row1.map(createMusicTile).join('')} +
+
+ ${row2.map(createMusicTile).join('')} +
+ `; + } +} + +function createMusicScreen() { + const musicScreen = document.createElement('div'); + musicScreen.classList.add('musicScreen', 'fs32', 'hidden'); + + const heading = ` +

+ + MUSIC + +

+ `; + + musicScreen.innerHTML = ` + ${heading} +
+ ${createMusicPage(1)} +
+ + + `; + + document.body.appendChild(musicScreen); +} + +createMusicScreen(); +let musicItems = ['.musicScreen', '.prevPageButton', '.nextPageButton', '.musicPage1', '.musicPage2', '.musicPage3',] +musicItems.forEach(element => { + window[element.substring(1)] = document.querySelector(element); +}) + +musicButton.addEventListener('click', () => openMenu(musicButton, musicScreen)); +prevPageButton.addEventListener('click', prevMusicPage); +nextPageButton.addEventListener('click', nextMusicPage); + +//deviceButton.addEventListener('click', changeDevice); +skinsButton.addEventListener('click', () => openMenu(skinsButton, skinsMenuScreen)); +audioButton.addEventListener('click', openAudioMenu); + +rightHexButton.addEventListener('click', toggleScores); +scoreDisplay.addEventListener('click', toggleScores); + +//keyboard +window.addEventListener("keydown", function (e) { //creates an array to detect keys + keys[e.key] = true; + //console.log(e.key); +}); +window.addEventListener("keyup", function (e) { //deletes any keys in the array to save memory + delete keys[e.key]; +}); + +document.addEventListener('click', function () { + userInteracted = true; +}); //make chrome happy; no DOM errors when trying to play music before user \ No newline at end of file diff --git a/index.html b/index.html index 69384fb..f175c5c 100644 --- a/index.html +++ b/index.html @@ -11,20 +11,20 @@ - +
Your browser does not support HTML Canvas - Background + Background
Ast-Emmental -

A game developed in html by Marcus Lim

+

A vanilla JavaScript game by Marcus Lim

- +

HIGHSCORES

    @@ -35,9 +35,9 @@

    HIGHSCORES

  1. 000
- + - - - -
@@ -69,9 +57,9 @@
FINAL SCORE: