
This game uses the <audio> tag and keyboard input to create a game in which musical notes fall. Here’s a step-by-step guide to understanding and updating your code to current JavaScript best practices.
The goal of the game is for the player to press the right keys at the right time to “catch” the musical notes falling from the top of the screen. Each musical note is associated with a specific key on the keyboard.
HTML: It will contain the basic structure of the game, including the <audio> tag and the <canvas> where the notes will be drawn.
CSS: Basic styles for the game.
JavaScript: It will handle the logic of the game, including key detection, note movement, and sound playback.
HTML:
A canvas (<canvas>) is defined where the musical notes will be drawn.
Included are <audio> labels for each musical note.
CSS:
The canvas is centered on the screen and given a white border.
JavaScript:
Initial Setup: The canvas and drawing context are configured.
Note Class: Defines the properties and methods for musical notes.
spawnNote: A function that generates random musical notes.
playSound: Plays the sound corresponding to the key pressed.
gameLoop: The main loop in the game that updates and draws the notes.
Keyboard Events: Detects keystrokes and plays the corresponding sound, as well as removes notes when pressed correctly.
This code provides a solid foundation for a set of musical notes. You can expand it by adding more features, such as different difficulty levels, more musical notes, and additional visual effects.
In the following sections we review the code of each element discussed above.
The coding structure is of the following type:
<!DOCTYPE html>
<html lang=”es”>
<head>
<meta charset=”UTF-8″>
<title>Audio Game</title>
<link rel=”stylesheet” href=”styles.css”>
</head>
<body>
<canvas id=”gameCanvas” width=”800″ height=”600″></canvas>
<audio id=”noteC” src=”noteC.mp3″></audio>
<audio id=”noteD” src=”noteD.mp3″></audio>
<audio id=”noteE” src=”noteE.mp3″></audio>
<script src=”script.js”></script>
</body>
</html>
In Section 3.2. We’ll expand on CSS coding, but in this section you can review the basic coding:
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #000;
}
canvas {
border: 1px solid #fff;
}
The corresponding JavaScript encoding:
document.addEventListener(‘DOMContentLoaded’, () => {
const canvas = document.getElementById(‘gameCanvas’);
const ctx = canvas.getContext(‘2d’);
const notes = [];
const noteSpeed = 2;
const keys = {
‘a’: ‘noteC’,
‘s’: ‘noteD’,
‘d’: ‘noteE’
};
class Note {
constructor(x, y, key) {
this.x = x;
this.y = y;
this.key = key;
}
draw() {
ctx.fillStyle = ‘#fff’;
ctx.fillRect(this.x, this.y, 50, 50);
}
update() {
this.y += noteSpeed;
}
}
function spawnNote() {
const keysArray = Object.keys(keys);
const randomKey = keysArray[Math.floor(Math.random() * keysArray.length)];
const x = keysArray.indexOf(randomKey) * 100 + 100;
notes.push(new Note(x, 0, randomKey));
}
function playSound(key) {
const audio = document.getElementById(keys[key]);
if (audio) {
audio.currentTime = 0;
audio.play();
}
}
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
notes.forEach(note => {
note.update();
note.draw();
});
requestAnimationFrame(gameLoop);
}
document.addEventListener(‘keydown’, (event) => {
const key = event.key;
if (keys[key]) {
playSound(key);
notes.forEach((note, index) => {
if (note.key === key && note.y > canvas.height – 100) {
notes.splice(index, 1);
}
});
}
});
setInterval(spawnNote, 1000);
gameLoop();
});
We analyse the structure of the CSS code of this web game that consists of two scenes (menu and game). The breakdown of the most important parts:
body {
background: #837400;
color: #333;
padding: 50px;
}
body: Set a brown background (#837400), text colour (#333), and a 50px padding around the content.
#game {
position: relative;
width: 768px;
height: 440px;
overflow: hidden;
}
#game: Define the main container of the game with a fixed size of 768x440px and relative position. Overflow: Hidden ensures that any content that overflows is not visible.
#game, footer {
width: 768px;
margin: 0 auto;
}
#game, footer: Both elements are 768px wide and are centred horizontally (margin: 0 auto).
.scene {
position: absolute;
width: 100%;
height: 100%;
}
.scene: The game’s scenes take up the entire game container and are absolutely positioned.
#menu-scene {
background: #ccc url(../images/menu_bg.jpg);
display: -webkit-box;
-webkit-box-pack:center;
-webkit-box-align: center;
display: -moz-box;
-moz-box-pack:center;
-moz-box-align: center;
display: box;
box-pack:center;
box-align: center;
}
#menu-scene: Light gray background with a background image. Use display: box (and its prefixes) to center content both vertically and horizontally.
#game-scene {
background: #efefef url(../images/game_bg.jpg);
top: -440px;
}
#game-scene: Light gray background with a background image. It is initially positioned out of sight (top: -440px).
#game-scene.show-scene {
top: 0;
-webkit-transition: top .3s linear;
-moz-transition: top .3s linear;
transition: top .3s linear;
}
#game-scene.show-scene: When the show-scene class is added, the scene scrolls down by 0.3 seconds, making it visible.
a[href=’#game’] {
width: 146px;
height: 78px;
background: url(../images/play_button.png);
overflow: hidden;
display: block;
}
a[href=’#game’]:hover {
background-position: -146px;
}
a[href=’#game’]:active {
background-position: -292px;
}
a[href=’#game’] span {
display: block;
margin-top: -999px;
}
.hit-line {
background: url(../images/hit_line.png);
position: absolute;
width: 50px;
height: 50px;
}
.hit-line: Define interactive elements in the game scene with a background image and fixed size.
.show {
opacity: 1;
}
.hide{
opacity: 0;
-webkit-transition: opacity .2s linear;
-moz-transition: opacity .2s linear;
transition: opacity .2s linear;
}
.show y .hide: They control the visibility of elements with opacity transitions.
#hit-line-1 {
left: 259px;
top: 335px;
}
#hit-line-2 {
left: 359px;
top: 335px;
}
#hit-line-3 {
left: 459px;
top: 335px;
}
#hit-line-1, #hit-line-2, #hit-line-3: They position interactive elements in specific places within the game scene.
A simple way to customize is to update or change the images used in the game. This update does not require any changes to the coding if you do not want to change some game parameters as explained in the previous sections. In this case, changing images does require them to be the same size in pixels and to be called the same way (unless the encoding is updated). Any new images that are created must be located in the appropriate Images folder for the game to work with the new images.
The images used:
Dot.png (is the object that we collect to made music)
Menu_bg (is game menu background)
Play_button (game buttons)
Hit_line
Game_bg (is game background)