Showing posts with label ggo15. Show all posts
Showing posts with label ggo15. Show all posts

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

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

Wednesday, April 1, 2015

April Fools!

Today is the first day of April, but I have no tricks or hoaxes here in my blog. I do have one on my webcomic, however.

I have too many things going on right now, which troubles me a bit. I'm having difficulty making sure the comics get done along with my GitHub Game Off 2015 entry while at the same time making sure I keep my day job and not neglect my family.

Here are my latest updates.

Amphibian.com April Fools' Day


I had to do something foolish for the 1 April comic. It's a technology company tradition to release phony products, absurd announcements, and generally silly ideas. The frogs had to join in. So I replaced the comics with text today - to finally make the site compatible with Internet Explorer 5. But of course, that's not really possible. I used the jQuery plugin Typed.js to create the manually-typing-the-comic-transcript-in-a-terminal effect that graces the site today.

In general, I liked Typed.js better than the alternatives but it was not without flaws. I was a little disappointed that I couldn't get the cursor to work the way I wanted, and you can see parts of the HTML tags appear briefly as it types. Still, I like how it turned out.

1980's terminal? Or today's Amphibian.com?

Game Off 2015 Jumping


Over the last few days, I also found a couple of minutes to add a critical path bonus to the frog jumping game. Since the game is supposed to represent Business Frog jumping through a Gantt chart, I decided that the red platforms should represent the critical path. Hitting several of them in a row results in an additional bonus multiplier at the end of the game. Jump on every red platform in the order in which they appear and you can get really crazy multipliers which lead to really crazy scores.

Critical Path!
My wife, who has never been subjected to a Gantt chart, constantly reminds me that she wants the high scores to work at the end of the game. I'm going to try to get to that this weekend, but it means adding a server-side component. I'll probably try to make something really lightweight using Node. She also suggests I replace the hamburgers with coffee. I'll probably do that too. I still have to fix the frog jumping sprites too, but the game is coming along well. The competition ends on April 13th.

Unfortunately that's all I have to talk about today. And there's no picture of a comic at the bottom here, because the comic has to picture today. But I'm sure there are plenty of other fun things to find on the Internet.

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

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