Monday, March 30, 2015

How Do You Like Them Apples?

Throwing Apples!
More progress on my game entry for the GitHub Game Off 2015! I've been working down the list I made for myself back when I started, and this weekend I was able to add the projectiles that come in from the sides and try to knock you off the platforms as you jump.

What image did I select for these projectiles?

Apples, of course.

Why apples? Well first of all, I had an apple image already. I made it for the February 18th comic. Secondly, both me and my daughter Alex are allergic to apples. They are actually bad for us. So it seemed like a good thing to throw at frogs. Does it have some kind of sinister, hidden meaning which implies that iPhones are dangerous as well? No. Not really. My intention was to have something to represent new requirements that are thrown at you during the development cycle...you know, stuff that knocks you off your schedule. The game is jumping through a Gantt chart. Apples make sense for that, right? No? Maybe I need a better metaphor.

I'm sure that you are wondering how easy it is to add game elements using the Crafty game framework. Good, because I'm going to tell you. It was not very difficult. As I talked about last week, everything you see on the screen in a Crafty game (and some things that you don't see too!) is an Entity, and Entities are created with the properties of one or more Components. I defined my own "Apple" component and then simply added a method to create Apple entities randomly.

This is the Component creation code.

Crafty.c("Apple", {
    init: function () {
        this._dir = (Math.random() < 0.5 ? -1 : 1);
        this.x = ( this._dir > 0 ? -(this._w) : (Crafty.viewport.width + (this._w)));
        this.y = (Crafty.viewport.height / 4) - (Crafty.viewport.y);
        this.z = 9999;
        this.bind("EnterFrame", this._enterframe);
    },
    _enterframe: function () {
        this.x = this._x + (this._dir * 4.5);
        if (this._x < -(this._w*2) || this._x > Crafty.viewport.width + (this._w*2)) {
            this.destroy();
        }
    }
});

And this is the Entity creation code.

Crafty.e("2D, DOM, Image, Tween, Apple")
    .image("assets/images/apple.png");

Here's how it works... Calling Crafty.c(String, Object) creates a new Component with the name given by the first parameter and the properties given in the second parameter. In my code, I made an Apple component that had two properties: a function called init and a function called _enterframe. You can define whatever you want in this object and everything will get copied into any Entity you create using this component, with two exceptions. Crafty has two special-purpose functions that can be included in the object: init and remove. I don't use remove, but I do have init. The special behavior is that the init function will be called whenever this component is added to an Entity (often at creation time, but it can be at any point). My init function sets up some interval variables such as the direction of the apple (from the left or from the right) and its position on the screen. The last thing it does is bind the "EnterFrame" event to the other function, _enterframe. The "EnterFrame" event is fired by Crafty for every frame of the game, meaning pretty much constantly. That's why I use a function bound to that event to update the position of the Apple. They only move horizontally, so the function just updates their x-value until they move off the opposite side of the screen - at which point they are destroyed.

One thing that troubles me a little with this setup is that I know that I will be changing the x-value of each apple by 4.5 pixels each frame, but I don't actually know what that really means in terms of speed. I know from my past work with JavaScript game engines that while 60 frames per second is the goal of functions like window.requestAnimationFrame(callback), stuff happens. By specifying movement per frame instead of movement per second, the game will slow down instead of getting "choppy" if the browser can't keep up for whatever reason. I might change this behavior, but it seems to be a common approach in Crafty. Perhaps it's accounted for in some other way that I haven't realized yet.

By the way, I don't typically call my "private" methods names that start with an underscore, but I am doing it in this game simply because the original author did it. I tend to continue things like naming and code style when I work with other people's code...even though in this case I'm not planning on submitting a pull request back to Octocat Jump.

That's all I'm doing for today. I still want to make more changes, but I have to do things in small steps. I still have comics to write, you know. And remember, you can play the latest version of the game at http://caseyleonard.com/ggo15.

Amphibian.com comic for 30 March 2015

Friday, March 27, 2015

Missing a Page, Finding a Game

Nothing new to report on my GitHub Game Off 2015 entry today. I was at my daughter's spelling bee tonight instead of working on it. She didn't win, because she spelled hurtle instead of hurdle. The lesson here is to always ask for the word to be used in a sentence. But how many times have you heard someone say that an object was hurdling toward them? Was it really jumping over things? Anyway...
No page? Have some Pac-Man!

I would like to share something interesting that I discovered while looking for a game to fork for the competition. Apparently, there are a lot of simple web-based games that have been made for 404 pages. It's like a consolation prize, I suppose. Your page could not be found, but here's a game!

Here is a list of some of them.
Sure, there are a lot of creative, nice-looking 404 pages out there...but these are real, working games! If more web sites did this, getting a broken link would actually be enjoyable.

The 404 page on Amphibian.com seems rather dull after playing these. After I finish this GitHub Game Off game I'd better get working on an original game for my 404 page. And remember to play my game entry and give me some feedback: http://caseyleonard.com/ggo15.

In today's comic, the frogs aren't going to end up with a 404 when looking for a unicorn...or at least when looking to enter the unicorn club.

Amphibian.com comic for 27 March 2015

Wednesday, March 25, 2015

Still Game Jamming

I'm still making progress on my GitHub Game Off 2015 entry. You can play the latest version at http://caseyleonard.com/ggo15/ and look at all my code on GitHub.

Over the past few days, I've been able to add a new power-up that temporarily extends the width of the platforms and some graphical changes which make the game look more like a Gantt chart.

Thanks to the Crafty framework, these changes were relatively easy. First, the power-up. So far I've just picked random accessories from my comic to be placeholders for the different items in the game. There are hamburgers, which are just good for bonus points at the end, and a briefcase for a warp portal. I chose to use a piece of cake for the platform-extender.

To make pieces of cake appear in the game above certain platforms, I just had to create Entities for them. With a certain probability every time a platform is created, I use code like this:

Crafty.e("2D, DOM, Pickup, Cake, Image")
    .image("assets/images/cake.png");

Everything in a Crafty-based game is an entity, which is created by calling Crafty.e(string) where string is a comma-delimited list of component names. The entity created will have the features of all components in the list. In the case of the cake, I created my cake entities to be 2D, DOM, Pickup, Cake, and Image components. The Image component is what allows me to call .image on the newly created entity to set the picture to my piece of cake. Piece of cake!

To make the cake do something when it collides with my frog, I have to add a function somewhere to call when hit. Here's an example.

function onHitCake(e) {

    var entity = e[0].obj;
    entity.removeComponent("Pickup");
    entity.removeComponent("Cake", true);
    entity.destroy();
            
    Crafty("Platform").each(function (i) {
        var p = this;
        var width = 125;
        var nx = p._x - ((width - p._w)/2);
        p.attr({
            "w": width,
            "x": nx
        });
    });

}

When calling Crafty(string), it works much like jQuery to give you the one or more components that match the component ids given by the string parameter. So on line 8 above, I am getting the set of all the Platform entities and executing a function on each of them. In that function, I give them a new width and re-center them based on their new size by changing their x value.

The only thing left to do is tie it all together with collisions. The frog entity (which is still called octocat in the code - I'll rename it one of these days) is created with the Collision component, allowing me to specify behavior when hitting other entities. The example code below is simplified a bit to remove a bunch of stuff that takes place because of the other component types...

var frog = Crafty.e("2D, DOM, Player, Octocat, Physics, Collision")
    .onHit("Cake", onHitCake);

The .onHit(component, function) method tells Crafty to call the specified function when the entity collides with an other entity of type component. So whenever the frog hits a cake, onHitCake gets called.

And that was it. I think I was able to get the cake added to the game in about 30 minutes - including the time it took for me to read the Crafty API to figure some of this stuff out. I think that's pretty good, since my day job, comics, and responsibilities as a parent don't leave me with a whole lot of time to do this game jam thing...

And speaking of comics and games, today's pokes a bit of fun at a famous game from 2014...

Amphibian.com comic for 25 March 2015

Monday, March 23, 2015

First Modifications for GGO15

After finally selecting a game to fork last week, I was able to start work on my GitHub Game Off 2015 entry this weekend.

The game I chose to modify was Octocat Jump from the 2012 Game Off, which used the Crafty game framework. Typically I stay away from frameworks that try to do "too much" for me...I tend to find myself fighting against them to do things the way I want and there's also typically a performance penalty that must be paid. However, I have so far been very impressed by Crafty and would definitely use it in a future JavaScript game project.

You can play my version at http://caseyleonard.com/ggo15.

So far, the changes I've made to the game are relatively minor.

1. Updated the dependencies.


Since the game I forked has been pretty much untouched since late 2012, the versions of jQuery and Crafty used in it were a bit out-of-date. The first thing I did was update them to the current releases. The upgrade to jQuery had no impact, but a few things had changed with Crafty over the years which broke the game.

Somewhere between the version used in Octocat Jump and the version released last November, the method of specifying animations changed significantly. You used to be able to specify an animated sprite like this

Crafty.e("2D, DOM, Portal, SpriteAnimation")
    .animate("portal", 0, 0, 10)
    .animate("portal", 5, 0);

But now you have to create a reel first before starting animation. Here is the updated code.

Crafty.e("2D, DOM, Portal, SpriteAnimation")
    .reel("portal", 500, 0, 0, 10)
    .animate("portal", 1)

I should explain a little about what's going on here. When using Crafty, everything in your game is called an Entity. The hero, enemies, power-ups, obstacles, everything. All Entities. To create an Entity, you just call Crafty.e("components_string"). The components string specifies what type of Entity you want to create. It's just a comma-delimited list of components. Your Entity will have the properties of everything in the list - it's basically a multiple inheritance pattern. In the example above, my Entity gets all the properties of a 2D, DOM, Portal, and SpriteAnimation component. Some of those are built-in components, but you can also define your own types. You can even just use a "type" that has no special meaning in order to tag that entity for other things later, such as which types of Entities create collisions against each other.

The code I modified, shown above, created an animated sprite Entity. The Entity inherits the reel and animate functions from the SpriteAnimation component. You can create multiple reels for each Entity if you want, and then select which one to play at different times by calling animate with two arguments: the name of the real and the number of times to loop through it. The example above starts an animation reel called "portal" that plays once immediately after creating the Entity and defining the reel.

2. Changed the Characters and Fonts


In my game I want to use one of my frogs from Amphibian.com instead of the Octocat. I mean, I like Octocat and all, but I have my own characters. I'm going to use Business Frog and modify the game so that he's jumping around navigating the twisted world of project management. I also changed the fonts used in the game to the same one I use on my comic (Sniglet, if you're curious).

First draft of the Business Frog sprite sheet (needs work)

3. Fixed Some Bugs


There are a few bugs in the original game that I fixed, which turned out to be a good exercise in learning how things work in a Crafty game.

The first was that near the beginning of the game, there seemed to be a platform missing. I'm not sure if it was that way by design or not, but it really bothered me. I tracked it down to where the level data is turned into platform entities. At the start of the game, there should be 10 platforms before the new platforms start coming down from above. There was an array.slice() call being made that only selected 9 elements instead of 10.

The second thing might not be considered a bug, but was certainly an important missing feature. In the original, there was no way to restart the game after you fall. You had to refresh the whole page in your browser. I added a keyboard event listener on the game-over scene that sends you back to the main scene - but had to reset the value of an internal variable n back to the start value of 10 in order for the game to work properly after a restart. I added that line to the initState() function, where it probably should have been all along.

The last thing weird thing I fixed was the pause behavior, but I think this one was my fault. The game was designed to show a dark overlay with the word "Paused" in the middle of the screen when you pause it. I believe the Crafty API must have changed somewhere between 2012 and today because it had incorrect behavior on my version but seemed to work on the original.

Crafty.bind("Pause", function onPause() {
    Crafty("BackgroundOverlay").color("#000000");
    Crafty("BackgroundOverlay").alpha = 0.5;
    Crafty("PauseText").destroy();
    Crafty.e("2D, DOM, Text, PauseText").css({
        "text-align": "center",
        "color": "#fff",
        "textShadow": "0px 2px 8px rgba(0,0,0,.9), -1px -1px 0 #000,1px -1px 0 #000,-1px 1px 0 #000,1px 1px 0 #000"
    }).attr({
        x: 0,
        y: Crafty.viewport.height / 2 - Crafty.viewport.y - 64,
        w: Crafty.viewport.width,
        z: 9999
    }).textFont({
        "family": "Sniglet",
        "size": "96px"
    }).text("Paused");
    Crafty.trigger("RenderScene");
});

In the original code, the Crafty.trigger("RenderScene") on line 18 was Crafty.DrawManager.draw(). That function is no longer defined on DrawManager, which resulted in the function throwing an uncaught exception and essentially un-pausing the game. Why is either line needed? Because when Crafty pauses, scene rendering doesn't take place - and that overlay and text will never show up. Manually telling it to draw once takes care of the issue. The accepted way to do that in the current API is to trigger the "RenderScene" event.

More To Do


I've really only scratched the surface of the changes I want to make to the game. I mentioned it briefly above, but I want to make it seem like Business Frog is jumping through a poorly managed software project (like he does in the comic). The platforms of different lengths stacked vertically remind me of a Gantt chart, so I want to make some of the platforms "critical path" elements which give you a bonus for hitting sequentially. I also want to add a power-up that temporarily makes the platforms wider. There should also be hoops to jump through. Like actual hoops. Finally, I want to have some kind of projectiles being thrown sideways after reaching a certain height.

I'll probably think of other things as I keep working on it. And just like in 2013, even if I don't win I'll have another game to add to Amphibian.com.

Amphibian.com comic for 23 March 2015

Friday, March 20, 2015

Stick a Fork In It

Typically, sticking a fork in something means that it's finished. In my case, however, it means that I've only just begun.

I'm trying to participate in the GitHub Game-Off 2015. I created a tadpole game on the theme of "change" for the Game-Off in 2013. There was no Game-Off in 2014. This year the theme is "The Game Has Changed." The meaning behind that catchy phrase is that to participate, you fork another game repository on GitHub and modify it.

For some reason, it seems infinitely more difficult than making a game from scratch. Just picking a game to fork was overwhelming. There are just so many. All Game-Off games have to be playable in a browser, so I try to stick with ones that are made with some JavaScript/HTML5 technology because I only have a limited amount of time and don't believe I have long enough to learn anything completely new (a fair number of past entries have been created with Unity, for example).

js-warrior, one of several HTML5 Dragon Warrior clones
I thought about forking one of several Dragon Warrior clones that are hanging around.

The draw for me was that I always loved that game and its sequels on NES back in the old days. But how could I modify it? Change the game assets to be frogs or something I suppose. When I was a kid I dreamed of being able to create my own towns and castles and dungeons for the game. I thought about adding simultaneous multi-player using Websockets, with which I have a bit of experience. But in the end I decided that most of them are so unfinished that the biggest thing I could do to them would be to add in all the missing parts of the original game. And while that would be somewhat satisfying, I could just play the originals on my Raspberry Pi Emulation Station any time I want. I can't play on the web, though... Oh well, maybe I can come back to this later.

My daughter wanted me to do a Flappy Bird clone. There is a pretty good one, Clumsy Bird, which uses MelonJS. But it just didn't feel right. I don't know, maybe I'm just over the whole Flappy Bird thing. It was fun a year ago, but now? The suggestion did inspire me to write a comic though (it runs next week). Anyway, I've also thought about doing a side-scrolling infinite runner for a while now so I searched for a good candidate to fork. Unfortunately, I didn't find any I thought would work for me. That will have to remain on my to-do list as well, but I'll probably write one from scratch if I ever get a few weeks free.

But I finally found a good candidate for forking. Octocat Jump from the 2012 Game-Off is about as close to perfect as I can find. I like the jumpiness of it (I can use a frog instead of the Octocat), it's JavaScript, it already has a to-do list of things I should be able to add, and it uses a game framework called Crafty that looks like it should be easy enough to learn in a short time. I'm already about a week behind, so I hope it goes well.

All my hard thinking about forks over the past week also gave me the idea for today's comic.

Amphibian.com comic for 20 March 2015

Wednesday, March 18, 2015

100th Comic

Today I've published 100 comics since starting my Amphibian.com webcomics on August 1, 2014. I feel like that's a major accomplishment. At least it's a large number. Not large like the national debt of the United States or Apple's market capitalization or anything, but pretty big.

A long time ago in a galaxy far, far away (okay maybe like 22 years ago in Port Royal, Pennsylvania) I did a comic about a frog that ran weekly in a local newspaper. At one comic per week, it took me nearly 2 years to reach 100. I guess it's really not that impressive, since Garfield reached 100 comics published in under 17 weeks.

But you know what I don't like about the number 100? It's not prime. 101 is though. If you ever want to calculate a list of prime numbers, you can use the Sieve of Eratosthenes. It is a very efficient algorithm for finding "smaller" primes (the primes that normal people would want, if normal people want primes at all). I implemented it once in Java.

public class SieveOfEratosthenes {

    /**
     * Uses the Sieve of Eratosthenes to calculate an array of prime
     * numbers up to a given maximum number.
     * 
     * @param max the highest number to consider for primeness
     * @return an array containing prime numbers
     */
    private static int[] getPrimes(int max) {

        if (max < 2) {
            return new int[0];
        }

        int size = ( max % 2 == 0 ? max/2 : (max/2)+1 );
        int[] nums = new int[size];
        nums[0] = 2; // 2 is the first prime and only even prime
        // we'll fill the rest of the array with the odds,
        // since we know that all the evens will just be removed anyway
        int n = 3; 
        for (int i = 1; i < nums.length; i++) {
            nums[i] = n;
            n = n + 2;
        }

        // we can stop when we get past the square root of max
        int sqRoot = (int) Math.sqrt(max);
        int idx = 0;
        int f = nums[idx];
        while (f <= sqRoot) {

            if (f != -1) {

                // "remove" all numbers that are multiples of f.
                // basically that just means set them to -1 and 
                // ignore them in the future.
                for (int j = idx+1; j < nums.length; j++) {
                    int num = nums[j];
                    if (num != -1) {
                        if (num % f == 0) {
                            nums[j] = -1;
                        }
                    }
                }

            }

            f = nums[idx++];

        }
  
        // clean up the list (remove the -1's)
        int marker = 0;
        int index = 0;
        int lastPrimeIndex = 0;
        while (index < nums.length) {
            if (nums[index] != -1) {
                lastPrimeIndex = marker;
                marker++;
            } else {
                for (int k = marker; k < nums.length; k++) {
                    if (nums[k] != -1) {
                        nums[index] = nums[k];
                        nums[k] = -1;
                        if (index > lastPrimeIndex) {
                            lastPrimeIndex = index;
                        }
                        marker = k+1;
                        break;
                    }
                }
            }
            index++;
        }

        int[] ret = new int[lastPrimeIndex+1];
        System.arraycopy(nums, 0, ret, 0, lastPrimeIndex+1);

        return ret;

    }

    public static void main(String[] args) {

        if (args.length < 1) {
            System.out.println("no arguments given");
            System.exit(1);
        } else {

            int largest = 0;
            try {
                largest = Integer.parseInt(args[0]);
            } catch (NumberFormatException nfe) {
                System.out.println(args[0] + " is not an integer");
                System.exit(1);
            }

            int[] primes = getPrimes(largest);

            // print out the list
            for (int i = 0; i < primes.length; i++) {
                if (i > 0) {
                    System.out.print(',');
                }
                System.out.print(primes[i]);
            }

        }

    }

}

Give that class a command-line argument of an integer and it will return you a list of prime numbers up to and including that number. I'll warn you though, very large numbers will take a while to calculate.

Today's comic includes multiple references to the number 100, which is a fine number to use as input to the sieve.

Amphibian.com comic for 18 March 2015

Monday, March 16, 2015

Frogs on Cakes

Yesterday was the 10th anniversary of the birth of my daughter Alexandria. Most people call that her birthday, but technically her birthday was just that one day back in 2005. What we celebrate each year is the anniversary of that day.

To celebrate each year, I've made a special cake for her.

2006 - Dora the Explorer

She really liked Dora, and at only 1 year old she couldn't really give me any feedback on the cake. Still, since I'd never decorated a cake before I practiced that star-tip frosting thing for days. This was actually the second Dora cake - I made and decorated a test cake the day before.


2007 - Butterfly

We moved into our new house just a few days before I made this cake for her second birthday. Kind of generic maybe.


2008 - Cinderella

By age 3 she was old enough to pick what she wanted for a cake. At the time, Cinderella was her favorite princess. She must have watched that movie 12,000 times this year.


2009 - Ms. Pac-Man

Finally, teaching her to play classic video games paid off and she asked for "Lady Pac-Man" to be her cake this year. So of course I made 2 cakes, one of Ms. Pac and one ghost...along with a bunch of cupcake dots to eat.



2010 - The Search Icon

I have no idea what she was thinking this year, but she insisted on a cake that looks like the search icon. I told her it was a magnifying glass. She said that's what she wanted. Okay.


2011 - Rapunzel's Tower

She watched Tangled in late 2010 and Rapunzel became her new favorite princess. This edible replica of her tower from the movie was a two-layer cake sitting on top of a column of iced crispy-rice treats. I even cooked some spaghetti to drape out of the window for Rapunzel's hair.


2012 - Perry the Platypus

Like all other children in America, Alex became a fan of Phineas and Ferb. I think her favorite character might have actually been Dr. Doofenshmirtz but Perry is easier to represent as a cake. His tail was a waffle.


2013 - Minecraft

She played a lot of Minecraft this year, but I guess technically this wasn't a cake. It was a giant cookie with iced cripsy-rice treats on top. It was my attempt at a Creeper. Still tasted good.


2014 - Volcano

I'm not sure where this idea came from. The cake was a volcano. All her Lego people were running away from it as it erupted. We actually put a cup of dry ice in the middle and poured water on it to make the "smoke" come out. The children at her party were amused for a few minutes.


2015 - Frog Comics

These frogs have been a big part of her life for the past year, as she's had to watch me spend hours and hours making the website and the comics that go on it. She's really picking up on my strange sense of humor. I wrote a special comic to commemorate her birth and had it printed the way they print photos on cakes. Three cakes, three frames of the comic. I had the comic up on Amphbian.com yesterday as well, but you can't eat a web page.


So there are Alex's ten birthday cakes. And you thought I was just good for making software and frog comics. Well, if you've been reading the comics and this blog you might not even think I'm good for that. But this proves that I can make cakes if nothing else. I have some other daughters as well, and I even make cakes for them. But that's too make cakes to put in one blog post. One daughter at a time.

Now, back to those frog comics...

Amphibian.com comic for 16 March 2015

Friday, March 13, 2015

Put Yourself on the Map

In today's comic the frogs are tracking their Hype Cycles on a big map display. In reality, the Hype Cycle is just the way new technology works its way into the mainstream of society. First, a new technology is envisioned in a lab, people talk about it and build prototypes, it gets picked up by the media, the hype starts to build. This leads up to the "Peak of Inflated Expectations." Everyone suddenly thinks this new thing, whatever it is, will change the whole world and be the greatest invention in the history of mankind. Of course, the first commercial products don't live up to the hype and we enter the "Trough of Disillusionment." Big downer. But as long as the technology isn't abandoned here, further refinements climb the "Slope of Enlightenment" until reaching the "Plateau of Productivity" where the technology is actually practical and useful.

The Hype Cycle (illustration by Jeremy Kemp)

But back to the big tracking display. I almost just drew a picture of one, but then I thought, why not just put a Google Maps element right in the comic? That is one of the benefits of using JavaScript and CSS to make comics instead of just images. The map in the 3rd frame of the comic can be panned and zoomed just like any other Google Maps you see on other web sites.

I'm using the Google Maps JavaScript API v3, and it is fairly easy. You should be able to add a simple map to a web page in just a few minutes.

Here is how I made my map for the comic. First, here is some simple HTML for a web page that will contain a map.

<!doctype html>

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

<body>

  <p>Map of State College, Pennsylvania</p>

  <div style="width: 400px; height: 300px;" id='map'></div>

</body>

<script type="text/javascript"
  src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY_HERE">
</script>

</html>

Make you you replace the "YOUR_API_KEY" in the JavaScript source location with your own Google API key. If you don't have one, you can get on the Google Developers Console. Just make sure you enable the "Google Maps JavaScript API v3" API for your key.

If you load that page into your browser, it won't do much. You need to create an initialize function to set up your map. Here is a slightly simplified version of the one I used in my comic.

function initialize() {

    var mapOptions = {
        zoom: 14,
        center: new google.maps.LatLng(40.791686, -77.856176),
        disableDefaultUI: true
    };

    var map = new google.maps.Map(document.getElementById('map'), mapOptions);

    var hc1 = new google.maps.LatLng(40.790232, -77.855726);
    var hc2 = new google.maps.LatLng(40.789087, -77.858451);
    var hc3 = new google.maps.LatLng(40.789436, -77.856348);

    var marker1 = new google.maps.Marker({
        position: hc1,
        map: map,
        title:"Hype Cycle 1"
    });

    var marker2 = new google.maps.Marker({
        position: hc2,
        map: map,
        title:"Hype Cycle 2"
    });

    var marker3 = new google.maps.Marker({
        position: hc3,
        map: map,
        title:"Hype Cycle 3"
    });

}

First, I create an object for passing options into the map constructor (line 3). I set the zoom level to 14, which gives me a starting zoom level pretty close to the street. Setting the center of the map is also done here. Coordinates can be specified by creating a new google.maps.LatLng object and passing the latitude and longitude to the constructor. I use coordinates of 40.791686, -77.856176 because that specifies downtown State College. I also set disableDefaultUI to true to get rid of all the zoom, street view, directions, and satellite view controls. I just want a plain map.

To create the map object which will take the place of the empty "map" div, I create a new map object passing in the DOM node of the div and the map options (line 9).

I put three markers on my map, in different locations around downtown. I set up the coordinates by creating more google.maps.LatLng objects (lines 11 through 13), and then make google.maps.Marker objects starting on line 15. Each Marker is passed an object which contains its configuration. The position field is the LatLng object for the marker location, map is the map on which the marker should be placed, and title is the text you see when you hover the mouse over it.

Only one thing remains - calling the initialize function. You can't just execute it from anywhere, you have to make sure that the map itself calls it once it has fully set itself up on the page. Just add this one line of JavaScript anywhere after the function definition.

google.maps.event.addDomListener(window, 'load', initialize);

Now as soon as the Google Maps JavaScript file is fully downloaded, your initialize method will be called. Put it all together, and you should end up with a web page that looks like this, similar to what the frogs saw on their giant tracking display.



The full Maps API is fairly impressive. There's a lot more you can do with it, which I might use in later comics. Check it out for yourself and build something awesome!

Amphibian.com comic for 13 March 2015

Wednesday, March 11, 2015

Going to the Server?

In previous posts, I've talked quite a bit about how I use Websockets for sending data from the server to the browser. For asynchronous server-to-client "push" scenarios, it can't be beat. But what about client-to-server? Using classic AJAX to post data to the server is still prevalent, but you may not be surprised to learn that Websockets are more efficient for that use-case as well.

HTTP is expensive, even when it's going on asynchronously in the background of your pages. I wanted to see just how much more it costs in terms of time to send data to the server using a classic HTTP POST versus sending data over an open Websocket. I set up the following test.

First, I set up a Node application using Express and Socket.io.

var express = require("express");
var http = require("http");

var app = express();
var server = http.Server(app);
var io = require("socket.io")(server);

//------------ Socket.io stuff

var wFirstSeen = null;
var events = 0;

io.on("connection", function(socket) {
  
    socket.on("data", function(data) {

        if (!wFirstSeen) {
            wFirstSeen = new Date();
        }
        events++;

        if (events === 200) {
            console.log('websockets done in ' + ((new Date() - wFirstSeen)));
            events = 0;
            wFirstSeen = null;
        }

    });

});

//------------ web application route

var hFirstSeen = null;
var posts = 0;

app.post("/data", function(req, res, next) {

    if (!hFirstSeen) {
        hFirstSeen = new Date();
    }
    posts++;

    if (posts === 200) {
        console.log('http post done in ' + ((new Date() - hFirstSeen)));
        posts = 0;
        hFirstSeen = null;
    }

    res.sendStatus(200);

});

app.use(express.static('public'));

// ------------ start the listening

var srv = server.listen(3000, function() {
    console.log("listening on port %d", srv.address().port);
});

Then I made a test web page so my client could send data to the server.

<!doctype html>

<html lang="en">
<head>
  <meta charset="utf-8">
  <title>WS vs HTTP</title>
</head>

<body>

  <p>Pushes data to the server.</p>
  
  <div id="wsStatus"></div>

  <div id="httpStatus"></div>

</body>

<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script type="text/javascript" src="/test.js"></script>

</html>

Finally, here are the contents of my test.js file.

var sckt;
var data = {
    field1: "something",
    field2: 12,
    field3: false,
    field4: "whatnot"
}

function websocketTest() {

    $("#wsStatus").append("starting send");
    for (var x = 0; x < 200; x++) {
        sendWebsocketData();
    }
    $("#wsStatus").append("sends complete");

}

function ajaxTest() {

    $("#httpStatus").append("starting send");
    for (var x = 0; x < 200; x++) {
        sendAjaxData();
    }
    $("#httpStatus").append("sends complete");

}

function sendWebsocketData() {
    sckt.emit("data", data);
}

function sendAjaxData() {
    $.post("/data", data);
}

$(function() {

    sckt = io.connect();
    sckt.on("connect", function() {
        $("#wsStatus").append("socket connected");
    });

});

So my test was pretty simple. I send the same data object from the client to the server 200 times and print out how long it takes for the server to process. I have test methods set up for Websockets and HTTP post. After I bring up my test page in my browser and see that my websocket connects, I can execute the websocketTest function and the ajaxTest function. The server will print out the results, which are in milliseconds.

The results in my Eclipse console

The send via Websocket was quite a bit faster every time, which is what I had expected. Posts consistently took well over 200 ms, whereas the data could be transmitted by websocket in the 45 ms range. Definitely something to think about when designing a web application that will be sending a lot of data from the client to the server. Websockets are currently supported across most browsers, so using them in place of HTTP posts may be a viable option.

That's enough seriousness for today. In today's frog comic, I examine the push for self-driving automobiles.

Amphibian.com comic for 11 March 2015

Monday, March 9, 2015

Plants Don't Do Math

There's no evidence that plants have any kind of higher-order cognitive abilities. They can't really perform calculations. So why do so many of them exhibit Fibonacci's sequence in their leaf arrangements, florets, etc.? Old Fib's sequence also provides us with a good way to estimate the Golden Ratio, which is an irrational number. And the Golden Spiral that is made using the Golden Ratio also appears in sunflower seed arrangements, as well as the shells of marine animals.

What's going on?

It turns out that these arrangements in nature seem to be the best ways to maximize space. The Golden Spiral is the best way to pack the most seeds into the head of the sunflower, for example.

Golden Spirals in a sunflower
To estimate the Golden Ratio using the Fibonacci Sequence, just take any two of the adjacent numbers and divide the larger by the smaller. It works better with the larger numbers. Take 6765 divided by 4181 (the 21st and 20th numbers), for example. That equals 1.618034, which is a pretty close estimate. Humans love the Golden Ratio - it seems to touch on something deep within our brains. It shows up all the time in architecture and art - sometimes not intentionally.

Fish scales, however, seem to be arranged randomly. So fish aren't that cool. I thought that I read years ago how fish scales are arranged in a way related to Fibonacci's Sequence, which is why this subject is tied to today's comic (which includes the trout again). However, a search on the subject turned up no evidence and I have to conclude that either my memory is faulty or my information was bad. Probably my memory.

But since we're here, if you'd like to calculate the first n Fibonacci numbers or the nth number in the sequence, you can use a recursive function. I wrote this one a while back in Java. It takes a number n as a command-line argument and prints out, one per line, the first n numbers in the sequence.

public class Fibonacci {

    /**
     * Calculate the (n+1)th number in the Fibonacci Sequence.
     * For example, 0 will give you the first number (0), 1 the
     * second number (1), 2 the third number (1), and so on.
     * 
     * @param n the sequence number
     * @return the value of that position in the sequence
     */
    private static int fib(int n) {

        if (n == 0) {
            return 0;
        } else if (n == 1) {
            return 1;
        } else {
            return fib(n-1) + fib(n-2);
        }

    }

    public static void main(String[] args) {

        if (args.length < 1) {
            System.out.println("no arguments given");
            System.exit(1);
        } else {

            int f = 0;
            try {
                f = Integer.parseInt(args[0]);
            } catch (NumberFormatException nfe) {
                System.out.println(args[0] + " is not an integer");
                System.exit(1);
            }

            for(int i = 0; i < f; i++) {
                System.out.println(fib(i));
            }

        }
    }
}

The function is really simple, since the method of calculation is so simple. The first number in the sequence is 0 and the second number is 1. So there are two cases to end the recursion. For all others, the function just calls itself for the previous 2 numbers and adds them together. I love recursion. And frogs.

Amphibian.com comic for 9 March 2015

Friday, March 6, 2015

What's on the Menu Today?

With such widespread use of touch-screen devices today, I have to wonder if the mouse will be a forgotten input device in 20 years. Some people probably wish it was already forgotten. It tends to be less efficient than using keyboard shortcuts (if you can remember them all). But I don't find it all that terrible and still make use of right-click context menus in my user interfaces.

I've used both Dojo and ExtJS context menus in the past, but for my comic editor I use the jQuery contextMenu plugin. I've found it to be very responsive and relatively lightweight at 65k, but it feels a little awkward to use at times. One of its best features is that the menu object is created only once and can be bound to any number of objects. This makes very efficient use of the DOM, but the menus are also immutable. I thought that a bit odd at first but was easy enough to work around.

The basic use is simple. Here is an example web page.

<!doctype html>

<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Menus</title>
  <link href="/css/jquery.contextMenu.css" rel="stylesheet">
  <link href="/css/jquery-ui-1.10.4.min.css" rel="stylesheet">
</head>

<body>

  <p>This text should not have a menu.</p>

  <p class="demo">This text should have a menu.</p>

  <p>This text should not have a menu.</p>

  <p>This text says nothing.</p>

</body>

<script src="/js/jquery-1.11.2.min.js"></script>
<script src="/js/jquery.ui.position.js"></script>
<script src="/js/jquery.contextMenu.js"></script>
<script>

</html>

Note that in addition to the JavaScript for contextMenu, there is a CSS file for it you should include as well. Also, jQuery UI Position is recommended.

To create a right-click menu that will bind to every element with the "demo" class, you can do this...

$.contextMenu({

    zIndex: 100,
    selector: ".demo",
    items: {
        item1: {
            name: "Item 1",
            type: "text",
            value: "nothing"
        },
        item2: {
            name: "Second Item",
            type: "text",
            value: ""
        },
        sep1: "----------",
        item3: {
            name: "Another Item",
            type: "text",
            value: "also nothing"
        },
        sep2: "----------",
        someAction: {
            name: "Take Some Action",
            callback: function(key, options) {
                console.log("take action");
            }
        },
    },
    events: {
        show: function(opt) {
            var mData = $.contextMenu.getInputValues(opt, this.data());
            mData.item2 = "222222";
            $.contextMenu.setInputValues(opt, mData);
            console.log("menu shown");
        },
        hide: function(opt) {
            var mData = $.contextMenu.getInputValues(opt, this.data());
            console.log("item 1 when hidden: " + mData.item1);
        }
    }

});

Calling $.contextMenu creates a menu that will be activated whenever you right-click on an element that matches the selector value. In this case, it will be all elements with the demo class. The menu items are called out as fields in the items object. Note that you can use multiple separators, but they each have to have unique names. Each item can specify a name and optionally a type. The value of type will determine how that item is presented in the menu. In my example, "text" as a type results in a text box. If you just want action items to click on in your menu (things like "cut" and "paste" for example), leave off the type attribute and use callback instead. Specifying a function here enables your code to be called whenever that menu item is clicked on. Clicking on an item as causes the menu to be immediately hidden as well.

The events object gives you the ability to set listeners on the menu's show and hide events. In these functions, you can read the write the values for menu items that happen to be form controls such as input boxes. In my example's show function, I call $.contextMenu.getInputValues(opt, this.data()) to get an object that represents the data values of all the input fields in the menu. I know, that's not exactly the most obvious way to get the data, but it is what it is. Once you have the object, you can inspect and/or change the values. In the show function, it might make sense for you to set a value before the menu is displayed to the user. I do that by setting item2's value to "222222". In the data object, you reference the values by the names you gave the menu items (item1, item2, etc.). I leave the other values alone. When the menu is displayed, the value for "Second Item" should be all those 2's even though the value is blank in the menu definition. In the hide listener, it often makes sense to do something with the values that were entered by the user. Getting the data object is the same here. In my example, I just log the value of item1. If you change the text on the menu before hiding it, you should see your text print out to the console.

The results look like this.


I mentioned near the top about how the menus can't be changed after they are created. So what do you do if you need to make serious changes to the menu structure at runtime? The easiest thing to do is to destroy the menu and create a new one. This is what I do when images are added to my image selector menu and I need to recreate it. There doesn't appear to be any drawback to this method, as long as it is easy for you to run your menu-creation function again.

To blow away a specific menu, call "destroy" and specify the selector:

$.contextMenu( "destroy", "demo" );

To destroy all context menus, you can make the same call without specifying a selector.

$.contextMenu( "destroy" );

There's lots more you can do with these context menus, so I encourage you to experiment with it. While you can't see them while viewing the comics on Amphibian.com, you can trust me when I tell you they are there for me when I create them.

None of this really answers the question of what to do with right-click menus in situations where there is no mouse, but honestly I'm still thinking about the best way to handle that. Right now, I just don't edit the comics on a phone or tablet. Primitive, I know.

Amphibian.com comic for 6 March 2015

Wednesday, March 4, 2015

Just Show Up

What is the one thing that I want everyone to say about me?
  • He sure loves frogs? Maybe true, but not very deep.
  • Biggest jerk I ever met? Definitely true, but not very flattering.
  • He eats a great quantity of cheese? Come on, who doesn't?
  • Can't take him anywhere? I don't want to go most places anyway.
  • He introduces more bugs than he fixes? I introduce bugs to each other. I'm like a bug matchmaker.
  • He shows up. YES!
I show up. That's what I want to be remembered for. Maybe that's the only reason anyone will remember me. I guess my odds of being remembered for anything are greater because I showed up. Just showing up is the key to my success, and it can be the key to yours as well.

Woody Allen once said that 80 percent of success is showing up. I would say it's more like 90 or 95. I have no other explanation for where I got in life except that I showed up.

Showing up is undervalued in our society. Be honest, how many classes did you cut in college? I never missed a single class until my senior year. Then I got the flu, had a fever of 103, and my girlfriend wouldn't let me go. But I tried. Showing up to all those classes got me good grades and allowed me to graduate summa cum laude in 2001. I really think the only thing that separated me from the rest of the students was that I showed up.

I'm not especially intelligent, but I might appear to be. It's just because I show up. Showing up provides opportunities that won't be available to those who don't show up. You won't be selected for anything if you're not there, even if you are the most qualified.

So don't cut class, don't call in sick to work just because you don't feel like going, don't disregard appointments, and don't keep quiet when someone asks for a volunteer.

Show up. And success will show up to meet you.

Amphibian.com comic for 4 March 2015

Monday, March 2, 2015

Do We Still Need HTML?

The joke on Friday was that the frogs switched their website to NoHTML after switching their databases to NoSQL, which resulted in the last frame being completely blank. But does NoHTML mean no HTML? And does no HTML mean no content? Is NoHTML even a thing?

I'll try to answer those questions. First of all, what would NoHTML mean? It's clearly a play on NoSQL, which is a term for a class of databases that store things differently than the classic relational models. NoSQL is typically associated with Big Data and "web scale" and things like that. If NoSQL is the data storage for the Internet of a trillion people, then NoHTML should be the data visualization.

There is a real project called noHtml. And it is exactly what you might think it is - a way to build the DOM for a web page without any HTML. The page contents are created entirely by JavaScript. But this is just the most extreme example of what many of us have been doing for several years: dynamically adding and modifying the web page programmatically.

I write very little HTML these days. All of the HTML for Amphibian.com is generated either by JavaScript code that I write or by the Jade template engine. Individual comics are stored as JSON data and either applied to a template to create HTML (for the general viewer) or have DOM elements created directly by JavaScript (for my editor).

The popular "single page" web applications are pretty much doing this as well. Data comes from the server and content for display is generated by JavaScript, not by HTML. We may have already entered the post-HTML era. Web 3.0? Maybe just 2.5.

How am I doing on answering those questions?
  1. Does NoHTML mean no HTML? Not necessarily. You can completely avoid creating HTML yourself and yet still have a template engine produce it for you before giving the content to the browser. HTML still exists.
  2. Does no HTML mean no content? Certainly not. As exhibited by the noHtml project and my own comic editor, the DOM can be created without any markup language.
  3. Is NoHTML even a thing? It would appear that it is.
Welcome to the future.

Amphibian.com comic for 2 March 2015