Javascript lesson six. Arcanoid game. Make it move!

Hi folks,

after a lot of boring and abstract stuff let’s do something really interesting. Let’s make things move!

Preparing the Model

First I refactored a little the existing code for Model objects: since there will be a lot of code describing the Ball, Bricks and the Racket, it’s good to move these pieces to appropriate files.

An important moment here:

  • each module itself is wrapped in self-executing function
    (function () {...}) ()
    so it is executed once appropriate file is loaded.
  • Game objects usually depend on each other (for instance, the ball reflects from playground walls so the Model.Ball depends on the Model.Playground).
  • This makes us either
    • mind the loading sequence, or
    • prevent depended code from immediate running by wrapping it in the init () {...} functions.
  • The last way is preferable because it lets us controlling the initialization process more precisely and allows us use more logical loading sequence.

The result of this refactoring is in the lesson/06 branch, this commit.

How Actors were changed

Starting from this point and below the next commit follows.
Same things that were done with the Model are applied to both Actors: the initialization code is wrapped in init () {...} methods which are invoked during the game initialization:

After this was done I’ve modified actor init methods a little:

  • the initTimer() left simple; so Timer.start() starts producing timer events and Timer.pause() stops doing this.
  • The initUser() is more complex. It listens to global mouseclick and keydown and emits appropriate events on the GAME level even if the User is paused.
    • Why is this done?
      We should be able to respond on space pressing and start/unpause the game from the state right when the User is paused!
      Later we will support click on appropriate button too.
  • In contrast to Timer‘s event, User‘s ones provide parameters to listeners:
    • mouse-move provides the delta between previous mouse position and current one respecting the mouseSensivity parameter;
    • mouse-click provide the event object itself.

Ok, where is the [censored] movement?

The most interest thing happens in racket.js and in ball.js:

  • I added the .move() methods to each of these objects.
    Although they look big, they’re relatively simple: we change object’s x and y coordinate and prevent the object from moving outside the playground.
  • I also subscribed the .move(); .draw(); pair to particular events:
    • Ball movement procedure happens when timer event is triggered,
    • Racket responds on mouse movement (mouse-move event).

The last thing does all the magic!

How dahell does it work, David Blane?

Event emitters do their business, they emit events (thanks, cap). Adding event listeners

Dispatcher.on("event-name", function () {/*...*/});

makes it possible the code running during each event tick!
Once we stop emitting events, for instance, with Timer.pause(), appropriate listener won’t be invoked. However, the listener itself exists and is ready to go so with next Timer.start() it happens again.

A very important note here:
event emitter and event listener know nothing Jon Snow about each other.
So the Timer does not care who exactly is listening to its event and the Ball does not care about where the event came from.
This is called loose component coupling. Read more here and here.

This approach is even that flexible:
we can stop emitting one event and continue emitting another one. Run


in the console and enjoy the cheat mode 😉

Oh, almost forgot: the game runs in paused mode so press space to begin the show. Here we also use the advantage of the event approach, see gameplay.js:

GAME.Dispatcher.on('play-pause', function () {
  if (GAME.Actors.User.isActive()) { // this is the marker of "play/pause" mode
  } else {

Next time we add actual Arcanoid logic to the project: we’ll make the ball reflecting from the racket and let it smash bricks. Check for updates here.

See you!


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s