Taghtml5

HTML5 Games Presentation for MemTech Super User Group

SlideshowShot

Slideshow | Code

Memphis flies under the radar as a technology hub, but there’s still a pretty active community of developers and other technologists that like to meet up and do stuff. I occasionally pop in on the PHP User Group, Ruby User Group, and Python User Group meetups when I get the chance. Every few months, the various user groups organize a joint meetup called the Super User Group Meetup and feature presentations on platform agnostic topics such as development tools, front-end development, processes, and whwatever else people want to talk about.

For the most recent meetup on June 20, 2013, I threw my name in the ring as a presenter and gave a talk about the what, where and how of HTML5 games. It’s nothing terribly complex or in-depth, just a brief survey of the general idea of developing games for the web using web based standards.

This was the first time I’d used the Reveal.js slideshow library. It was a pretty positive experience, especially with the help of slid.es to get started. Embedding live javascript is pretty boss. Also, there are a lot of great plugins, and I definitely took advantage of the ‘notes server’ so I could display the slides on once screen, and my notes on another. I’ll be using Reveal again in the future.

Construct 2 HTML5 Mobile Game: Turkey Trot of Doom!!

So it’s a week before Thanksgiving and I get an email from the hostess of the dinner I plan on attending. Included was a list of dishes assigned for guests to bring. The usual suspects were present: stuffing, cranberry sauce, pie, lots of pie…

But when I finally got to my name, a ‘holiday themed video game’ was requested.

“Ha!” I thought, funny joke, can’t be done. But then I thought some more. Perhaps it could be done. I’ve always wanted to try making one of those newfangled mobile HTML5 games that all the kids are talking about, and here was the perfect motivation. To make things even more interesting, I decided to try out Construct 2 – a drag-n-drop game maker that exports to HTML5. I haven’t used anything of the sort since Klik ‘n Play back in 1995. Construct 2 is much, much cooler.

The interface is mostly intuitive, but reading the manual is definitely necessary to do anything meaningful. After a few hours of fiddling with the sample projects and reading bits and pieces from the manual and a few tutorials I was confident enough to at least begin my own project. After I got started, many grand ideas popped into my head, but there just wasn’t time. I had an hour here, and an hour there to work, and Turkey Day was quickly approaching. In the end, I managed to get one major feature from my wishlist working – accelerometer controls. When playing the game on a mobile browser, the player moves by tilting the device. It works pretty well on a modern iPhone (4, 4s, 5) and iPads. Doesn’t work so great on Android, but you can still get the gist of it.

Rather than go into too much detail on how the game was assembled within Construct 2, I’ll just post the game file for download. There’s nothing terribly complicated going on, and the way the event sheets are organized, it reads almost like a book. You can download the file here.

To play the game, simply visit http://turkey.thebogstras.com. If you are using a mobile device, make sure it is in landscape orientation with the home button on the right. It takes a while to get used to the tilt controls, and you will probably die very quickly. If playing on a desktop browser, click the mouse where you want the character to move.

Remember, this game was never intended to be fun. It’s sole purpose was to be a game, and have some Thanksgivingy stuff in it. Fun was never a requirement.

Credits for artwork:
Boss Turkey – Puppet Nightmares
Turkey Leg – Kenj
Mini Turkey – MikariStar
Evil Turkeys – DMN666

AngularJS SignIt! – Custom directives and form controls

Note: This is a companion post to Example CRUD App – Starring AngularJS, Backbone, Parse, StackMob and Yeoman. If you haven’t read that yet, please do so, otherwise this might not make much sense.

The most prominent feature, by far, of AngularJS SignIt! is the signature pad. It’s a fixed-size canvas that can be drawn upon with a mouse pointer or finger. The code for this wonderful widget is provided as a jQuery plugin by Thomas Bradley. There are a few more features for the signature pad than I use in this app, and I encourage you to check out the full documentation if you get a chance. It’s pretty great.

In order to implement the signature pad into my form, It must be a required field, and have the data included with the other fields when the form is submitted. The sig pad works by creating objects of x/y coordinates that correspond to marks on the canvas. When drawing on the pad, all that data gets set into a hidden form field. The data from that field is what needs to get into the Angular scope, and get validated by Angular’s form validation routine. Oh, and Angular somehow needs to fire the custom validation function built into the signature pad.

Luckily, this is the type of thing directives were built for. Custom directives let you create custom html tags that get parsed and rendered by Angular. So to start out, I created a custom directive called sigpad that is used by placing <sigpad></sigpad> in my HTML. The sigpad tag then gets replaced by the directive’s template HTML. The template for the HTML5 signature pad is just the default snippet taken directly from the signature pad documentation. See below:

<div class="control sigPad">
  <div class="sig sigWrapper">
    <canvas class="pad" width="436" height="120" ng-mouseup="updateModel()"></canvas>
  </div>
</div>

The logic for the directive is defined in a separate Angular module (see directives.js for full code). Take a look at the code below, and be sure to review Angular’s documentation on directives. The Angular docs give a great conceptual overview, but the examples are a bit lacking. I reviewed the docs many, many times, and still needed some help from the to get this working correctly (thanks P.B. Darwin!).

My biggest stumbling block was not using ngModelController, and instead trying to manipulate scope data directly. When working with a form, Angular provides all sorts of awesome code to work with data and do some validation. Basically, it all went down like this…

Insert the sigpad directive into the form with

<sigpad ng-model='user.signature' clearBtn=".clearButton" name="signature" required></sigpad>

Now Angular knows to replace the sigpad element with the template defined earlier. After this happens, Angular runs the linking function which contains all the logic for the directive. The little snippet shown below is in the linking function. It uses jQuery to select the template element (passed into the linking function as ‘element’) and runs the signaturePad function from the signature pad API. This is what creates the actual, drawable canvas.

var sigPadAPI = $(element).signaturePad({
                             drawOnly:true,
                             lineColour: '#FFF'
                           });

The ng-model=’user.signature’ bit is key. This is how data is shared between the signature pad and Angular. Also, go back up and look at the template. You will see ng-mouseup="updateModel() as an attribute of the canvas element. This tells Angular to run the updateModel() function when your mouse click ends on the signature pad. The updateModel() function is defined in the linking function of the sigpad directive.

When the updateModel() function is executed, it will wait for a split second so the signature pad can finish writing data to its hidden form field, then it will assign all that data to the Angular model value of the directive. Sounds confusing, and it is. The signature pad is off doing its own thing, completely oblivious to the fact that it is in an AngularJS app. It is Angular’s responsibility to grab data from the sigpad to get that data into its own scope. That is what $setViewValue is for. It hands the signature data over to Angular, so when the form is submitted, Angular has it available in scope.

Below is the entire directive for the drawable signature pad. You can see that it relies heavily on the signature pad API, but only after certain events handled by Angular have occurred.

.directive('sigpad', function($timeout){
  return {
    templateUrl: 'views/sigPad.html',   // Use a template in an external file
    restrict: 'E',                      // Must use <sigpad> element to invoke directive
    scope : true,                       // Create a new scope for the directive
    require: 'ngModel',                 // Require the ngModel controller for the linking function
    link: function (scope,element,attr,ctrl) {

      // Attach the Signature Pad plugin to the template and keep a reference to the signature pad as 'sigPadAPI'
      var sigPadAPI = $(element).signaturePad({
                                  drawOnly:true,
                                  lineColour: '#FFF'
                                });
     
      // Clear the canvas when the 'clear' button is clicked
      $(attr.clearbtn).on('click',function (e) {
        sigPadAPI.clearCanvas();
      });
     
      $(element).find('.pad').on('touchend',function (obj) {
        scope.updateModel();
      });

      // when the mouse is lifted from the canvas, set the signature pad data as the model value
      scope.updateModel = function() {
        $timeout(function() {
          ctrl.$setViewValue(sigPadAPI.getSignature());
        });
      };      
     
      // Render the signature data when the model has data. Otherwise clear the canvas.
      ctrl.$render = function() {
        if ( ctrl.$viewValue ) {
          sigPadAPI.regenerate(ctrl.$viewValue);
        } else {
          // This occurs when signatureData is set to null in the main controller
          sigPadAPI.clearCanvas();
        }
      };
     
      // Validate signature pad.
      // See http://docs.angularjs.org/guide/forms for more detail on how this works.
      ctrl.$parsers.unshift(function(viewValue) {
        if ( sigPadAPI.validateForm() ) {
          ctrl.$setValidity('sigpad', true);
          return viewValue;
        } else {
          ctrl.$setValidity('sigpad', false);
          return undefined;
        }
      });      
    }
  };
})

And what about the tiny signatures that show up in the signatories list? Also a custom directive. This one is smaller, but still tricky. The signature is displayed as an image on-screen, but a canvas element is still required to generate the signature from raw data before it can be converted to an image.

The directive is implemented with <regensigpad sigdata={{signed.get('signature')}}></regensigpad>. The ‘signed’ value is a single signature in the signature collection pulled from the back-end when the user picks a petition. the signature data from signed is passed into the directive scope using scope: {sigdata:'@'}.

When a list of signatures is retrieved, each signature record (including first & last name, email, and signature data) goes into a table row using ngRepeat. The regensigpad directive is executed for each row. The linking function will create a canvas element and make a displayOnly signature pad from it. The signature drawing is regenerated from the data, and then the canvas is converted to PNG format.

This PNG data is then used in the pic scope value, which is bound to the ng-src of an img tag. This img tag is the directive’s template, and will be inserted into the page. The full code for this directive is below.

.directive('regensigpad',function() {
  return {
    template: '<img ng-src="{{pic}}" />',
    restrict: 'E',
    scope: {sigdata:'@'},
    link: function (scope,element,attr,ctrl) {
      // When the sigdata attribute changes...
      attr.$observe('sigdata',function (val) {
        // ... create a blank canvas template and attach the signature pad plugin
        var sigPadAPI = $('<div class="sig sigWrapper"><canvas class="pad" width="436" height="120"></canvas></div>').signaturePad({
                          displayOnly: true
                        });
        // regenerate the signature onto the canvas
        sigPadAPI.regenerate(val);
        // convert the canvas to a PNG (Newer versions of Chrome, FF, and Safari only.)
        scope.pic = sigPadAPI.getSignatureImage();
      });
    }
  };
});

But that’s not all! You might have noticed that the select box holding the names of each petition looks kinda fancy, and allows you to type stuff to filter the list. This fancy form control is the select2 widget which is based of the Chosen library.

I didn’t have to write my own directive for it though. The Angular-UI project has already done the honors. Angular-UI is an open-source companion suite for AngularJS. It provides a whole pile of custom directives, and even a few extra filters. Many of the directives are wrappers for other widgets and open source projects, like CodeMirror, Google Maps, Twitter Bootstrap modal windows, and many more. It’s definitely worth looking into for any AngularJS project.

© 2018 Eric Terpstra

Theme by Anders NorénUp ↑