diff --git a/front/assets/Background.jpg b/front/assets/Background.jpg new file mode 100644 index 0000000..edda548 Binary files /dev/null and b/front/assets/Background.jpg differ diff --git a/front/assets/applause.mp3 b/front/assets/applause.mp3 new file mode 100644 index 0000000..c673fb7 Binary files /dev/null and b/front/assets/applause.mp3 differ diff --git a/front/assets/downArrowDynamic.png b/front/assets/downArrowDynamic.png new file mode 100644 index 0000000..59aa507 Binary files /dev/null and b/front/assets/downArrowDynamic.png differ diff --git a/front/assets/electroSportRock.mp3 b/front/assets/electroSportRock.mp3 new file mode 100644 index 0000000..218f380 Binary files /dev/null and b/front/assets/electroSportRock.mp3 differ diff --git a/front/assets/favicon.ico b/front/assets/favicon.ico new file mode 100644 index 0000000..0fbb2dc Binary files /dev/null and b/front/assets/favicon.ico differ diff --git a/front/assets/github.png b/front/assets/github.png new file mode 100644 index 0000000..29d5d1f Binary files /dev/null and b/front/assets/github.png differ diff --git a/front/assets/leftArrowDynamic.png b/front/assets/leftArrowDynamic.png new file mode 100644 index 0000000..b6f17d3 Binary files /dev/null and b/front/assets/leftArrowDynamic.png differ diff --git a/front/assets/paranoia.mp3 b/front/assets/paranoia.mp3 new file mode 100644 index 0000000..60095d0 Binary files /dev/null and b/front/assets/paranoia.mp3 differ diff --git a/front/assets/pause.png b/front/assets/pause.png new file mode 100644 index 0000000..2ebe9df Binary files /dev/null and b/front/assets/pause.png differ diff --git a/front/assets/play.png b/front/assets/play.png new file mode 100644 index 0000000..d26ad38 Binary files /dev/null and b/front/assets/play.png differ diff --git a/front/assets/proposalREADME.md b/front/assets/proposalREADME.md new file mode 100644 index 0000000..3209d92 --- /dev/null +++ b/front/assets/proposalREADME.md @@ -0,0 +1,72 @@ +# tapTapRevolution + +### Overview + +Tap Tap Revolution(TTR) is a take on the classic arcade game known as Dance Dance Revolution(DDR) + +DDR was a single or multi-player game where the players attempted to "dance" to the music and directional arrows that move up the screen. Towards the top of the screen there is a row of static arrows representing the four possible directional arrows: up, down, left, and right. + +The objective is to time your steps on the appropriate directional arrow key of the arcade machine to try to trigger the key just as the arrow moves on top of the respective arrow in the static row. Doing so will trigger a visual cue indicating that you've successfully registered the directional arrow and you will accrue points. + +If the player fails to trigger the key at the appropriate time, the arrow will move past the static row and off the screen. Users will be able to play the game through the duration of the song in an effort to get as high of a score as possible. + +### Functionality & MVP + +In TTR, players will be able to: +- [ ] Have a completely interactive experience with the game's single, dynamic screen. +- [ ] Adjust the speed of the game. +- [ ] Keep track of their score. +- [ ] Mute on/of, start and pause the game. +- [ ] Access a straightforward tutorial on how to play + +### Wireframes + +TTR will consist of a single screen with the rendering canvas, a mute button, an about button revealing info about the app, and nav links to the project's Github and my LinkedIn. + +The simulation canvas will also include a button to control volume on/off as well as start and pause. + +![alt text](https://imgur.com/ya6pyMx.png) + +### Technologies + +TTR will be made using the following technologies: + + +There will be two scripts involved for this project: + +`screen.js`: this script will govern the logic handling the DOM elements. + +`tapTapRev.js`: this script will handle the logic of the game itself. + +### Implementation Timeline + +Over the weekend: +- [ ] Went through HTML Canvas tutorials to learn about eventh handling and collisions. +- [ ] Researched how to render the special effects of the game. + +Day 1: +- [ ] Set up the canvas as well as the static assets(row of static arrows that will catch the moving arrows) via the `tapTapRev.js` file +- [ ] Finish rendering the dynamic arrows and begin to set up the logic of registering the arrows with the right input. + +Day 2: +- [ ] Finish the collision detection between dynamic and static arrows. +- [ ] Figure out and render the animated aspect of the arrows, moving and dynamic. + +Day 3: +- [ ] Finish styling. +- [ ] Figure out and implement the music aspect of the app. +- [ ] Build the points system of the game. + +Day 4: +- [ ] Render an appropriate background. +- [ ] Set up the about and various nav links, final touches. + +### Bonus Features + +Some ways the game could grow in the future: +- [ ] Adding a simple Node.js backend to persist state to keep track of high scores. +- [ ] Introduce a multiplayer option with interactive controls for two players. diff --git a/front/assets/restart.png b/front/assets/restart.png new file mode 100644 index 0000000..f60f945 Binary files /dev/null and b/front/assets/restart.png differ diff --git a/front/assets/rightArrowDynamic.png b/front/assets/rightArrowDynamic.png new file mode 100644 index 0000000..dcbcc2c Binary files /dev/null and b/front/assets/rightArrowDynamic.png differ diff --git a/front/assets/sound.png b/front/assets/sound.png new file mode 100644 index 0000000..3a07765 Binary files /dev/null and b/front/assets/sound.png differ diff --git a/front/assets/staticDown.png b/front/assets/staticDown.png new file mode 100644 index 0000000..0558e29 Binary files /dev/null and b/front/assets/staticDown.png differ diff --git a/front/assets/staticLeft.png b/front/assets/staticLeft.png new file mode 100644 index 0000000..c92eac4 Binary files /dev/null and b/front/assets/staticLeft.png differ diff --git a/front/assets/staticRight.png b/front/assets/staticRight.png new file mode 100644 index 0000000..7910a29 Binary files /dev/null and b/front/assets/staticRight.png differ diff --git a/front/assets/staticUp.png b/front/assets/staticUp.png new file mode 100644 index 0000000..96dc99e Binary files /dev/null and b/front/assets/staticUp.png differ diff --git a/front/assets/upArrowDynamic.png b/front/assets/upArrowDynamic.png new file mode 100644 index 0000000..3f1a03c Binary files /dev/null and b/front/assets/upArrowDynamic.png differ diff --git a/front/ggr.html b/front/ggr.html new file mode 100644 index 0000000..0d0d534 --- /dev/null +++ b/front/ggr.html @@ -0,0 +1,62 @@ + + + + + + + + Green Green Revolution + + + +
+

Green Green Revolution !

+

Ce jeu est une reproduction du classique DDR.

+

Utiliser les touches directionnelles ou D, F, J et K pour jouer. Vous pouvez aussi pause/resume, restart, et mute/unmute la musique en cliquant sur les icônes à droite du canvas.

+ +
+
+

Merci d'avoir jouer !

+ +
+
+ +
Green Green Revolution
+
+ +
+ + + +
+
Score: 0
+
+

+ combo +
+ +
+
+

Comment jouer

+ + +
+
+ + + + +
+ + + + + + diff --git a/front/index.html b/front/index.html index 1c5a9ad..ca2c514 100644 --- a/front/index.html +++ b/front/index.html @@ -9,7 +9,7 @@ - + diff --git a/front/src/arrowSprites.js b/front/src/arrowSprites.js new file mode 100644 index 0000000..32526a3 --- /dev/null +++ b/front/src/arrowSprites.js @@ -0,0 +1,65 @@ +class ArrowSprite { + constructor(direction) { + this.direction = direction; + this.width = 75; + this.height = 75; + this.y = 700; + this.dy = 0; + this.points = true; + this.combo = true; + this.drawArrow = this.drawArrow.bind(this); + this.arrowParams(direction); + } + + arrowParams(direction) { + this.directionImage = new Image(); + switch (direction) { + case "left": + this.directionImage.src = "assets/leftArrowDynamic.png"; + this.shift = 0; + this.x = 84.375; + break; + case "down": + this.directionImage.src = "assets/downArrowDynamic.png"; + this.shift = 300; + this.x = 154.6875; + break; + case "up": + this.directionImage.src = "assets/upArrowDynamic.png"; + this.shift = 600; + this.x = 225; + break; + case "right": + this.directionImage.src = "assets/rightArrowDynamic.png"; + this.shift = 900; + this.x = 295.3125; + break; + } + } + + drawArrow() { + let numFrames = 0; + const animate = () => { + numFrames++; + ctx.drawImage( + this.directionImage, + this.shift, + 0, + this.width, + this.height, + this.x, + this.y, + this.width, + this.height + ); + this.y += this.dy; + if (numFrames === 15) { + this.shift += this.width; + numFrames = 0; + this.shift = this.shift === 1200 ? 0 : this.shift; + } + requestAnimationFrame(animate); + }; + animate(); + } +} diff --git a/front/src/konami.js b/front/src/konami.js index 4dd1a9f..c06fdfe 100644 --- a/front/src/konami.js +++ b/front/src/konami.js @@ -37,6 +37,6 @@ document.addEventListener('keydown', function(e) { }); const activateCheats = () => { - alert('cheats activated'); - // TODO redirect to easter egg page + console.log("XD"); + window.location.href = 'ggr.html'; }; \ No newline at end of file diff --git a/front/src/scriptDDR.js b/front/src/scriptDDR.js new file mode 100644 index 0000000..21eb9bb --- /dev/null +++ b/front/src/scriptDDR.js @@ -0,0 +1,605 @@ +const canvas = document.getElementById("ttrCanvas"); +const ctx = canvas.getContext("2d"); +let modalOverlay = document.getElementById("modalOverlay"); +let directions = document.getElementById("directions"); +let playButton = document.getElementById("playButton"); +let mainSong = document.getElementById("mainSong"); +let applause = document.getElementById("endApplause"); +let startModal = document.getElementById("startGameModal"); +let endModal = document.getElementById("endGameModal"); +let scoreDisplay = document.getElementById("score"); +let comboCount = document.getElementById("comboCount"); +let comboText = document.getElementById("comboText"); +let pauseIcon = document.getElementById("pauseIcon"); +let score = 0; +let combo = 0; +let pause = false; +let restart = false; +let ended = false; +let leftPressed = false; +let downPressed = false; +let upPressed = false; +let rightPressed = false; +let dirSty = window.getComputedStyle(directions).getPropertyValue("display"); +let arrowArray = []; +let arrowDrawTimeout; +let hitObjects = [ + [2.1,1], + [4.1,1], + [6.1,4], + [8.1,4], + [10.1,2], + [12.1,2], + [14.1,3], + [16.1,3], + [18.1,1], + [18.35,2], + [18.6,4], + [18.85,3], + [19.35,1], + [19.35,2], + [19.6,4], + [19.6,3], + [20.1,4], + [20.35,3], + [20.6,1], + [20.85,2], + [21.35,4], + [21.35,3], + [21.6,1], + [21.6,2], + [22.1,1], + [22.35,2], + [22.6,4], + [22.85,3], + [23.35,1], + [23.35,2], + [23.6,4], + [23.6,3], + [24.1,4], + [24.35,3], + [24.6,2], + [24.85,1], + [25.35,1], + [25.35,3], + [25.6,4], + [25.6,2], + [26.1,4], + [26.35,3], + [26.6,1], + [26.85,2], + [27.35,4], + [27.35,3], + [27.6,1], + [27.6,2], + [28.1,1], + [28.35,2], + [28.6,4], + [28.85,3], + [29.35,1], + [29.35,2], + [29.6,4], + [29.6,3], + [30.1,4], + [30.35,3], + [30.6,1], + [30.85,2], + [31.35,4], + [31.35,3], + [31.6,1], + [31.6,2], + [32.1,1], + [32.35,2], + [32.6,3], + [32.85,4], + [33.35,4], + [33.35,2], + [33.6,1], + [33.6,3], + [34.1,1], + [34.1,3], + [34.6,4], + [35.1,2], + [35.6,4], + [36.1,4], + [36.6,1], + [37.1,3], + [37.6,1], + [38.1,1], + [38.6,4], + [39.1,2], + [39.6,4], + [40.1,4], + [40.1,2], + [40.6,1], + [41.1,3], + [41.6,1], + [42.1,1], + [42.1,3], + [42.6,4], + [43.1,2], + [43.6,4], + [44.1,4], + [44.1,2], + [44.6,1], + [45.1,3], + [45.6,1], + [46.1,4], + [46.1,2], + [46.6,1], + [46.6,3], + [47.1,4], + [47.35,2], + [47.6,4], + [47.85,2], + [48.1,4], + [50.1,1], + [50.1,4], + [50.35,3], + [50.6,2], + [50.85,1], + [50.85,4], + [51.1,2], + [51.35,1], + [51.35,4], + [51.6,2], + [51.6,3], + [52.1,2], + [52.1,3], + [52.35,4], + [52.6,1], + [52.85,2], + [52.85,3], + [53.1,4], + [53.35,2], + [53.35,3], + [53.6,1], + [53.6,4], + [54.1,1], + [54.1,4], + [54.35,2], + [54.6,3], + [54.85,1], + [54.85,4], + [55.1,3], + [55.35,1], + [55.35,4], + [55.6,2], + [55.6,3], + [56.1,2], + [56.1,3], + [56.35,1], + [56.35,4], + [56.6,2], + [56.6,3], + [56.85,1], + [56.85,4], + [57.1,2], + [57.1,3], + [57.35,1], + [57.35,4], + [57.6,2], + [57.6,3], + [58.1,1], + [58.1,4], + [58.35,2], + [58.6,3], + [58.85,1], + [58.85,4], + [59.1,3], + [59.35,1], + [59.35,4], + [59.6,2], + [59.6,3], + [60.1,2], + [60.1,3], + [60.35,1], + [60.6,4], + [60.85,2], + [60.85,3], + [61.1,1], + [61.35,2], + [61.35,3], + [61.6,1], + [61.6,4], + [62.1,1], + [62.1,4], + [62.35,3], + [62.6,2], + [62.85,1], + [62.85,4], + [63.1,2], + [63.1,3], + [63.35,1], + [63.35,4], + [63.6,2], + [63.6,3], + [64.1,2], + [64.1,3], + [64.35,1], + [64.35,4], + [64.6,2], + [64.6,3], + [64.85,1], + [64.85,4], + [65.1,2], + [65.1,3], + [65.35,1], + [65.35,4], + [65.6,2], + [65.725,3], + [65.85,2], + [65.975,3], + [66.1,1], + [66.1,4] +]; +let nxtObj = 0; + +window.onload = drawStaticArrows; +document.getElementById("redirectButton").onclick = popupDirections; +playButton.onclick = gameStart; +document.getElementById("playAgainButton").onclick = playAgain; +document.getElementById("muteIcon").onclick = toggleMute; +pauseIcon.onclick = gamePause; +document.getElementById("restartIcon").onclick = gameRestart; +document.getElementById("mainSong").onended = songEnd; +document.getElementById("endApplause").onended = gameEnd; +document.addEventListener("keydown", handleKeyPress); +document.addEventListener("keyup", handleKeyPress); + +function drawStaticArrows() { + let leftImg = document.getElementById("left"); + let leftSX = 1.5 * (canvas.width / 8); + let downImg = document.getElementById("down"); + let downSX = 2.75 * (canvas.width / 8); + let upImg = document.getElementById("up"); + let upSX = 4.0 * (canvas.width / 8); + let rightImg = document.getElementById("right"); + let rightSX = 5.25 * (canvas.width / 8); + + let img; + let sx; + let sy = 40; + let width = 75; + let height = 75; + ["left", "down", "up", "right"].forEach(dir => { + switch (dir) { + case "left": + img = leftImg; + sx = leftSX; + break; + case "down": + img = downImg; + sx = downSX; + break; + case "up": + img = upImg; + sx = upSX; + break; + case "right": + img = rightImg; + sx = rightSX; + } + ctx.drawImage(img, sx, sy, width, height); + }); +} + +function popupDirections() { + startModal.style.display = "none"; + directions.style.zIndex = 10; + if (dirSty === "none") { + directions.style.display = "flex"; + } +} + +function gameStart() { + modalOverlay.style.visibility = "hidden"; + playButton.style.display = "none"; + directions.style.zIndex = 0; + if (dirSty === "none") { + directions.style.display = "none"; + } + mainSong.play(); + arrowDraw(); + setInterval(draw, 1); +} + +function arrowDraw() { + if (ended || restart) { + return; + } else { + if (!pause) { + if (mainSong.currentTime >= hitObjects[nxtObj][0]){ + console.log(mainSong.currentTime); + let nextArrow = arrowCreate(hitObjects[nxtObj][1]); + arrowArray.push(nextArrow); + arrowArray[arrowArray.length - 1].drawArrow(); + arrowArray.forEach(arrow => (arrow.dy = -4)); + nxtObj++; + } + arrowDrawTimeout = setTimeout(arrowDraw, 10); + } else { + for (let i = 0; i < arrowArray.length; i++) { + arrowArray[i].dy = 0; + } + arrowDrawTimeout = setTimeout(arrowDraw, 10); + } + } +} + +function arrowCreate(num) { + switch (num) { + case 1: + return new ArrowSprite("left"); + case 2: + return new ArrowSprite("down"); + case 3: + return new ArrowSprite("up"); + case 4: + return new ArrowSprite("right"); + } +} + +function gamePause() { + pause = !pause; + if (pause) { + mainSong.pause(); + pauseIcon.src = "./assets/play.png"; + } else { + mainSong.play(); + pauseIcon.src = "./assets/pause.png"; + } +} + +function gameRestart() { + restarting(); + if (restart === true) { + restart = false; + playButton.style.display = "flex"; + startModal.style.display = "flex"; + modalOverlay.style.visibility = "visible"; + } +} + +function restarting() { + clearTimeout(arrowDrawTimeout); + restart = true; + pause = false; + clearNumbers(); + mainSong.pause(); + mainSong.currentTime = 0; + arrowArray = arrowArray.map(arrow => { + arrow.y = canvas.height; + arrow.dy = 0; + }); + arrowArray = []; +} + +function clearNumbers() { + score = 0; + scoreDisplay.innerHTML = "Score: " + `${score}`; + combo = 0; + comboCount.innerHTML = ""; + nxtObj = 0; +} + +function songEnd() { + ended = true; + if (ended === true) { + applause.play(); + } +} + +function gameEnd() { + modalOverlay.style.visibility = "visible"; + endModal.style.display = "flex"; +} + +function playAgain() { + modalOverlay.style.visibility = "hidden"; + endModal.style.display = "none"; + clearNumbers(); + ended = false; + gameStart(); +} + +function toggleMute() { + mainSong.muted = !mainSong.muted; +} + +function handleKeyPress(e) { + switch (e.keyCode) { + case 37: + leftPressed = !leftPressed; + break; + case 68: + leftPressed = !leftPressed; + break; + case 38: + upPressed = !upPressed; + break; + case 74: + upPressed = !upPressed; + break; + case 39: + rightPressed = !rightPressed; + break; + case 75: + rightPressed = !rightPressed; + break; + case 40: + downPressed = !downPressed; + break; + case 70: + downPressed = !downPressed; + break; + } +} + +function draw() { + ctx.clearRect(0, 0, canvas.width, canvas.height); + + drawStaticArrows(); + + for (let i = 0; i < arrowArray.length; i++) { + if (combo > 0) { + comboText.style.visibility = "visible"; + } else { + comboText.style.visibility = "hidden"; + } + + if (leftPressed) { + if ( + arrowArray[i].x === 84.375 && + arrowArray[i].y < 28 && + arrowArray[i].y > 1 + ) { + if (arrowArray[i].combo === true) { + combo += 1; + arrowArray[i].combo = false; + } + comboCount.innerHTML = combo; + + if (arrowArray[i].points === true && combo <= 10) { + score += 50; + arrowArray[i].points = false; + } else if (arrowArray[i].points === true && combo > 10 && combo <= 25) { + score += 75; + arrowArray[i].points = false; + } else if (arrowArray[i].points === true && combo > 25 && combo <= 50) { + score += 100; + arrowArray[i].points = false; + } else if ( + arrowArray[i].points === true && + combo > 50 && + combo <= 100 + ) { + score += 150; + arrowArray[i].points = false; + } else if (arrowArray[i].points === true && combo > 100) { + score += 200; + arrowArray[i].points = false; + } + scoreDisplay.innerHTML = "Score: " + `${score}`; + arrowArray[i].directionImage.src = ""; + } + } + + if (downPressed) { + if ( + arrowArray[i].x === 154.6875 && + arrowArray[i].y < 28 && + arrowArray[i].y > 1 + ) { + if (arrowArray[i].combo === true) { + combo += 1; + arrowArray[i].combo = false; + } + comboCount.innerHTML = combo; + + if (arrowArray[i].points === true && combo <= 10) { + score += 50; + arrowArray[i].points = false; + } else if (arrowArray[i].points === true && combo > 10 && combo <= 25) { + score += 75; + arrowArray[i].points = false; + } else if (arrowArray[i].points === true && combo > 25 && combo <= 50) { + score += 100; + arrowArray[i].points = false; + } else if ( + arrowArray[i].points === true && + combo > 50 && + combo <= 100 + ) { + score += 150; + arrowArray[i].points = false; + } else if (arrowArray[i].points === true && combo > 100) { + score += 200; + arrowArray[i].points = false; + } + scoreDisplay.innerHTML = "Score: " + `${score}`; + arrowArray[i].directionImage.src = ""; + } + } + + if (upPressed) { + if ( + arrowArray[i].x === 225 && + arrowArray[i].y < 28 && + arrowArray[i].y > 1 + ) { + if (arrowArray[i].combo === true) { + combo += 1; + arrowArray[i].combo = false; + } + comboCount.innerHTML = combo; + + if (arrowArray[i].points === true && combo <= 10) { + score += 50; + arrowArray[i].points = false; + } else if (arrowArray[i].points === true && combo > 10 && combo <= 25) { + score += 75; + arrowArray[i].points = false; + } else if (arrowArray[i].points === true && combo > 25 && combo <= 50) { + score += 100; + arrowArray[i].points = false; + } else if ( + arrowArray[i].points === true && + combo > 50 && + combo <= 100 + ) { + score += 150; + arrowArray[i].points = false; + } else if (arrowArray[i].points === true && combo > 100) { + score += 200; + arrowArray[i].points = false; + } + scoreDisplay.innerHTML = "Score: " + `${score}`; + arrowArray[i].directionImage.src = ""; + } + } + + if (rightPressed) { + if ( + arrowArray[i].x === 295.3125 && + arrowArray[i].y < 28 && + arrowArray[i].y > 1 + ) { + if (arrowArray[i].combo === true) { + combo += 1; + arrowArray[i].combo = false; + } + comboCount.innerHTML = combo; + + if (arrowArray[i].points === true && combo <= 10) { + score += 50; + arrowArray[i].points = false; + } else if (arrowArray[i].points === true && combo > 10 && combo <= 25) { + score += 75; + arrowArray[i].points = false; + } else if (arrowArray[i].points === true && combo > 25 && combo <= 50) { + score += 100; + arrowArray[i].points = false; + } else if ( + arrowArray[i].points === true && + combo > 50 && + combo <= 100 + ) { + score += 150; + arrowArray[i].points = false; + } else if (arrowArray[i].points === true && combo > 100) { + score += 200; + arrowArray[i].points = false; + } + scoreDisplay.innerHTML = "Score: " + `${score}`; + arrowArray[i].directionImage.src = ""; + } + } + + if (arrowArray[i].y <= 1 && arrowArray[i].points !== false) { + combo = 0; + comboCount.innerHTML = ""; + arrowArray[i].points = false; + } + } +} diff --git a/front/style/styleDDR.css b/front/style/styleDDR.css new file mode 100644 index 0000000..835a2c1 --- /dev/null +++ b/front/style/styleDDR.css @@ -0,0 +1,322 @@ +:root { + --font-family: 'Monoton', cursive; + --white: #ffffff; + --light-gray: #b2b2b2; + --dark-gray: #7f7f7f; + --black: #000000; + --brown: rgb(187, 125, 32); + --neon-yellow: #e5ff00; + --pink: #FF69B4; +} + +body { + background-image: url("../assets/Background.jpg"); + background-size: cover; + display: flex; + position: relative; + justify-content: center; + align-items: center; + margin: 0; + padding: 0 1%; +} + +h3 { + margin-top: 0; +} + +h4 { + margin: 0; +} + +section { + position: relative; + width: 45vw; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +button { + color: var(--black); + font-size: 20px; + display: flex; + justify-content: center; + align-items: center; + border: 1px solid var(--white); + border-radius: 2px; + padding: 10px 25px; +} + +button:hover { + background-color: var(--light-gray); +} + +button:active { + background-color: var(--dark-gray); +} + +#modalOverlay { + position: fixed; + top: 0; + left: 0; + height: 100%; + width: 100%; + z-index: 5; + background-color: rgba(0, 0, 0, 0.9); + display: flex; + align-items: center; + justify-content: center; + visibility: visible; +} + +#score { + color: var(--white); + font-size: 28px; + background-color: rgba(0, 0, 0, 0.5); + border: 3px solid var(--white); + border-radius: 3px; +} + +#startGameModal { + display: flex; +} + +#endGameModal { + display: none; +} + +.modalMessage { + flex-direction: column; + align-items: center; + text-align: center; + color: var(--white); + font-size: 18px; + width: 75%; + padding: 5% 3%; + border: 3px solid var(--white); + border-radius: 3px; + background-color: var(--black); + opacity: 1; + z-index: 10; +} + +.modalMessage > h3 { + font-size: 28px; + font-family: var(--font-family); + color: var(--neon-yellow); +} + +.links { + position: absolute; + top: 50px; + left: -90px; + display: flex; + flex-direction: column; +} + +.links img { + width: 40px; + height: 40px; +} + +.controls { + position: absolute; + top: 15px; + right: -75px; + display: flex; + flex-direction: column; +} + +.controls img { + border-radius: 50%; + background-color: var(--white); + width: 25px; + height: 25px; + margin: 5px 0; + border: 1px solid var(--white); + cursor: pointer; +} + +.combo { + font-size: 35px; + position: absolute; + left: -110px; + top: 200px; + color: var(--pink); + display: flex; + justify-content: flex-end; + align-items: flex-end; +} + +.combo p { + margin: 0; +} + +.combo span { + font-size: 20px; + margin-left: 5px; + color: var(--brown); + visibility: hidden; +} + +.title { + display: none; +} + +#directions { + display: none; + flex-direction: column; + justify-content: center; + align-items: center; + width: 300px; + position: fixed; + top: calc(50vh - 175px); + left: calc(50vw - 150px); + background-color: rgba(0, 0, 0, 0.5); + color: var(--white); + border: 3px solid var(--white); + border-radius: 3px; + padding: 10px; +} + +#directions h4 { + font-size: 18px; + font-weight: 300; + text-align: center; + border-bottom: 3px solid var(--white); +} + +#directions ul { + padding-inline-start: 0; + flex-wrap: wrap; + display: flex; + color: var(--white); + list-style-type: none; +} + +#directions li { + font-size: 15px; + padding: 10px; +} + +#directions li::before { + content: "\25B7"; + color: var(--neon-yellow); + margin-right: 10px; +} + +.arrowImages { + display: none; +} + +@media only screen and (min-width: 600px) { + .combo { + font-size: 45px; + left: -75px; + } + + .combo span { + font-size: 25px; + } + + .controls { + right: -30px; + } + + .modalMessage { + width: 50%; + font-size: 23px; + } + + .modalMessage > h3 { + font-size: 33px; + } + + .links { + left: -40px; + } + + .title { + font-family: var(--font-family); + width: 20vw; + font-size: 20px; + word-wrap: break-word; + color: var(--neon-yellow); + display: flex; + justify-content: center; + align-items: center; + } + + #directions { + display: flex; + width: 20vw; + margin-left: 3%; + position: static; + } +} + +@media only screen and (min-width: 768px) { + .controls { + right: 0; + } + + .links { + left: 0; + } + + .title { + width: 30vw; + font-size: 30px; + } + + #directions { + width: 30vw; + } + + #directions h4 { + font-size: 24px; + } + + #directions li { + font-size: 18px; + } +} + +@media only screen and (min-width: 992px) { + .combo { + font-size: 55px; + } + + .combo span { + font-size: 30px; + } + + .controls { + right: 25px; + } + + .modalMessage { + font-size: 28px; + } + + .modalMessage > h3 { + font-size: 38px; + } + + .links { + left: 25px; + } + + .title { + font-size: 45px; + } + + #directions h4 { + font-size: 28px; + } + + .directions li { + font-size: 20px; + } +}