Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Friday, 8 August 2014

Brush up on your Languages with Pluralsight

Over the last year not only have I created a number of courses for Pluralsight, I’ve also watched a lot too. Most of the time, I’m not watching to learn a brand new technology, but as a refresher for something I’ve already used a bit. Often in just an hour or two (on 1.3x playback) you can watch a whole course and pick up loads of great tips.

I’ve found it a particularly effective way to brush up on my skills in a few programming languages that I’m semi-proficient in, but not completely “fluent” in. So here’s a few programming language related courses that I can recommend:

First, last year I was glad I watched Structuring JavaScript by Dan Whalin, as I had been hearing lots of people talking about the “revealing module pattern” and “revealing prototype pattern” but hadn’t yet properly learned what those patterns were. He explains them simply and clearly.

Another great course is Python Fundamentals by Austin Bingham and Robert Smallshire. It’s been a number of years since I did any serious Python development, so my skills had grown a bit rusty. This superbly presented course is a brilliant introduction to Python, and filled in a couple of gaps in my knowledge. They’ve got a follow-up course out as well which is undoubtedly also worth watching.

Third, several times over the years I’ve tried and failed to get to grips with PowerShell. The Everyday PowerShell for Developers course by Jim Christopher was exactly what I needed as it shows how to do the sorts of things developers will be interested in doing with PowerShell.

And finally, the F# section of the Pluralsight library is still small, but growing fast, and one fascinating course was Mark Seemann’s Functional Architecture with F#. It’s fast-moving but gives fascinating insights into how you could architect a typical line of business application in a more functional way.

Anyway, that’s enough recommendations for now. I have several other courses I want to highlight, so maybe this will become a regular blog feature. Let me know in the comments if there are any must-see courses you’ve come across.

Wednesday, 12 February 2014

TypeScript Tetris

Over a decade ago I decided to teach myself Java by writing a Tetris game which I made as an “applet” embedded in a webpage. The game itself worked fine, but Java in the browser never really took off, and so no one was actually able to play my masterpiece.

image

Every now and then I would think about trying to port it to Javascript with a HTML 5 canvas. But one of the frustrating things about Javascript (from a Java or C# developer’s perspective) is it’s rather peculiar approach to object inheritance, which I hadn’t got round to learning.

So when TypeScript was announced, with its greatly simplified syntax for classes, I thought it might be worth giving this another try. And it turned out to be surprisingly easy to port. In fact I got it working shortly after the first version of TypeScript was released, but I never got round to blogging about it. Here’s some notes:

The HTML

There wasn’t much that needed to be done in the HTML, except to create a HTML 5 canvas object for us to draw on. Probably there is some cool trick web developers use to pick the optimal size for the game based on your browser size, but I just went for a fixed size canvas for now.

<canvas id="gameCanvas" width="240" height="360"></canvas>

The Shape Classes

In my original Java code I had a Shape base class, with methods like move, drop, rotate etc, and a series of classes derived from it representing the different Tetris shapes (square, L-shape, T-shape etc).

These were the easiest to convert from Java into TypeScript. The only real difference was that Javascript’s arrays are slightly different to Java arrays. You declare an empty one, and then “push” elements into it. Here’s the base "Shape” class (I made my own Point type, as I don’t think JavaScript has a built in one):

class Shape {
    public points: Point[]; // points that make up this shape
    public rotation = 0; // what rotation 0,1,2,3
    public fillColor;

    private move(x: number, y: number): Point[] {
        var newPoints = [];

        for (var i = 0; i < this.points.length; i++) {
            newPoints.push(new Point(this.points[i].x + x, this.points[i].y + y));
        }
        return newPoints;
    }

    public setPos(newPoints: Point[]) {
        this.points = newPoints;
    }

    // return a set of points showing where this shape would be if we dropped it one
    public drop(): Point[] {
        return this.move(0, 1);
    }

    // return a set of points showing where this shape would be if we moved left one
    public moveLeft(): Point[] {
        return this.move(-1, 0);
    }

    // return a set of points showing where this shape would be if we moved right one
    public moveRight(): Point[] {
        return this.move(1, 0);
    }

    // override these
    // return a set of points showing where this shape would be if we rotate it
    public rotate(clockwise: boolean): Point[] {
        throw new Error("This method is abstract");
    }
}

and here’s an example of a derived shape:

class TShape extends Shape {
    constructor (cols: number) {
        super();
        this.fillColor = 'red';
        this.points = [];
        var x = cols / 2;
        var y = -2;
        this.points.push(new Point(x - 1, y));
        this.points.push(new Point(x, y)); // point 1 is our base point
        this.points.push(new Point(x + 1, y));
        this.points.push(new Point(x, y + 1));
    }

    public rotate(clockwise: boolean): Point[] {
        this.rotation = (this.rotation + (clockwise ? 1 : -1)) % 4;
        var newPoints = [];
        switch (this.rotation) {
            case 0:
                newPoints.push(new Point(this.points[1].x - 1, this.points[1].y));
                newPoints.push(new Point(this.points[1].x, this.points[1].y));
                newPoints.push(new Point(this.points[1].x + 1, this.points[1].y));
                newPoints.push(new Point(this.points[1].x, this.points[1].y + 1));
                break;
            case 1:
                newPoints.push(new Point(this.points[1].x, this.points[1].y - 1));
                newPoints.push(new Point(this.points[1].x, this.points[1].y));
                newPoints.push(new Point(this.points[1].x, this.points[1].y + 1));
                newPoints.push(new Point(this.points[1].x - 1, this.points[1].y));
                break;
            case 2:
                newPoints.push(new Point(this.points[1].x + 1, this.points[1].y));
                newPoints.push(new Point(this.points[1].x, this.points[1].y));
                newPoints.push(new Point(this.points[1].x - 1, this.points[1].y));
                newPoints.push(new Point(this.points[1].x, this.points[1].y - 1));
                break;
            case 3:
                newPoints.push(new Point(this.points[1].x, this.points[1].y + 1));
                newPoints.push(new Point(this.points[1].x, this.points[1].y));
                newPoints.push(new Point(this.points[1].x, this.points[1].y - 1));
                newPoints.push(new Point(this.points[1].x + 1, this.points[1].y));
                break;
        }
        return newPoints;
    }
}

Drawing

My application also had a “Grid” class, which was responsible for managing what shapes were present on the board, and for rendering it as well. So it needs the HTMLCanvasElement, and draws onto it with a CanvasRenderingContext2D. Thankfully the methods on the rendering context are actually quite close to the Java ones. We chose the colour with a call to context.fillStyle, and then draw a rectangle with context.fillRect.

class Grid {
    private canvas: HTMLCanvasElement;
    private context: CanvasRenderingContext2D;
    private rows: number;
    public cols: number;
    public blockSize: number;
    private blockColor: any[][];
    public backColor: any;
    private xOffset: number;
    private yOffset: number;

    constructor (rows: number, cols: number, blockSize: number, backColor, canvas: HTMLCanvasElement) {
        this.canvas = canvas;
        this.context = canvas.getContext("2d");
        this.blockSize = blockSize;
        this.blockColor = new Array(rows);
        this.backColor = backColor;
        this.cols = cols;
        this.rows = rows;
        for (var r = 0; r < rows; r++) {
            this.blockColor[r] = new Array(cols);
        }
        this.xOffset = 20;
        this.yOffset = 20;
    }

    public draw(shape: Shape) {
        this.paintShape(shape, shape.fillColor);
    }

    public erase(shape: Shape) {
        this.paintShape(shape, this.backColor);
    }

    private paintShape(shape: Shape, color) {
        for (var i = 0; i < shape.points.length; i++) {
            this.paintSquare(shape.points[i].y, shape.points[i].x, color);
        }
    }

    // check the set of points to see if they are all free
    public isPosValid(points: Point[]) {
        var valid: boolean = true;
        for (var i = 0; i < points.length; i++) {
            if ((points[i].x < 0) ||
                (points[i].x >= this.cols) ||
                (points[i].y >= this.rows)) {
                valid = false;
                break;
            }
            if (points[i].y >= 0) {
                if (this.blockColor[points[i].y][points[i].x] != this.backColor) {
                    valid = false;
                    break;
                }
            }
        }
        return valid;
    }

    public addShape(shape: Shape) {
        for (var i = 0; i < shape.points.length; i++) {
            if (shape.points[i].y < 0) {
                // a block has landed and it isn't even fully on the grid yet
                return false;
            }
            this.blockColor[shape.points[i].y][shape.points[i].x] = shape.fillColor;
        }
        return true;
    }

    public eraseGrid() {
        this.context.fillStyle = this.backColor;
        var width = this.cols * this.blockSize;
        var height = this.rows * this.blockSize;

        this.context.fillRect(this.xOffset, this.yOffset, width, height);
    }

    public clearGrid() {
        for (var row = 0; row < this.rows; row++) {
            for (var col = 0; col < this.cols; col++) {
                this.blockColor[row][col] = this.backColor;
            }
        }
        this.eraseGrid();
    }

    private paintSquare(row, col, color) {
        if (row >= 0) { // don't paint rows that are above the grid
            this.context.fillStyle = color;
            this.context.fillRect(this.xOffset + col * this.blockSize, this.yOffset + row * this.blockSize, this.blockSize - 1, this.blockSize - 1);
        }
    }

    public drawGrid() {
        for (var row = 0; row < this.rows; row++) {
            for (var col = 0; col < this.cols; col++) {
                if (this.blockColor[row][col] !== this.backColor) {
                    this.paintSquare(row, col, this.blockColor[row][col]);
                }
            }
        }
    }

    public paint() {
        this.eraseGrid();
        this.drawGrid();
    }

    // ... a few more methods snipped for brevity

}

Keyboard Handling

The game is controlled by the keyboard, both for moving pieces and for starting/pausing the game. In the Game class constructor I subscribe to the keydown event with the following code:

        var x = this;
        document.onkeydown = function (e) { x.keyhandler(e); }; // gets the wrong thing as this, so capturing the right this

One slight disappointment with TypeScript is that it doesn’t do anything to fix the weirdness around JavaScript’s “this” keyword. In JavaScript, “this” isn’t always what you think it would be if you’ve got a background in Java/C#. I had to resort to little hacky tricks like this in various places to make sure the right “this” object would be available in the called method. I guess if I did more Javascript this would be second nature to me. Here’s the keyboard handler:

private keyhandler(event: KeyboardEvent) {
    var points;
    if (this.phase == Game.gameState.playing) {
        switch (event.keyCode) {
            case 39: // right
                points = this.currentShape.moveRight();
                break;
            case 37: // left
                points = this.currentShape.moveLeft();
                break;
            case 38: // up arrow
                points = this.currentShape.rotate(true);
                break;
            case 40: // down arrow
                // erase ourself first
                points = this.currentShape.drop();
                while (this.grid.isPosValid(points)) {
                    this.currentShape.setPos(points);
                    points = this.currentShape.drop();
                }

                this.shapeFinished();
                break;
        }

        switch (event.keyCode) {
            case 39: // right
            case 37: // left
            case 38: // up
                if (this.grid.isPosValid(points)) {
                    this.currentShape.setPos(points);
                }
                break;
        }
    }

    if (event.keyCode == 113) { // F2
        this.newGame();
        // loop drawScene

        // strange code required to get the right 'this' pointer on callbacks
        // http://stackoverflow.com/questions/2749244/javascript-setinterval-and-this-solution
        this.timerToken = setInterval((function (self) {
            return function () { self.gameTimer(); };
        })(this), this.speed);
    }
    else if (event.keyCode == 114) { // F3
        if (this.phase == Game.gameState.paused) {
            this.hideMessage();
            this.phase = Game.gameState.playing;
            this.grid.paint();
        }
        else if (this.phase == Game.gameState.playing) {
            this.phase = Game.gameState.paused;
            this.showMessage("PAUSED");
        }
    }
    else if (event.keyCode == 115) { // F4
        if ((this.level < 10) && (this.phase == Game.gameState.playing) || (this.phase == Game.gameState.paused)) {
            this.incrementLevel();
            this.updateLabels();
        }
    }
}

Timer

Any game needs a timer loop, and my original one would drop the falling block and paint the grid each tick. But I was also painting the falling brick from the keyboard handler whenever you moved it. So I refactored things slightly to have a rendering loop, which was doing all the drawing, and then a game timer, which dropped the current block and decided if you had lost, or progressed to the next level.

I discovered that the recommended way to create a render loop in Javascript seems to be window.requestAnimationFrame (with a fallback to window.setTimeout if that’s not available). For the game timer itself I carried on using window.setTimeout. Again, you have to jump through some hoops to get the right this pointer:

this.timerToken = setInterval((function (self) {
    return function () { self.gameTimer(); };
})(this), this.speed);

Messages

The final task was to show messages such as “Game over” and “Game paused”. I was in two minds about how to do this. I could either use place a div over the top of my canvas with the message in, or use fonts to draw onto the canvas. I initially went about trying to draw messages onto the canvas, which did work, but in the end I decided that simply positioning a floating div over the canvas to show messages was easier (although even that was quite frustrating to work out the correct CSS incantation).

I came up with this HTML and CSS to give me a floating message.

<div id="container">
    <canvas id="gameCanvas" width="240" height="360" ></canvas>
    <div id="floatingMessage" ></div>
</div>
#container {
    position: relative;
    float: left;
    background-color: cornflowerblue;
}

#gameCanvas {
    height: 360px;
    width: 240px;
}

#floatingMessage {
    position: absolute; 
    top: 120px; 
    left: 60px;
width: 120px;
text-align: center; background-color: azure; }

There’s still a whole host of improvements I ought to make to both the appearance and functionality of this game, but the point of this exercise was simply to see how easily I could get started with TypeScript. And the good news is, it seems pretty straightforward, even for someone without a lot of web development experience.

Try It

I’ve uploaded the code for my TypeScript Tetris app to GitHub, and you can also play it here. (Please note, this is not intended as a “best practices” guide to anything. This was my first ever TypeScript app, ported from my first ever Java app. So there are quite a few rough edges. Feel free to send me your comments, or fork it and show me how it should be done).

Wednesday, 15 May 2013

Knockout - What MVVM should have been like in XAML

I've not got a lot of JavaScript programming experience, but I've been learning a bit recently, and decided to try knockout.js. I was pleasantly surprised at how quickly I was able to pick it up. In part this is because it follows a MVVM approach very similar to what I am used to with WPF. I've blogged a three-part MVVM tutorial here before as well as occasionally expressing my frustrations with MVVM. So I was interested to see what the MVVM story is like for Javascript developers. What I wasn't expecting, was to find that MVVM in JavaScript using knockout.js is a much nicer experience than I was used to with XAML + C#. In this post I'll run through a few reasons why I was so impressed with knockout.

Clean Data-Binding Syntax


The first impressive thing is how straightforward the binding syntax is. Any HTML element can have a data-bind property attached to it, and that can hold a series of binding expressions. Here's a simple binding expression in knockout that puts text from your viewmodel into a div:

<div data-bind="text: message" ></div>

To bind multiple properties, you can just add extra binding statements into the single data-bind attribute as follows:

<button data-bind="click: prev, enable: enablePrev">

In XAML the syntax for basic bindings isn't too cumbersome, but a bit more repetitive nonetheless:

<TextBox Text="{Binding Message}" 
Enabled="{Binding EnableEditMessage}" />

Event Binding

One frustration with data binding in XAML is that you can't bind a function directly to an event. So for example when an animation finishes, it would be great to be able to call into a method on our ViewModel with something like this:

<Storyboard Completed="{Binding OnFinished}" />

Sadly, that is invalid XAML, but with knockout.js, binding to any event is trivial:

<div data-bind="click: handleItem"/>

Arbitrary expressions in binding syntax


XAML data binding does allow you to drill down into members of properties on your ViewModel. For example, you can do this:

<TextBlock Text="{Binding CurrentUser.LastName}" />

And it also does give you the ability to do a bit of string formatting, albeit with a ridiculously hard to remember syntax:

<TextBlock Text="{Binding Path=OrderDate, StringFormat='{}{0:dd.MM.yyyy}'}" />

But you can't call into a method on your ViewModel, or write expressions like this

<Button IsEnabled="{Binding Items.Count > 0}" />

However, in knockout.js, we have the freedom to write arbitrary bits of JavaScript right there in our binding syntax. It's simple to understand, and it just works:

<button data-bind="click: next, enable: index() < questions.length -1">Next</button>

This is brilliant, and it keeps the ViewModel from having to do unnecessary work just to manipulate data into the exact type and format needed for the data binding expression. (Anyone who's done MVVM with XAML will be all too familiar with the task of of turning booleans into Visibility values using converters)

Property Changed Notifications


Obviously, knockout needs some way for the ViewModel to report that a property has changed, so that the view can update itself. In the world of XAML this is done via the INotifyPropertyChanged interface, which is cumbersome to implement, even if you have a ViewModelBase class that you can ask to do the raising of the event for you.

private bool selected;
public bool Selected 
{
   get { return selected; }
   set   
   {
        if (selected != value)
        {
            selected = value;
            OnPropertyChanged("Selected");
        }
   }
}

Contrast this with the gloriously straightforward knockout approach which uses a ko.observable:

this.selected = ko.observable(false);

Now selected is a function that you call with no arguments to get the current value, and with a boolean argument to set its value. It's delightfully simple. I can't help but wonder if a similar idea could be somehow shoehorned into C#.

To be fair to the XAML MVVM world, you can alleviate some of the pain with Simon Cropp's superb Fody extension, which allows you to add in a compile time code weaver to automatically raise PropertyChanged events on your ViewModels. I use this on just about all my WPF projects now. It is a great timesaver and leaves your code looking a lot cleaner to boot. However, in my opinion, if you have to use code weaving its usually a sign that your language is lacking expressivity. I'd rather directly express myself in code.

Computed properties


Computed properties can be a pain in C# as well, as you have to remember to explicitly raise the PropertyChanged notification. (Although Fody is very powerful in this regard and can spot that a property getter on your ViewModel depends on other property getters.) Here's an example of a calculated FullName property in a C# ViewModel:

private string firstName;
public string FirstName 
{
   get { return firstName; }
   set   
   {
        if (firstName!= value)
        {
            firstName= value;
            OnPropertyChanged("FirstName");
            OnPropertyChanged("FullName");
        }
   }
}

public string FullName 
{
    get { return FirstName + " " + Surname; }
}

Knockout's solution to this is once again elegant and simple. You simply declare a ko.computed type on your ViewModel:
this.fullName = ko.computed(function() {
     return this.firstName() + " " + this.lastName();
}, this);

Elegant handling of binding to parent and root data contexts


Another area that causes regular pain for me with XAML databinding is when you need to bind to your parent's context or the root context. I think I've just about got the syntax memorized now, but I must have searched for it on StackOverflow hundreds of times before it finally stuck. You end up writing monstrosities like this:

...Binding="{Binding RelativeSource={RelativeSource FindAncestor, 
AncestorType={x:Type Window}}, Path=DataContext.AllowItemCommand}" ...

In knockout, once again, the solution is simple and elegant, allowing you to use $parent to access your parent data context (and grandparents with $parent[1] etc), or $root. Read more about knockout's binding context here.

<div data-bind="foreach: currentQuestion().answers">
    <div data-bind="html: answer, click: $parent.currentQuestion().select"></div>
</div>

Custom binding extensions!


Finally, the killer feature. If only we could add custom binding expressions to XAML, then maybe we could work around some of its limitations and upgrade it with powerful capabilities. Whilst I have a feeling that this is in fact technically possible, I don't know of anyone who has actually done it. Once again knockout completely knocks XAML out of the water on this front, with a very straightforward extensibility model for you to create your own powerful extensions. If you run through the knockout tutorial, you'll implement one yourself and be amazed at how easy it is.


Conclusion

I've only used knockout.js for a few hours (here's what I made) and all I can say is I am very jealous of its powers. This is what data binding in XAML ought to have been like. XAML has been around for some time now, but there have been very few innovations in the data-binding space (we have seen the arrival of behaviours, visual state managers, merged dictionaries, format strings, but all of them suffer from the same clunky, hard to remember syntax). And now we have another subtly different flavour of XAML to learn for Windows Store 8 apps, it seems that XAML is here to stay. Maybe it is time for us to put some pressure onto Microsoft to give XAML data binding power to rival what the JavaScript community seem to be able to take for granted.