Building the Classical Musician’s Answer to Guitar Hero in JavaScript (with a lot of help from jQuery)

Le Héros Orchestral title page

As I mentioned in my previous post, my first project on General Assembly’s Web Development Immersive was to build a game in HTML, CSS, and JavaScript. As if programming a game after only three weeks of serious coding wasn’t bad enough, I decided to take the insanity to a new level by making my game an orchestral version of Guitar Hero. It is just like a browser-based Guitar Hero, only featuring Russian Romantic music. And there are fifteen keypress commands, not four. What could possibly go wrong?!

Whilst the brief certainly did not limit craziness, it was definitely not a requirement. Up until this point, we had covered the basics of the three technologies, and briefly visited some of their friendly companions: SASS (SCSS), Bulma, and the ever-so-friendly jQuery. We had also tried our hand at simple games in class and for homework, including Tic Tac Toe, which is surprisingly complicated to build at this stage. Our games, however, could be anything we wanted so long as they were reasonable, and we were encouraged to tap into our interests.

“choir in room with turned on lights” by Manuel Nägeli on Unsplash

The natural choice, for me, was a music game of some description. I have played classical music since I was five, and have a deep seated interest in orchestral music (despite not playing an orchestral instrument) — especially that of Romantic and early 20th century composers. I also spent four years studying composition at the Guildhall School of Music & Drama (with six months of that spent at Koninklijk Conservatorium in The Netherlands) so I almost couldn’t not base it on this interest. It does sadden and frustrate me that classical music is seen as “boring” and “uncool” because it could not be further from the truth. So I set out to create a game that was both fun and educational. The Guitar Hero/Rock Band framework is so iconic and well known, so why not build on that!

Resisting the urge to go crazy and have the user play the first bassoon part from Stravinsky’s Prelude to Le Sacre de Printemps, I decided on Tchaikovsky’s Swan Lake op. 20 no. 10 Scène, with the user playing first oboe. The world cup was finishing at the time I was starting the game, and ITV had used it in their titles, so it was extremely well known. Plus it was also easy to code: it stays in the same tempo throughout (albeit one that is not divisible by 60 or 90,) stays in the same metre throughout, and features no complex rhythms that would be a pain to divide.

“group of ballerinas dancing while raising both hands” by Michael Afonso on Unsplash

Quickly, I found myself getting swept up in this idea of a beautifully styled game, featuring a conductor character, a setup feature to allow the user to customise gameplay, and the most beautiful styling this world has ever known. But first, I had to build the game itself.

It wasn’t long before I came across my first problem. My second task (after assigning audio files to keypresses) was to generate divs with the keypress commands inside them, and to have these pop up on the screen in time with a metronome backing track. Not for the first or last time, setInterval() let me down here. It’s amazing how quickly it slips out of time, even on an up-to-date Macbook Pro running Chrome. I could not get half a bar in before it was completely out of time. Thankfully, I quickly found a solution, but it wasn’t a quick one. Each div is controlled on its individual setTimeout(). This way, I can keep the divs beautifully in time, because if one setTimeout() lags, it doesn’t have a knock-on effect. I was able to calculate the number of milliseconds a setTimeout() would need to wait before popping up, based on the time already elapsed, and the note value of the note before. The downside is that each div had its own function. There are over one hundred notes in the piece…

Of course, there is something to be said for refactoring. My JS file, as a whole, is somewhat Herculean. I tried refactoring the setTimeouts but found things went very wrong when I got to rests. Since this was my first go at doing a substantially sized project, I decided it was best to have WET code that worked, than DRY code that didn’t. Obviously.

“tilt selective photograph of music notes” by Marius Masalar on Unsplash

Next came collision detection — a topic I feel I may write a longer, separate post about, because it sure was a learning curve! Sure, collision detection is not hard in principal. But when you have to get the dimensions of several elements — all but one of which were animated by this point — it is another kettle of fish. What made matters even harder was that my collision zone was bang on in the middle of the page. To have this target area in the centre was a design decision for better UX. Musicians are used to sight reading, and reading a few bars ahead, so this motion made sense. However, it meant it was much harder to get the note that I needed to check for collision! I couldn’t check for the first note on the DOM. I couldn’t even check for the first note with a class of that keypress.

Eventually, I found a rather convoluted work around. First, I gave each div a class of its keypress. Annoyingly, this meant diving back into my hundred plus setTimeout() functions. Next, I give each div a class of dead just after they hit the collision zone. So, I could check for a collision between the stationary collision zone, and the first div that a) has a class equal to the keypress, b) does not have a class of dead, and c) does not have a class of miss, which is applied if the div isn’t within the collision zone.

Just a small part of my collision detection

Finally, after getting collisions working, it was all downhill from there!

After adding in a score function, and something to tell the user how they’ve done, I was at MVP. Time to add extra features! From random squeaks to play when the user hits a wrong note, to bonus scores/booing, to some intro pages complete with an “audition” page to introduce the keypresses to the player.

Finally came styling. Up until the final day of the project, the only styling I had done was some layout for the collisions. Throughout the day, I added some black and white background images, some gradient gold text, and some beautiful Google fonts. Somehow, I even found time to photoshop Emmanuel Macron’s head onto a stock image conductor for the lols.

At last, Le Héros Orchestral was ready! It is available to play on GitHub Pages, and the repo is stalk-able on GitHub.

Was it Even Worth It?!

In short: yes, but eventually…

The longer answer is: yes, and it was a very steep learning curve. It was the first coding project I had built on any significant scale, and was built after a week. Upon finishing the project, I did not want to look at it again for some time. But I have since found a great deal of value in it.

Embarking on this project really solidified my knowledge of CSS, JavaScript and jQuery — in fact, the code contains so much jQuery that I often find myself going back to it before the jQuery docs when I need a bit of guidance. Plus it was great to put what we’d learnt in class into a context, a project that I was very proud of at the end. If someone had told me, before starting at General Assembly, that I would put up a project like that, I would not have believed them. And, yet, I did it!