Sunday, 27 April 2014

Writing games in JavaScript

Swami Nikhilaananda said:
"All work and no play makes Gulagulaananda a dull old man... well duller"

With every passing day, I am beginning to like JavaScript more and more. JavaScript is very easy to learn and with one language, you can write front-end applications, back-end scripts, run servers and even write mobile apps for Android, iOS, Tizen etc. I think that's incredible!

I have written a couple of simple games with JavaScript and thought I should write a post about one of them. So, let's have a look at a simple game I wrote, called Crates.

The objective of the game is simple. There is a "hero", a character you control with the keyboard arrows. There are some crates and some targets (golden balls). The goal is to cover all targets with the crates. The hero can push a single crate but never pull one. Only one crate can be pushed at a time. A crate that is against the wall or another crate cannot be pushed. So it gets tricky when you push crates to some corner.

The game is a clone of the classic 'Box World' that I had played long ago in school. I just wrote this one in JS as an exercise. Let's dissect and see how it was written. I would really appreciate it if you can leave some suggestions at the end.



You can play the game here and find  the source on Github here. (This game isn't really well written, it was written in a great hurry. But the concepts in this post are sound, and I would like you to look at it, rather than the source code of crates. I would recommend looking at the source code of MemBlock instead.)

Everything is a matrix
One of the main reasons I loved Matlab in college was that everything was a matrix. It was like some deep philosophical thing - everything is Brahman. An image can be represented as a matrix, with each point being a number in the matrix and the value being the intensity. RGB frames in colour images are three matrices, all within one matrix. Sound can be represented as a matrix. Basically, everything is a matrix.

Keeping that in mind, I like to see games as matrices. If a particular cell has 0, it translates to a wall. If a cell has 1, it translates to grass. If it is 4, it translates to the hero, and so on. So a simple matrix like this represents a hero standing with grass on one side and a wall on the other:
[0, 4, 1]

Next, we have to use some syntactic sugar. What this means is that, we don't want to use numbers like 0, 1 etc. in our code to make comparisons. While you might understand this while writing code, you will never understand it a month later. Imagine seeing this piece of code:
if (matrix[i][j] == 3)

What's 3? Therefore, let's define variables like:
var WALL = 0;
So that we can make comparisons like:
if (matrix[i][j] == WALL)
you will know what you are doing.

Models and Views?
Once we have defined what each number in a matrix means, we have to write a very important function - a rendering function. This function essentially translates changes in the matrix to changes on screen. What does this mean? This is exactly along the lines of MVC, where the matrix is your model, and the graphics you see on the screen is the view. Changing the matrix behind the scenes changes the model, but someone has to change the view. So you have two options here - Either use some kind of an MVC framework that does this automatically for you, such as AngularJS, etc. (which in my opinion, is an overkill for simple games) or write your own rendering function.

Personally, I write my own simple functions for rendering - I call it draw_map(). The draw_map function simply reads the matrix and draws the map, period. In this function, you can represent the numbers by some graphics. Keep all your images in some folder called assets.

Let's move (on)
Next, we need to be able to read input from the user - Just bind keypress or keydown event to the document or window, check if the input key is one among the ones that you want. Otherwise, simply discard it. Again, use some syntactic sugar for key codes.
var LEFT_ARROW = 37;
var RIGHT_ARROW = 39;
var UP_ARROW = 38;
var DOWN_ARROW = 40;
The fact that JavaScript is an event based language makes it great for games!
Logic
Then comes the important part of the game - The logic. Depending on the key code, check if the move is valid by validating it against the matrix. If it is valid, change the matrix and call the draw map function. If it is not valid, either reject it, or indicate it to the user with a subtle 'invalid move'. Always remember that all changes should be made only to the matrix and no DOM changes should be made whatsoever. So, if you want to increase or decrease points, do it by altering the variable. But the actual display of the score on screen should be done by the rendering function.

What next?
That's it! You are done with the game. However, games such as these are only as fun as the number of levels in it. You can build only as many levels. To take it to the next level, would be to create a simple game world creator so that your users can design levels and share it with others. The game designer uses the same rendering function, and with some small alterations, a lot of code can be reused. Ensure that the user can play and test out the games she has created. Once that is done, and the game gets validated, enable upload and sharing of the game. Check out Crate's "Create a world" section. It allows you to create worlds and test it, but the publish feature as of now is not linked to any backend servers for persistence. It instead simply spits out a matrix when you "Return to game design" that you can mail to me.

Can this be improved further?
The answer, according to me, is a resounding yes. A lot of games can be made using this matrix concept, and there are a lot of similarities among these games. The ability to create worlds, uploading and reading games created by others can be the same across games. So, it should be possible to create some kind of a game framework around this. If anyone is interested in building this with me, please let me know.

Many games such as pacman, NumArrange (uses AngularJS), MemBlock use matrices. Think of other games that can be built using matrices

The other way of building a game would be using classes and objects. Perhaps there will be another post about that.

Recommended Posts
I would like to highly recommend by friend Niyaz's post on how to write a chess game in JavaScript - I think he uses the same method.

No comments: