It was a super fun experience and every team had something to show at the final reckoning in the demo sessions. My personal favorite (and the winner) was a virtual fly that sprang to life when you connected several devices together and started buzzing as it randomly flied through a crowded room to everyone’s delight (or almost everyone XD).
I, myself, worked as a coach during the Hackathon so I couldn’t fully participate with any team. I did sneak some hours though and attempted to build something cool with Rx.js and Web Speech.
This is the story of… Say What Maddafackaaaaaaa!! – The Game… Behold!!
That Light Bulb Moment
On the flight to Dublin I had some hours to brainstorm about what I could build during the hackathon. I had been experimenting a lot with Rx.js lately so I wanted to build something with it, just for experimenting and having fun. Of course, being a hackathon about music and sound it had to have some speech or audio web API in it.
I had also just finished reading Sergi’s Reactive Programming with Rx.js book, which is great by the by, and I think that it planted the seed for a game in my subconscious so that when I started thinking of options before the hackathon it sprung. I was going to build a game. But what kind of game?
Out of nowhere I remembered those typing games where words come from the top of the screen and slowly travel down. The gist is to type each word before it gets to the bottom or you die and disappear into oblivion. If you type the word right the word gets eliminated, you get some points and can continue fighting for your survival. As the game progresses words appear more often and they scroll down faster and faster and faster until they overwhelm you and bring your demise.
Yes! I was going to build something like that, but using speech instead of a keyboard. The idea was to start shouting words that started using a given letter, and then perhaps add more levels of complexity combining letters, phrases, speed, etc.
Awesome, I finally had an idea for the hackathon… rock on!
Take a Look at This Introduction to Rx.js
If you haven’t worked with Rx.js before then perhaps you may want to take a look at this introduction that explains some of the basics before you continue reading. If you like living on the edge, proceed my adventurous friend.
Building the Game Step by Step – Part I
The whole code for this article in this jsFiddle. Beware that this is weekend-conference-booze-hackathon level code. Expect duplication and inconsistencies :P
So! Given the super tight time schedule, my first priority was to get something onto the screen as soon as possible. I chose to use jsFiddle to write the game so it would be easy to demonstrate and share at the end of the hackathon.
I decided to start by having a black background and some letters falling down the screen at regular intervals. In order to achieve that I needed to create a teeny tiny game engine of sorts and undust my limited game dev knowledge (from this, this and that).
Let’s take a look at a simplified version of game development and an exemplar game engine for if you haven’t traveled these waters before.
And A Teeny Tiny Intro to Game Development
A game, in programming terms, consists of an infinite loop with the following steps:
- gather user input,
- update the state of the game based on that input
- draw everything
This is commonly known as… brace yourself… (ominous voice) the game loop.
In addition to implementing a game loop, you need a way to represent the different entities that are going to live within your game, like the player itself, backgrounds, enemies, scores, etc. You do that by using an abstraction usually called
GameObject to represent these entities. A
GameObject generally has an
draw methods. The
update method updates the state of the game object based on the player input, previous interactions or other game logic and the
draw method paints it onto the screen.
Additionally, you often divide your game in a collection of Scenes. Each Scene let’s you group and manage collections of game objects that are displayed and interactive to the player at any given point in time.
The game loop for a simple game where you only have a scene could look some thing like:
1 2 3 4 5
Doing a Game Loop in Rx.js
Now, let’s try to recreate this in Rx.js. An infinite loop, if you reflect about it, can be thought of as an infinite sequence of do-something events. Since we want this sequence to execute the game loop at certain intervals, we use
Now we want to setup my background in that infinite loop. So we create a
GameObject that represents a game object that can be drawn into the screen. This game object has a position in a 2-dimensional space and a speed when it moves:
1 2 3 4 5 6 7 8 9
We then create a
Background object to represent the actual background of my game:
1 2 3 4 5 6 7 8
In order to draw the
Background and the game itself we need to place a
canvas in my html markup:
Now that we have a
canvas we can use its primitives to paint a black rectangle when the background
draw method is called:
1 2 3 4 5 6 7 8 9 10 11
Once we have a way to represent a background we can include it in our game by making it be a part of our game loop. In order to do that we create a background observable:
And combine it with our game loop:
1 2 3 4 5
combineLatest operator combines multiple observables. It combines then in a way that every time one of these source observables emits a value, the resulting observable emits another value that contains all the latest values pushed by the original streams.
I understand, many words there, blablabla… It’s much easier to understand if we express it via a marble diagram:
1 2 3
What to Understand What An Operator Does? Check RxMarbles!
So now that we have a
game$ observable that contains our game objects being pushed through time every 16 milliseconds, we can subscribe to it to perform the actual updating and drawing:
1 2 3 4 5 6 7 8
If we go back to our original definition for the game loop, we could see at a glance like this:
1 2 3 4 5 6 7 8 9 10 11 12
After having included the background in our game loop and subscribed to it you should be able to see a black screen. Tadaaaa! :)
Adding Some Letters
The next step would be to add some letters falling from the top of the screen towards the bottom.
Just like with the background we need a way to represent a letter in our game universe. That is, we need to create a new
Letter game object:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
And now we have to decide how we are going to introduce these letters into the game. Let’s think… We want a letter to fall down the screen every so often, so that sounds like some sort of interval. Let’s say that we want new letters every 2 seconds. We can represent through a new
1 2 3
But we need a way to transform these intervals into actual letters:
1 2 3
getRandomPosition are just helper method to get an arbitrary letter and place it in the screen at an arbitrary position:
1 2 3 4 5 6 7 8
We also we want to keep these letters in our game, accumulate them until the player says a word or the letters just fall off the screen.
In order to do that we are going to use the
scan operator which works like
Array.prototype.reduce and applies reduce on the existing items within a stream:
1 2 3 4 5 6 7
If we represent it through a marble diagram it would look like this:
1 2 3
Where we accumulate our letters inside an array every 2 seconds. It just remains to add them to our game by including them inside our
1 2 3 4 5
And voilà! You should have letters appearing in your screen every 2 seconds and moving downwards until they leave the screen.
Concluding Part I
And again this grew up to be a much longer article that I had expected, so we’ll divide it into several articles.
In this first installment you learned how to implement the rudiments of a game engine in Rx.js with a basic game loop and a way to represent game objects, update their state and draw them in the screen. You also learnt about the
scan operators along the way. We now have the beginnings of a game where we display a background and letters that travel downwards our screen.
Up next we will continue by gathering some user input using the Web Speech API that will affect our game and earn us some rewards.
At any rate, you can find the whole source code in this jsFiddle so feel free to experiment yourself if you’re curious.
Have a great weekend! Now I must run to work! :)