Friday, April 17, 2015

Publish/Subscribe with jQuery

The frog dodgeball thing from Wednesday's comic was probably more fun for me to create than it was to play. Embedding a simple game in a comic, even a SVG/CSS/JavaScript comic, was not the easiest thing to do. But I used some very effective design patterns to make it easier.

Not a Sub, a Pub/Sub
The comic has supported simple animations since the beginning, but for the game to work I needed to add a custom module to just that one comic which could take additional actions when the animation state changed. I certainly didn't want to tightly couple the general-purpose animation code to this one comic, and also I didn't want to duplicate the most of the animation code in this module just to add one feature. Since I may want to do similar things in the future as well, I wanted a solution that would be flexible.

I decided to use the Publish/Subscribe Pattern. A derivative of the Observer Pattern, a Publish/Subscribe model allows me to completely decouple the event generator (my animation code in this case) from any other components that may wish to take action on certain events (the game code).

The Publish/Subscribe pattern has three parts:

  1. the publisher (creates the events)
  2. the subscriber(s) (want to be notified of events)
  3. the controller (takes events from publishers to subscribers).


My animated comic objects will publish events at certain points in their animation cycles. It doesn't matter if no one is subscribed to those events or if 100 other objects are subscribed. The general contract is that the subscriber says to the controller, "call my notify method when event X happens" and the publisher says to the controller, "event X just happened" the controller will pass the message on to every subscriber by calling the notify method. The publisher doesn't have any idea who is subscribed.

Fortunately, jQuery provides the controller. In jQuery-speak, this system is called custom events. Basically, the .trigger(event) method on jQuery objects invokes a controller that notifies any other objects that may be subscribed to that particular event on that object.

Consider the following example.

<!doctype html>

<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Pub/Sub</title>
</head>

<body>

  <p id="publisher">I have something to say.</p>

  <p id="target">Nothing here.</p>

</body>

<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>

<script>

$(function() {

    // subscribe to events named "myEvent" from #publisher
    $("#publisher").on("myEvent", function(event, data) {

        $("#target").html(data.text);

    });

    // using setTimeout to simulate an asynchronous event
    setTimeout(function() {

        var myData = {
            text: "This is my event text"
        }
        // publish a "myEvent" event, with some custom data
        $("#publisher").trigger("myEvent", [myData]);

    }, 5000);

});

</script>

</html>

As soon as the page is loaded, it sets up a subscriber function to "myEvent" events that may come out of the P element named "publisher." I used setTimeout to simulate an asynchronous event that may happen sometime on your page. When it does, the "publisher" publishes its "myEvent" along with some data. The subscriber function is called, and the P element named "target" changes its contents to be whatever was provided as data.

If you execute this code yourself, you'll see that the text "Nothing here" is replaced by "This is my event text" after 5 seconds.

I used this pattern on IMG tags to have them publish events at certain points in their animation cycles, so I am now able to make comic-specific code that can take special actions on general-purpose animations. All I had to do was add a single line with a call to .trigger() to my animation function! That means comic-cell games will now be even easier for me to create! There will be more!

But not today. It's just a normal comic with a little animation.

Amphibian.com comic for 17 April 2015

Wednesday, April 15, 2015

Sounds Good

Today's comic was a lot of fun to create. If you haven't seen it yet, go there right away. You won't regret it. It's much more entertaining than this blog.

If you're still reading, it means you've either already looked at the comic or you just ignored my advice in the first paragraph. Let's move on.

So the third frame in the comic is a frog dodgeball game. Every time you click (or touch) it launches a ball at the frogs. If they get hit, their agility score goes down. It's really pointless. But still, throwing red balls at frogs as they hop past is strangely entertaining.

There's a lot of good programming topics that came up while I was making it. I added animation event emitters so that I could use a listener pattern for the frogs' paths. I added animation that changes the image of an object as it moves around on the screen. I added collision detection that uses jQuery selectors. All good stuff.

Creative Commons Licensed Sounds
But the one thing I would like to mention here today is where I get the sound effects. The sound the page makes when you successfully hit a frog is the same sound I used in my GitHub Game Off 2015 game entry for when Business Frog gets hit by an apple. I got it and all my other sound effects from Freesound.org.

Previously, I've mentioned how I sometimes get SVG clipart from OpenClipart.org. Freesound is like the same thing, but for sounds. All of the sound effects on Freesound are licensed under one of the Creative Commons license agreements. Many completely free, having been donated to the public domain. Most are licensed by Attribution, which means you just need to give credit to the creator. There are vast amounts of sound effects that are perfect for the kinds of small web-based games that I like to create.

You'll need to create an account in order to download the sounds, but you can listen to them right on the web until you find the perfect one. Unlike with OpenClipart, I'm not really capable of creating any kind of audio files that anyone would want - so I don't upload my own work. But if you do make your own sound effects, by all means share them! The world will be a better place for it!

One final thought. The sound files on Freesound.org tend to come in a variety of formats. Typically I need them in .mp3 or .ogg format for my games. I've found Audacity to be a great tool for my simple audio conversion and editing needs.

Here's another link to that comic, in case you missed it.

Amphibian.com comic for 15 April 2015

Monday, April 13, 2015

Goodbye, GitHub Game Off 2015

And so today the GitHub Game Off 2015 has ended. The last four weeks have been busy, but I'm happy with my entry this year. Even though I didn't get to write a game completely from scratch like I did back in 2013, learning the Crafty framework was worth it.

Learning to use a new framework is good in itself, but what I've really liked about Crafty is that I've found such interesting things while looking at its source code. I wrote last week about how it is able to make read-only fields on JavaScript objects, but here's another neat trick I found.

One feature that Crafty offers is the ability to draw the game entities with either Canvas or the DOM. You can even mix the two in your game, like I did in mine (it was done that way in Octocat Jump originally). All "2D" entities have a .flip() method which, you guessed it, flips the entity's image backwards. I thought I knew how this was done for Canvas entities, but it also works on DOM entities. I had to look in the code to see how the flip was performed.

When I saw it, I said to myself, "Of course! Why didn't I think of that?"

You can flip any element in the DOM using the CSS3 2D transform scale methods. Just set the scale to a negative number.

<div id="flipMe" style="transform: scaleX(-1);">
    this will be backwards
</div>

You can do it programmatically with jQuery just as easily.

$("#flipMe").css("transform", "scaleX(-1)");

I knew you could scale DOM objects this way but it never occurred to me that a scale of -1 on the X or Y axis would just flip the object!

Flipping a comic cell. The one on the right has had a transform of  scaleX(-1) applied.

Just another reason that I love looking in open source code, and you should too! Hopefully GitHub posts a list of all the Game Off 2015 entries soon, so we'll all be able to learn new techniques by looking at other people's code.

You know what else you should love looking at? My frog comics! Here's a link to today's...

Amphibian.com comic for 13 April 2015

Friday, April 10, 2015

Listen to the Spring Peepers

This week I was able to hear one of my favorite sounds again - the Spring Peepers. Not some weird hipster music group, but the small chorus frogs Pseudacris crucifer.

I love listening to the chorus of these tiny amphibians every spring here in central Pennsylvania. When I was a child I lived next to the Tuscarora Creek where it was easy to listen to them every evening. Now I am a bit more removed from a suitable habitat and don't get to hear them nearly as much as I'd like. And they don't seem to last as long as they used to. It seems like I only get to hear them for a week or two in April, although they supposedly will call until June.

If you don't live in the eastern United States you may have never heard these little frogs. Listen to these audio files and hear what you've been missing.

The sound of a single frog: 

The whole chorus of frogs: 

If I hadn't told you they were frogs, you might mistake them for some kind of insect or something. Maybe even a bird, if it called at night. But most birds don't call at night. Only owls.

They might not be spring peepers, but my comic frogs can also entertain you today. For a few minutes at least.

Amphibian.com comic for 10 April 2015



Wednesday, April 8, 2015

ALTER comic DROP MySQL

I've decided to migrate my comic away from MySQL. I have my reasons. Lots of people have reasons.

Some people complain that MySQL isn't truly open source anymore. It's true that it does have closed-source modules now. And Oracle is not exactly forthcoming with test cases or security patches. But these things don't bother me that much, since I'm just looking for a free, easy to use database.

Some people say that MySQL is not standards-compliant. Well, this is not my main reason but certainly a factor. I've been doing SQL for a looong time, and MySQL's is weird. I've always just dealt with it. But it would be nice to not have to think about is this the MySQL way or the normal way when I'm working on something.

Some people say that the performance doesn't scale as well as other RDBMS software. I don't know. I only ever use it for basic, low-performance stuff.

Some people say that MySQL has become stagnant. Ah, this is certainly a factor for me. It seems as though Oracle doesn't have a lot of interest in making MySQL better. And why would they? It completes with their classic RDBMS, which makes them big money. Honestly, up until this point I've just been happy that they haven't killed it off altogether. Some people have forked MySQL, like MariaDB, to move the product forward.

PostgreSQL. I'm going back.
But it's the new features in PostgreSQL that really have me wanting to change. Specifically the native JSON support. Since I store and work with my comic data in JSON, it makes sense to use a database that treats JSON as a first-class data type. I know that many of the popular NoSQL databases do this, but I don't have other use cases that drive me towards a NoSQL solution.

I once used Postgres for all my projects. It was my go-to RDBMS product back around 2001. But then I hopped on the MySQL train with everyone else and rode it to Disillusionment Town. Now I'm heading back.

I'm currently working with the node-postgres client pg to convert my comic. Thanks to my prior design decisions, it is fairly easy to swap one product for another. I use a module I called data.js which encapsulates all the database details. I've swapped it out for a new pg-data.js which implements all the same functions and I'm working through the issues. The Node pg module uses a fairly different design pattern than the mysql module does, particularly for pooled connections. That's really my biggest hurdle.

And now for the comic! They haven't been very deep lately. I've been putting too much time into the GitHub Game Off for the past 2 and half weeks. But I am working on a very interesting set for later in the month.

The Game Off ends Monday! Remember to play my game: http://caseyleonard.com/ggo15!


Amphibian.com comic for 8 April 2015

Monday, April 6, 2015

Cross-Site Scripting (Legitimately)

This weekend I completed one of the major features that I wanted to add to my GitHub Game Off 2015 game - the high scores list. While it may sound mundane, it has one feature that I don't use a whole lot - JSONP.

JSONP, or JSON with Padding, is in my opinion a technique that has a very misleading name. It's really about bypassing the same-origin policy that web browsers use to prevent cross-site scripting hacks. And it works by having the server respond with full JavaScript instead of just a JSON string. The JavaScript is typically a function call with the JSON string directly in the call. I guess that's where the "padding" part of the names comes from - the data is "padded" with the function call. Odd if you ask me, but whatever.

Here's a basic example. For it to work, the client defines a function to process the data it wants to request from the server.

function processData(data) {
    console.log(data); // or do something more useful, whatever
}

Now the request can be made. By injecting a <script> tag into the DOM, the browser will make a remote call to any server you want - it doesn't have to be the same as the one serving the original page. As part of the URL in that script tag, the name of the local function is typically passed as part of the query string. The script tag would look like this...

<script type="application/javascript"
     src="http://www.example.com/giveMeData?callback=processData"></script>

On the server, the data is then prepared for the response. Instead of just sending a JSON string, the server creates a string response that looks like a regular JavaScript function call. The function being called is the one specified in the script tag URL, and the JSON data is directly in the call. This is what the server response text looks like:

processData({"field1":"value1","field2":"value2"});

The browser treats the response just the same as any static JavaScript file requested from a server and executes it. Your data processing function gets called, you get the data, and everyone is happy.

For this to work, the server obviously has to be set up for this. You can't just pass a "callback" query string parameter to any random web server and expect a usable response. This pattern is most useful for creators of data services who want to make their product available on other peoples' web pages. Like the Facebook buttons, for example.

I found myself wanting to use this pattern because I put my game on caseyleonard.com, but that site just serves static content via Nginx. To maintain the high scores web service, I'd have to run an application somewhere else. Without the JSONP pattern, my game wouldn't be able to send and receive high score data. It was also useful to allow me to test updates to my game locally and still access the high scores on a remote server.

As it turns out, this pattern is common enough that jQuery includes some utilities to make it easier. They have a really nice API that makes performing a JSONP request almost the same as a "normal" AJAX request. Here's an example from my game code.

function processHighScores(data) {
 
    var $tbl = $("#scoreboard");
    for(var i=0; i < data.length; i++) {
     var n = data[i].name;
     var s = data[i].score;
        var $row = ("<tr><td>" + n + "</td><td>" + s + "</td></tr>");
        $tbl.append($row);
    }

}

function populateHighScores() {

    $.ajax({
        type: "GET",
        url: "http://amphibian.com/scores",
        jsonpCallback: "processHighScores",
        contentType: "application/json",
        dataType: "jsonp",
        success: function(json) {
            console.log(json); // don't really need this
        },
        error: function(e) {
            console.log(e.message);
        }
    }); 
}

The processHighScores function above is the one that receives the data from the JSONP request. The populateHighScores function makes the call. As you can see, jQuery makes it easy by allowing me to specify just the URL and then the name of the JSONP callback as another field (line 18). When it builds the script tag for me, it automatically adds the "?callback=processHighScores" to the end of the URL.

I wrote the high scores application using Node. All of the routes I set up are designed for JSONP callbacks. In each one, the response is built as a string using the callback parameter. One thing to note is that the proper content type for a JSONP response is "application/javascript" not "application/json". It is legitimate JavaScript, pretty much like you'd have in a static .js file. The only difference is that you are generating it dynamically. Here is the server-side route that handles the client request from above:

app.get("/scores", function(req, res, next) {

    var fn = req.query.callback;

    var data = JSON.stringify(scores);

    var js = fn + "(" + data + ");";

    res.setHeader("Content-Type", "application/javascript");
    res.send(js);

});

Dynamically generating JavaScript based on URL parameters in the request is nothing new. I was doing it back in the '90's as part of ASP web applications. But back then I never thought about it as a way to bypass the same-origin policy. I'm not even sure I even knew what the same-origin policy was back then. It was a simpler time...back when I drew these frogs by hand.

Amphibian.com comic for 6 April 2015

Friday, April 3, 2015

Stay Out Of My Objects!

While working on my game for the GitHub Game Off this week, I was looking in the code for Crafty.js. Crafty is the JavaScript game engine used by the game I forked for the contest, and I was curious about how it did some things. I noticed some JavaScript features it in that I don't see used very often and I thought it was interesting enough to share.

Have you ever wanted to make a field in a JavaScript object read-only? Consider this example:

var o = {
    answer: 42
};

console.log(o.answer); // prints 42
o.answer = 84;
console.log(o.answer); // prints 84

Typically, you might not care that you can reassign answer to some other value. Perfectly normal, right? Sure. But what if you were making a library that you want to share and be used by other people in other projects? You might not want them accidentally (or on purpose) messing with your object internals.

So try this:

var o = {};

Object.defineProperty(o, 'answer', {
    value: 42,
    writable: false
});

console.log(o.answer); // prints 42
o.answer = 84;
console.log(o.answer); // prints 42 again! ha!

Now you'll see that the answer of 42 prints out both times. The reassignment had no effect. You've created a read-only field on the object!

The JavaScript function Object.defineProperty gives you much more control over the properties on your objects. In addition to writable, you can also specify if a field should be enumerable. Being enumerable means that the property shows up during property enumeration of the object. Look at this example:

var o = {};

Object.defineProperty(o, "answer", {
    value: 42,
    writable: false,
    enumerable: false
});

Object.defineProperty(o, "whatnot", {
    value: 33.3,
    enumerable: true
});

Object.defineProperty(o, "here", {
    value: "there",
    enumerable: true
});

for (var i in o) {
    console.log(i);
}

The example above will output "whatnot" and "here" but not "answer." The answer field does still show up if you console.log(o) in modern Chrome, however. It will also be visible in the debugger, so this is more about hiding things from other code that it is from people.

The answer can be seen here, but not enumerated.

There's another neat trick you can do with Object.defineProperty, which is create getter and setter functions. Instead of just getting or setting a field's value in your code, defining a custom getter or setter means that a function is invoked which can take other actions. Here is an example:

var o = {
    theAnswer: 42,
    answersGiven: 0
};

Object.defineProperty(o, "answer", {
    get: function() {
        console.log("giving an answer");
        this.answersGiven++;
        return this.theAnswer; 
    },
    set: function(a) {
        console.log("changing the answer!");
        this.theAnswer = a * 2;
    }
});

var myAnswer = o.answer;
console.log(myAnswer); // prints 42

o.answer = 15; // changes the answer, but not to 15!

var myNextAnswer = o.answer;
console.log(myNextAnswer); // prints 30

console.log(o.answersGiven); // prints 2

In the code above, the special getter function is called and an internal counter is incremented each time o.answer is invoked. Similarly, assigning o.answer to a value calls the setter function which has its own ideas about what value should really be set.

I don't know if these things will ever be useful to you, but at the very least I hope you found them as interesting as I did. Always look in the code for open-source libraries! You never know what cool tricks you'll see in them.

Remember to try out my game at http://caseyleonard.com/ggo15 and give me some feedback. I still have over a week left to work on it!

There's one thing that bothers me now, though. Why is there a w in answer?

Amphibian.com comic for 3 April 2015