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.

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