Multiple keys input handling in javascript

There is communication established between player and server and other players. There is key handling so that player can move his character. But quite soon gamers will notice that they can only move in one direction at the same time. But they cannot move down and right at the same time. Why is that? Javascript only sends one key pressed, the latest key that user pressed, ignoring all other keys that may be down at the same time. Thankfully that can be handled quite easily.

function keyboardInput(args) {
    var keyPressed = 0;

    var keyDown = function (e) {
        if (e.which === 87 || e.which === 119 || e.which === 38)
            keyPressed |= moveDirections.Up;

        if (e.which === 83 || e.which === 115 || e.which === 40)
            keyPressed |= moveDirections.Down;

        if (e.which === 65 || e.which === 97 || e.which === 37)
            keyPressed |= moveDirections.Left;

        if (e.which === 68 || e.which === 100 || e.which === 39)
            keyPressed |= moveDirections.Right;

        if (keyPressed > 0)
            args.inputChanged({ direction: keyPressed });
    };

    (function () {
        document.addEventListener("keydown", keyDown);
    })();
};

First – I’ve extracted keyboard handling into separate file. What it does is – waiting for user input, parsing it – whether it is key game is interested in or not – and notifying application by calling callback inputChanged, later on wired to SignalR communication. There is also state variable defined – keyPressed – which holds info about all the keys that were pressed, as they are comming in. This is a flag variable – values assigned to it are powers of 2. And each flag, with its own value, are combined together using or operator. This alone allows to send multiple keys pressed to server and handle movement.

But since the values are added and never removed – once a key is pressed – it will never be released, causing infinite move. Time to fix that.

function keyboardInput(args) {
    var keyPressed = 0;

    var keyDown = function (e) {
        // same as before
    };

    var keyUp = function (e) {
        if (e.which === 87 || e.which === 119 || e.which === 38)
            keyPressed ^= moveDirections.Up;

        if (e.which === 83 || e.which === 115 || e.which === 40)
            keyPressed ^= moveDirections.Down;

        if (e.which === 65 || e.which === 97 || e.which === 37)
            keyPressed ^= moveDirections.Left;

        if (e.which === 68 || e.which === 100 || e.which === 39)
            keyPressed ^= moveDirections.Right;

        if (keyPressed > 0)
            args.inputChanged({ direction: keyPressed });
    };

    (function () {
        document.addEventListener("keydown", keyDown);
        document.addEventListener("keyup", keyUp);
    })();
};

Using xor operator flags are being cleared as soon as keys are released. This way multiple keys are handled and all that I’ve done is – added one variable and one more event handler. Easy as pie.

Sending player movement to all players

Once the player has pressed the key and we got the info, everyone would expect the application to react to it somehow. Fortunately that is pretty simple – I defined callback in my Area code that will be called every time game notices player wanting to change the position. To this callback client side hub will subscribe a method sending communication to server. This in turn will modify player’s status on the server side and send updated position to all other players, letting them see position change.

Arena.js

var keyDown = function (e) {
    var key = 0;
    if (e.which === 87 || e.which === 119 || e.which === 38)
        key |= moveDirections.Up;

    if (e.which === 83 || e.which === 115 || e.which === 40)
        key |= moveDirections.Down;

    if (e.which === 65 || e.which === 97 || e.which === 37)
        key |= moveDirections.Left;

    if (e.which === 68 || e.which === 100 || e.which === 39)
        key |= moveDirections.Right;

    if (key > 0)
        playerMoving({ direction: key });
};

var playerMoved = function (who) {
    var player = players.get(who.Name);
    player.Position = who.Position;
    drawArena();
};

raim.js

var arena = new Arena({
    playerMoving: function (e) {
        raim.server.playerMoving(e.direction);
    }
});

raim.client.registered = arena.addNewPlayer;
raim.client.playerMoved = arena.playerMoved;

RaimHub.cs

public void PlayerMoving(int direction)
{
    var player = players[Context.ConnectionId];
    player.Position.X += 10; // draft implementation
    Clients.All.PlayerMoved(player);
}

It gets very ‘drafty’ at points, but the idea is clear. And it works – server gets notification, sends player position back, using player’s name I get his object and set new position (and name will be later changed to Id of some sort in future, of course). There is one problem though – the new player position is printied, true, but the old one gets displayed as well.

Well, not quite. The old one was just not removed from screen. Canvas needs to be cleared between refreshes.

var drawArena = function () {
    drawingContext.clearRect(0, 0, view.width, view.height);
    for (var i = 0; i < players.count() ; i++) {
        var player = players.get(i);

        drawingContext.strokeStyle = "#F00";
        drawingContext.fillStyle = "#F00";
        drawingContext.arc(player.Position.X, player.Position.Y, player.Size, 0, 2 * Math.PI);
        drawingContext.stroke();
        drawingContext.fill();
    }
};

clearRect is supposed to remove content form the part of the screen it was pointed to (view is initialised in constructor with actual available screen width and height). This implementation however does not work. clearRect is not clearing screen, marking pixels as white, transparent or whatever.

What is missing is – every time we draw on canvas, we do it to create some path. And every time we call fill or stroke that path gets filled with colors defined. I haven’t defined any path though, so it is putting all requests into the same path, never closing it. So even though the clearRect clears the screen, first time stroke and fill functions are called, all historical changes to path are being repainted again and again – since the path was not cleared.

How to solve it? Oh, simple – open new path for every object that is being drawn (or even for every part of an object, once they get more complex).

var drawArena = function () {
    drawingContext.clearRect(0, 0, view.width, view.height);

    for (var i = 0; i < players.count() ; i++) {
        var player = players.get(i);

        drawingContext.beginPath();
        drawingContext.strokeStyle = "#F00";
        drawingContext.fillStyle = "#F00";
        drawingContext.arc(player.Position.X, player.Position.Y, player.Size, 0, 2 * Math.PI);
        drawingContext.stroke();
        drawingContext.fill();
        drawingContext.closePath();
    }
};

User input and Canvas

With player’s token displayed on screen, next step would be to actually provide player with any interaction with application. Standing still is not much fun I think. Time to handle user input.

My first thought was to do it like this:

var keyDown = function (e) {
    console.log(e.keyCode);


(function init() {
    players = args.playersList || new PlayersList(args.playersListOptions);
    var canvas = document.createElement("canvas");
    canvas.addEventListener("keydown", keyDown);
    arena.appendChild(canvas);
    drawingContext = canvas.getContext("2d");
})();

However, to my surprise, that does not work at all. Nothing got logged to console, no matter how hard I pressed those keys, no matter how many times I clicked on canvas area to make it focus.

Focus. Canvas. Yea, not gonna work. Canvas does not capture focus it seems. Makes sense, at least at some level. How to work around it? First idea was to attach event listener to document directly. And while it sounds reasonable, I thought that there must be other solution.
Five minutes with google and I have it:

var canvas = document.createElement("canvas");
canvas.setAttribute("tabindex", 1);
canvas.addEventListener("keydown", keyDown);
arena.appendChild(canvas);

Notice setting tabindex attribute. Turns out it is quite well know (among UI programmers I guess) workaround – setting tab index on any element will make it focusable. That, too, makes some sense. But unfortunately it gives blue border around canvas. This I guess could be handled by CSS styling of the element.

But dirty tricks like that in code, especially at the begining, might bite back in future. Will I remember what is this useless attribute there for in month or two? Knowing myself – absolutely not. And it is just one step away from removing it thinking I’ve just optimised the code. And broke it at the same time, but who’s counting?

I guess I will go with attaching listeners directly to document object then. That makes more sense to me.

Drawing on canvas

Sure would be nice to see some players on the screen, not just players’ list right? In a spirit of doing everything myself (which will cause me a lot of pain later on, I’m sure, but I’ll let future me worry about it) I won’t get any graphics engine to help me with this task. Well, nothing more than plain HTML canvas has to offer.

First, it is time to encapsulate players’ list inside game object. I don’t want to handle all the logic inside my hub after all.

function Arena(args) {
    args = args || {};
    var players;
    var arenaHandler = args.arena || "arena";
    var arena = document.getElementById(arenaHandler);

    (function init() {
        players = args.playersList || new PlayersList(args.playersListOptions);
    })();

    var addNewPlayer = function (who) {
        players.addNewPlayer(who);
    }

    return {
        addNewPlayer: addNewPlayer,
    };
};

Ok, that was more work then benefit for now, just another layer of abstraction. But it will serve its purpose. Here I hope to have all the logic behind how the game works, at least at top level. It has handle for arena game display element. But I won’t be painting on a div directly, since HTML provides useful canvas with some helpful functions.

(function init() {
    players = args.playersList || new PlayersList(args.playersListOptions);
    var canvas = document.createElement("canvas");
    arena.appendChild(canvas);

    drawingContext = canvas.getContext("2d");
})();

Simple for now – create canvas, append it to game arena and get drawing context. This context is what HTML offers to help us draw lines, arcs, dots etc. All the basics. Visual studio even offers great intelisense for that feature, very helpful along the way if you are new to it.

Since I have where to draw, I need something to draw. Best would be to start with player’s position indicator on the game board. On server side Player object is created and added when registering to the game. It holds Position structure, with X and Y, as well as Size, which is plain integer for now. What can be drawn with that information? Square maybe? Yea, squares are fine, but I think I will go for something more curved. Like a circle. Since the player’s object is returned to all players, it can be used to draw the position on the arena in response to register event.

var addNewPlayer = function (who) {
    players.addNewPlayer(who);
    drawingContext.strokeStyle = "#F00";
    drawingContext.fillStyle = "#F00";
    drawingContext.arc(who.Position.X, who.Position.Y, who.Size, 0, 2 * Math.PI);
    drawingContext.stroke();
    drawingContext.fill();
}

Once player is added to the list of players, drawing context picks color for strike (border) and filling, then using arc function given by HTML canvas circle is being drawn. First two parameters are circle’s center, then the radius, after that comes starting angle and ending angle. Angles are given in radians; hence the closing angle is calculated to 2*Pi. After that all that is left is to draw the stroke and fill the content.

Voilà – player has his representation on game area!

File bundling with Gulp

As the project is moving forward there are new files appearing. There are few javascript files now, and I know there are going to be more to come. This is bit of an issue – more files mean more requests to server, which directly causes slower loading time. Browsers can only do so many concurrent requests, if you will require more files than browser limit, you will have to wait for previous request to complete. On server it is also more stressing to serve dozen requests for different files than to give one file and be done with it.

With Visual Studio 2015 comes built in support for task running. There are few task systems available, most popular being Grunt and Gulp. They support various javascript written tasks and you can always write your own one, doing what you need. They may be used for anything, but I will get them to do bundling for me.

Bundling is process of merging multiple files into one resource, that can then be used on page. In my case I want to get all my javascript files bundled, but css can also be merged if you want. I’ve picked Gulp as my poison of choice.

First thing that has to be done is to create packages.json file – Visual studio has template file to support that. Second – gulpfile.js – in this file I will be defining my tasks, gulp automatically looks for this file for list of tasks. So does task runner explorer (you can turn its window on in View-Other Windows-Task Runner Explorer, or by pressign Ctrl+Alt+Backspace).

What I need is some task definitions downloaded by npm – node js package manager. To do this I write what I need in packages.json

{
    "version": "1.0.0",
    "name": "ASP.NET",
    "private": true,
  "devDependencies": {
    "gulp": "3.9.1",
    "gulp-concat": "2.6.0",
    "gulp-concat-css": "2.2.0",
    "del": "2.2.0"
  }
}

DevDependencies is the section of interest here. I will be using gulp to run tasks, gulp-concat for javascript files and del for removing unnecessary files. You can right on this file in Solution Explorer and restore packages. They will appear in node_modules directory.

Now it is time to write some tasks in gulp. First – it needs to import required tasks (the ones that were references through packages.json):

var gulp = require('gulp');
var concat = require('gulp-concat');
var concatCss = require('gulp-concat-css');
var del = require('del');

And after that tasks can be defined:

var bundlesOutputDir = "Bundles";

var bundles = [
    { scripts: ["Content/raim.js", "Content/PlayersList.js"], output: "raim_main.js"}
];

gulp.task('clean', function () {
    del(bundlesOutputDir + '/*');
});

gulp.task('bundling', function () {
    bundles.forEach(function (bundle) {
        gulp.src(bundle.scripts)
            .pipe(concat(bundle.output))
            .pipe(gulp.dest(bundlesOutputDir));
    });
});

Those are pretty basic. clean goes to defined output directory for bundles and removes all the files. bundling on the other hand iterates over my array of bundles I want to create (which at the moment only holds one thing), loads those files (or marks them as files to process), pipes (forwards) them to concat task, which handles merging files and creates new file with name passed as parameter. This newly created file is then piped to gulp.dest task, which outputs it to target directory.

When ran from task explorer it sure does create raim_main.js file in Bundles directory!

But bundling by hand is not what I want to do. This should be done automatically, each time I change any file. I want to have them ready for use the second I stop writing them. For this, gulp.watch is perfect:

gulp.task("watch", function () {
    bundles.forEach(function (bundle) {
        gulp.watch(bundle.scripts, ['clean', 'bundling']);
    });
});

gulp.task('default', ['clean', 'bundling', 'watch']);

Again, going through all bundles, I mark those files for watch process and each time any of those files change I want to trigger clean task and later bundling. Additionally, default task is created to run those tasks automatically when gulp is ran as parameter (e.g. from console or during build process on CI machine).

Triggering default task prepares working space for me, old bundles removed, new ones created and watch configured.

But what about newly cloned repository, if someone downloads it? Or if I restart visual studio – I don’t want to have to go to task explorer and trigger those tasks. Thankfully Visual Studio supports biding tasks to few events in VS, one of those being – project opened. It is done simply by providing special structure in comment at top of the file:

/// <binding ProjectOpened='default' />

There can be comma separated list of tasks to run on start, but I just need one at the moment. This way if I unload the project, kill task running in background, and reload main project again – default tasks kicks in automatically, preparing workspace. Neat!

What is left is to reference the bundle from html file:

<a href="http://../Bundles/raim_main.js">http://../Bundles/raim_main.js</a>

And it should be… wait – no. Scripts are in Bundles directory, but Nancy wont be serving those files. What it needs is some configuration to tell it there is static content there. One line in Bootstrap file:

nancyConventions.StaticContentsConventions.AddDirectory("Bundles");

And only now all is running smoothly.

jQuery promises: done vs then

Imagine that, while working in jQuery and javascript, you want to trigger one task and once it is finished you want to trigger another one. You might come up with something like this:

var d1 = $.Deferred();
var d2 = $.Deferred();

d2.done(function() { console.log("d2 done")});

d1.done(function() { console.log("d1 done")})
.done(function () {
      setTimeout(function () {
        d2.resolve();
      }, 1000);
      return d2;
  })
  .done(function () {console.log("both done")});

console.log("start");
d1.resolve();

jsfiddle.net/bLh9eo2f/

Timeout in d2 resolving is just to simulate time taking task. And expected output would be like:

start
d1 done
d2 done
both done

However if you run it you will get something different

start
d1 done
both done
d2 done

Race condition? Not at all, something entirely different – invalid use of promises. You see, done and then may sound similar but do something completely different. Done is used to callback some code once promise is done. Then is used to chain promises – it will be triggered once first promise is done and it will return entirely new promise.

Code above uses done incorrectly – when d1 is finished it calls first done, triggering d2 processing, but then immediately calls both done callback – done returns original promise to which it was applied, and since it was finished, all done callbacks are going to be called. Correct solution is as follows:

var d1 = $.Deferred();
var d2 = $.Deferred();

d2.done(function() { console.log("d2 done")});
d1.done(function() { console.log("d1 done")})
  .then(function () {
      setTimeout(function () {
        d2.resolve();
      }, 1000);
      return d2;
  })
  .done(function () {console.log("both done")});

console.log("start");
d1.resolve();

jsfiddle.net/ttuLmwxq/1/

producing output:

start
d1 done
d2 done
both done

As expected. And imagine what would happen if d2 failed to finish correctly? In first case – system would report that both were done ok. In second, it would report that d1 finished, true, but later would fail on d2 and since then all callbacks would only be triggered for fail case.

Object management in javascript; default values

It is quite logical to expect hub code both on server and client side to get bigger and more complex as development progresses. Also, having multiple functionalities covered by a single file is not clear, can be nest of bugs etc. Look at your code base, get some stats – if you see some files being edited over and over again – that’s where your most serious problems probably are and investing some time to get this situation under control will pay of.

One operation that is pretty much separate form the rest is adding player to players list. It needs a name and can operate on DOM tree by itself. Moving it to separate file is easy enough:

function PlayersList() {
    var playersListElementId = 'playersList';

    var addNewPlayer = function (player) {
        var players = document.getElementById(playersListElementId);
        var playerNameElement = document.createElement('span');
        playerNameElement.textContent = player;
        players.appendChild(playerNameElement);
    };

    return {
        addNewPlayer: addNewPlayer
    };
}

Instead of extracting just a function, I’ve decided to create small object that can handle players list management. It has one field with name of DOM element in which players should be listed, as well as one function to add new player to said list. Standard javascript structure with private function and returning object structure which will expose this function to public thanks to beauty of closures.

That seems quite good, doesn’t it? Well, there are some problems though. It uses hardcoded id of element. It would be nice to be able to pass it from outside if I decide to change its name. Leveled up version is:

function PlayersList(args) {
    args = args || {};
    var playersListElementId = args.playersList || 'playersList';

    var addNewPlayer = function (player) {
        var players = document.getElementById(playersListElementId);
        var playerNameElement = document.createElement('span');
        playerNameElement.textContent = player.Name;
        players.appendChild(playerNameElement);
    };

    return {
        addNewPlayer: addNewPlayer
    };
}

To constructor function there can be passed args parameter – an object holding any values PlayersList might want to use. If it is empty, it’s going to be initialized with empty object. And if there is no player list id in args, code will fall back to default id. All of this thanks to the way javascript works.

There are true and false values in computer programming. Javascript also has truthy and falsy values – those that are evaluated to true and false respectively, when used in logical expression. One of falsy values is undefined. And when parameter is defined (or any variable for that matter) and no value is assigned to it, it is undefined.
Second part of solution is || operator. That’s a logica or. If at least one of its sides is true (or truthy) – it is going to be evaluated to true. But double pipes || also have neat optimization in it – if left part of expression is evaluated to be truth(y) – right part does not have to be evaluated, as it is already known what the outcome is going to be.
Third, and last part of solution is – this expression will not actually return true of false, but will return the part of expression that was last evaluated. So the logic goes: if args value is falsy – go to right part of expression and return new object. But if on the other hand args are already initialized, no need to evaluate the other part, and args, as they were, are returned from expression.

The same logic goes for checking if args have playersList value assigned to it. This way we can easly define default values.

Is it perfect? Not necessarily – when there are multiple values passed and each has to be checked before using, the code gets nasty. Not in this case, but in complex classes that is going to happen. jQuery has a solution for that – extend function. I am however still dedicated to not using jQuery yet. For the moment above solution fits well enough, and if not – I will see if I can write something simillar to jQuery extend.