konami code + DDR
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
@@ -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.
|
||||
|
||||

|
||||
|
||||
### Technologies
|
||||
|
||||
TTR will be made using the following technologies:
|
||||
<ul>
|
||||
<li> Plain Javascript for game logic and overall structure.</li>
|
||||
<li> `HTML Canvas` for rendering.</li>
|
||||
<li> `Web Audio API` to incorporate tunes</li>
|
||||
</ul>
|
||||
|
||||
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.
|
||||
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 9.2 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 69 KiB |
@@ -0,0 +1,62 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" type="text/css" href="./style/styleDDR.css">
|
||||
<link href="https://fonts.googleapis.com/css?family=Monoton" rel="stylesheet">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="./assets/favicon.ico" />
|
||||
<title>Green Green Revolution</title>
|
||||
</head>
|
||||
<body>
|
||||
<span id="modalOverlay">
|
||||
<div id="startGameModal" class="modalMessage">
|
||||
<h3>Green Green Revolution !</h3>
|
||||
<p>Ce jeu est une reproduction du classique DDR.</p>
|
||||
<p>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.</p>
|
||||
<button id="redirectButton">Continuer</button>
|
||||
</div>
|
||||
<div id="endGameModal" class="modalMessage">
|
||||
<h3>Merci d'avoir jouer !</h3>
|
||||
<button id="playAgainButton">Rejouer</button>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<div class="title">Green Green Revolution</div>
|
||||
<section class="canvasArea">
|
||||
<div class="links">
|
||||
<a href="https://github.com/joniboy74prog/nuitdelinfo"><img src="./assets/github.png"></a>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<img id="muteIcon" src="./assets/sound.png">
|
||||
<img id="pauseIcon" src="./assets/pause.png">
|
||||
<img id="restartIcon" src="./assets/restart.png">
|
||||
</div>
|
||||
<div id="score">Score: 0</div>
|
||||
<div class="combo">
|
||||
<p id="comboCount"></p>
|
||||
<span id="comboText">combo</span>
|
||||
</div>
|
||||
<canvas id="ttrCanvas" width="450" height="680"></canvas>
|
||||
</section>
|
||||
<div id="directions">
|
||||
<h4>Comment jouer</h4>
|
||||
<ul>
|
||||
<li>Utiliser les touches directionnelles ou D, F, J et K pour jouer.</li>
|
||||
<li>Essayer d'appuyer sur les bonnes touches lorsque les flèches bougeantes chevauchent les flèches statiques.</li>
|
||||
<li>Un compteur montre le combo actuel.</li>
|
||||
<li>Plus le combo est haut, plus vous obtiendez de points !</li>
|
||||
</ul>
|
||||
<button id="playButton">Jouer</button>
|
||||
</div>
|
||||
<div class="arrowImages">
|
||||
<img id="left" src="./assets/staticLeft.png">
|
||||
<img id="down" src="./assets/staticDown.png">
|
||||
<img id="up" src="./assets/staticUp.png">
|
||||
<img id="right" src="./assets/staticRight.png">
|
||||
</div>
|
||||
<audio id="mainSong" src="./assets/electroSportRock.mp3"></audio>
|
||||
<audio id="endApplause" src="./assets/applause.mp3"></audio>
|
||||
</body>
|
||||
<script src="./src/arrowSprites.js" type="text/javascript"></script>
|
||||
<script src="./src/scriptDDR.js" type="text/javascript"></script>
|
||||
</html>
|
||||
@@ -9,7 +9,7 @@
|
||||
<link rel="stylesheet" href="style/navbarHorizontal.css">
|
||||
<link rel="stylesheet" href="style/main.css">
|
||||
|
||||
<script src="./src/konami.js" type="module" defer></script>
|
||||
<script src="./src/konami.js" type="text/javascript" defer></script>
|
||||
</head>
|
||||
<body id="accueil">
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||