Custom Canvas Drawing in CraftyJS

A lot of people have asked about this and I thought it’s about time I write up a quick example for custom drawing on the canvas in a way that doesn’t break the redraw regions.

The first thing to ensure is that the entity’s width and height is large enough to encapsulate the entire drawing so the redraw region manager knows how much to clear.

The second thing to do is overwrite the draw method. In there we can do our custom 2D canvas drawing.

My example is a Circle drawer. It requires a radius and color:

As you can see I set the width and height to the size of the circle (radius * 2).

I also create a draw method which draws a circle at the entity’s x and y position with an offset of the the radius.

It’s as simple as that. We can have some fun with the custom renderer by adding the Tween component and decreasing the radius over 500 frames.

External Documentation Proposal for Exposed APIs

I have been playing around with various methods of documentation and for a while I thought the way to go was inline documentation where the documentation exists within the source code, but I’ve noticed a few flaws in this approach.

Who is the target reader?

Inline documentation doesn’t make sense if the end user has no knowledge or interest in the source. It should exist to teach the reader how and why the code works from the perspective of someone interested in the internals. For a developer who just wants to make use of the API, why include it with the source?

Forcing Object-Oriented-ness

JSDoc in particular generates documentation similar to JavaDoc; a strictly Object Oriented language. This doesn’t cross over well when you have things such as chaining, currying or other JavaScript oddities.

The solution

Damon Oehlman wrote about using a Domain Specific Language (DSL) in an external document for API documentation. In his example developers would use some specific representations of how to use the API using text.

I imagine a structure where the documentation mimics the source code file structure, but for every code file a documentation file exists in its place. These files will be a superset of Markdown with extra formatting to denote namespaces, signature overloading, types and internal links. A generator would then convert the structure into HTML pages.

I’ll start with an example:

#Core.Crafty()
>Crafty(selectors:string) => <Core.Entity>
>Crafty(entityID:number)  => <Entity>
Select a set of or single entities by components or an entity's ID.

Crafty uses syntax similar to jQuery by having a selector engine to 
select entities by their components. Selecting by multiple components
is done by seperating with a comma or a space. A comma is similar
to OR where the entities can match one or more of the components. 
A space is similar to AND where entities have to match all the 
components.

##Example
    Crafty("MyComponent")
    Crafty("Hello 2D Component")
    Crafty("Hello, 2D, Component")

The first selector will return all entities that has the component 
MyComponent. The second will return all entities that has Hello 
and 2D and Component whereas the last will return all entities that
has at least one of those components (or).

**See also: <Crafty.map.search>**

In Markdown, a line starting with a single # means Heading 1. This will also denote a unit of code to document; such as a function, namespace or variable. It will also be used as the path for any other references in the documentation.

Grouping can be done by creating a path with a dot . as the separator. This could be used for categorising units of code or specifying a namespace path or even both at the same time!

As per Damon’s example, the greater than symbol > denotes a method signature where you specify the arguments as name:type (name is optional). The return type is specified after =>.

In my example the return type is wrapped in <angled brackets>. This represents an internal link to another unit. You may either specify the full path (as specified after the #) or use a subset of the path (assuming no collision) and the generator will pick it up.

Special files could be used for an Introduction, License information and even tutorials.

#Tutorial.RPG Demo
My tutorial formatted in Markdown!

The output of this format would be a hierarchy of units where each unit has its own HTML page. Templates for headers and footers would allow stronger customisation.

I would be interested in hearing some ideas on the subject. I think external documentation can create a greater separation between how to use the code and how the code works. It avoids huge source code files and can let the developers document in the format that suits the project.

HashBBG.com Sneak Peek

I had a go playing around with Drupal for the new and improved #BBG community site. It was surprisingly easy to get started and build a dynamic site. The content type feature was very helpful for customizing the data that BBG members will be posting.

The current content types are:

  • Projects: This is if members have created a project and want to share it. You can specify the repo and homepage.

  • Links: Sharing relevant links for HTML5 game development.

  • Text Posts: Purely text for those who don’t want a full blog but feel like writing about what they are working on.

  • Screenshots: An image and short description of the latest preview for any work in progress projects.

  • Poll: A standard poll to get a general opinion from the community.

All these posts will be aggregated under the members page as well as categorised for newcomers. This entire site was very quick to put together thanks to some great Drupal modules, not to mention a handy skill to learn for any future dynamic sites.

I have included a screenshot and will upload the site in the next couple of days or so.

A new direction for #BBG

If you haven’t heard of #BBG, check it out now! It’s an IRC channel on freenode.net dedicated to browser based games (regardless of your chosen tech) and boasts a variety of industry professionals from authors to engine developers.

We have a site dedicated to the community at hashbbg.com but we think it’s time for a revamp.

Categories

First of all we want to add categories on the home page so newcomers can see the latest and greatest games, tutorials, podcasts, blogs etc from the community and find out the developers responsible. The best part is they can then chat to the developers on #BBG!

Profile Page

Members should be able to post links to anything new they are working on or have recently created. This would be posted on their profile page as well as in a feed on the home page (and a tweet from @HashBBG).

Events

We will need to add sections for the various events such as the BBGMeetup and BBGChallenge. The BBGMeetup will be more frequent once we secure some members who want to participate regularly.

Ask an HTML5 Dev

Myself and Andrew J Baker started a series on HTML5Grind where the community would decide on a question to ask professional HTML5 developers and we would compile a list of responses from members. We intend to bring that back.

Essentially we want a place where BBG members can post the amazing stuff they’re working on and where newcomers can discover the great developers behind the work. The site will be a community effort so any help is appreciated.

Recent Posts widget in Tumblr

Pure JavaScript and less than 600 bytes. This will create an unordered list of recent posts from the blog of your choosing in a div that will replace the script tag.

Unminified (864 bytes):

<script type="text/javascript">
(function(blog, limit) {
limit = +limit || 10;

var scriptTags = document.getElementsByTagName('script');
var scriptNode = scriptTags[scriptTags.length - 1];
var recent = document.createElement("div");
scriptNode.parentNode.appendChild(recent);
recent.setAttribute("class", "widget");
recent.setAttribute("id", "TumblrRecentPosts");

var script = document.createElement("script");
script.src = "http://" + blog + "/api/read/json";
script.onload = function(data) {
    if(!tumblr_api_read) return;

    var response = tumblr_api_read.posts;
    var post;
    var len = Math.min(response.length, limit);
    var html = "<ul>";

    for(var i = 0; i < len; ++i) {
        post = response[i];
        html += "<li><a href='" + (post['url-with-slug'] || post.url) + "'>" + 
            post['regular-title'] + "</a></li>";
    }

    recent.innerHTML = html;
};

document.body.appendChild(script);

})("louisstow.tumblr.com", 30); //enter your settings here
</script>

Minified (573 bytes):

<script type="text/javascript">
(function(d,e){var  e=+e||10,
a=document.getElementsByTagName("script"),
a=a[a.length-1],b=document.createElement("div");
a.parentNode.appendChild(b);b.setAttribute("class","widget");
b.setAttribute("id","TumblrRecentPosts");a=document.createElement("script");
a.src="http://"+d+"/api/read/json";a.onload=function(){if(tumblr_api_read){
for(var a=tumblr_api_read.posts,c,d=Math.min(a.length,e),f="<ul>",g=0;
g<d;++g)c=a[g],f+="<li><a href='"+(c["url-with-slug"]||c.url)+"'>"+
c["regular-title"]+"</a></li>";b.innerHTML= f}};
document.body.appendChild(a)})
("louisstow.tumblr.com",30); //enter your settings here
</script>

Usage:

Place the script tag where you want the unordered list to be in your HTML document. Enter the blog URL in the arguments and specify a limit to the number of posts to list (default being 10). My blog is louisstow.tumblr.com or louisstowasser.com and I specified a limit of 30 posts.

How it works:

It uses the old Tumblr API (accessed via http://{Tumblr URL}/api/read/json) and runs it as a script. The script sets a global variable called tumblr_api_read. This is a large object which includes public blog information and posts.

Replacing the script tag is done by grabbing all script tags through document.getElementsByTagName("script") where the last script will be the one currently executing (the one we want to replace). We can then append our created div to the parent of the script tag.

Self promotion should be encouraged

The web seems to favour curation over creation. Self promotion is generally frowned upon and most will tell you sharing a mix of other’s links and your own is more acceptable; but why? This only encourages curation and stunts creation.

Content is king

Once upon a time this was the mantra of the web. Content above all else is most important. By this logic it doesn’t matter where the content came from, as long as it is good quality content.

Self promotion is not always spam

Some regard self promotion as a form of spam. Spam implies the content is unwanted which to me depends on the quality and frequency as opposed to whether the owner submited it for self gain.

Curation promotes reposts and stale content

We should be actively seeking new and quality content rather than sharing an already popular link otherwise known as reposts.

Good content goes to waste

It is very hard for content creators to get noticed. Think of how many blogs, tech articles, tutorials, videos, stories, games, music, tools, software, services or webcomics exist on the web. Some of them might be good, some might be great and not all of them will be discovered by curators.

Different monetization methods for HTML5 games and apps

Monetization is one of many challenges when creating a game or app in HTML5. After all the effort it would only be fair to recieve minor compensation to keep development alive. The problem is deciding how to earn money from your creation while not affecting it’s growth.

A standard method is to offer a freemium model (free with ads, pay for more content). Another is in-game purchases. I was thinking about various other ways it could be done where the player has more incentive to pay.

Raffle

Players would have to buy the game to enter (say for $1). The prize could be 10% of the proceeds or any other reward. Players can win by beating a level first or holding the highest score by a certain date.

It would encourage players to buy the game, play it and most of all share it with friends as it would increase the winnings.

In-game product placement

This is just another form of advertising but more subtle than an attention grabbing advertisment blocking half the screen. In-game items that advertise a brand name would be less obtrusive and most likely more effective. Finding sponsors wouldn’t be easy but there are other sources such as affiliate marketing (see Amazon Affiliate Program).

Sell unobfuscated and commented source code

With HTML5 games and apps the source code will always be there for all to see even if obfuscated. One may as well either publicly release it or offer the full commented and styled source code for a fee, should developers want to learn or expand on it.

Merchandise

Companies like CafePress offer the ability to customise T shirts, stickers, posters and various types of merchandise to sell to loyal fans or even as a prize for the aforementioned raffle.

There is definitely room for some creative forms of monetization that benefit the developer as well as the player. I would be interested in hearing other ideas.

Simulating a player

Automated tests are a great way to do a sanity check against any changes you feel might affect other areas. You can quickly run some tests and ensure components do as they’re expected. This doesn’t cross over well into game development because other factors come into play such as input, randomization, networking and other variables that affect the program.

What’s really needed is to be able to simulate a player and observing the outcome exactly as it was when it was logged. To do this, every single variable that affects the game state has to be logged with a timestamp so it can be played back at the exact same interval. This includes randomly generated numbers, click or keyboard events, network data, time etc etc.

Benchmarking

There are more use cases than just automated tests. You can use it for benchmarking so that every platform you test will involve the same gameplay and actions. Domsz has done this for his game engine, ImpactJS.

Validate High Scores

Blindly accepting any high score as valid can and probably will lead to people sending requests with an obviously fake score. Sending the data to the server and replaying it to see what the end result is can be used to determine whether they cheated or not.

Multiplayer

Simulating the input on the server can be used for multiplayer games to keep two or more players in sync and prevent players from cheating. There’s obviously more to it than that but it’s an idea.

Gameplay

It’s now a common gameplay component to allow players to replay part of the game or for a stylised effect such as killcam.

For games that are heavily randomly generated (which a lot are), there is the option to save the seed used so all that is needed is to use the same seed when replaying to generate the same random numbers. Not all random functions provide this feature (JavaScript doesn’t). Another way around this is to log the generated value so when you replay it, use the same number that was generated last time.

There is a great post about implementing such as thing known as Deterministic Games. Unfortunately it is mainly relevant to the LWJGL framework.

Performance framework proof-of-concept

Performance is a very important factor for JavaScript games. It becomes a crucial factor when you bring mobile devices into the mix.

Luckily we have some great tools for testing different methods of coding such as JSPerf. This lets developers test code snippets across multiple browsers to compare.

On the same vein, JSGameBench stress tests rendering methods including WebGL, Canvas and DOM.

At Game Closure we want to look deeper and more thorough so I’ve been thinking about different ways to design a framework that will allow us to run tests with an assortment of different methods and combinations. With JSPerf one has to write individual test cases for every combination. Here is my proposal:

Templates

Code to test should have some templates that form the basis of what we’re testing. It is similar to startup and teardown methods but finer grained. You may want to move some startup code outside of the template to avoid it being benchmarked unnecessarily.

Placeholders

This is the key component to the power of this testing framework. Add placeholders in the template code that will be replaced based on the combinations being tested. The placeholders are denoted by a comment followed by a colon and the name of the placeholder.

function renderDOM() {
    dom.style.left = /*:x*/;
    dom.style.top = /*:y*/;
}

function renderCanvas() {
    ctx.drawImage(
        /*:type*/,
        /*:x*/,
        /*:y*/
    );
}

This looks like gibberish now but starts to make sense when you create a list of different values for these placeholders in the form of an object where the key is the name of the placeholder and the value is an array of possible combinations to test:

{
    x: [
        "~~x", 
        "x", 
        "Math.floor(x)"
    ],

    y: [
        "~~y", 
        "y", 
        "Math.floor(y)"
    ], 

    type: [
        "cnv", 
        "img"
    ]
}

The test framework will use all the possible combinations of these values testing to see which performs the best. You can also specify which functions to test against. In our case the two functions are “renderDOM” and “renderCanvas”. This means it will generate 36 combinations of the placeholders and functions.

Test it!

Running a test requires the startup code, a template defined with relevant placeholders and then an object with the combinations of values. You can optionally specify an amount of iterations to run (it defaults to 1000).

The above test gives us this:

~~x, ~~y, cnv, renderDOM | 28ms
~~x, ~~y, cnv, renderCanvas | 1222ms
~~x, ~~y, img, renderDOM | 18ms
~~x, ~~y, img, renderCanvas | 8ms
~~x, y, cnv, renderDOM | 33ms
~~x, y, cnv, renderCanvas | 1234ms
~~x, y, img, renderDOM | 33ms
~~x, y, img, renderCanvas | 8ms
~~x, Math.floor(y), cnv, renderDOM | 18ms
~~x, Math.floor(y), cnv, renderCanvas | 1237ms
~~x, Math.floor(y), img, renderDOM | 18ms
~~x, Math.floor(y), img, renderCanvas | 8ms
x, ~~y, cnv, renderDOM | 25ms
x, ~~y, cnv, renderCanvas | 1305ms
x, ~~y, img, renderDOM | 24ms
x, ~~y, img, renderCanvas | 7ms
x, y, cnv, renderDOM | 54ms
x, y, cnv, renderCanvas | 1322ms
x, y, img, renderDOM | 55ms
x, y, img, renderCanvas | 7ms
x, Math.floor(y), cnv, renderDOM | 25ms
x, Math.floor(y), cnv, renderCanvas | 1301ms
x, Math.floor(y), img, renderDOM | 26ms
x, Math.floor(y), img, renderCanvas | 8ms
Math.floor(x), ~~y, cnv, renderDOM | 18ms
Math.floor(x), ~~y, cnv, renderCanvas | 1238ms
Math.floor(x), ~~y, img, renderDOM | 18ms
Math.floor(x), ~~y, img, renderCanvas | 8ms
Math.floor(x), y, cnv, renderDOM | 36ms
Math.floor(x), y, cnv, renderCanvas | 1235ms
Math.floor(x), y, img, renderDOM | 34ms
Math.floor(x), y, img, renderCanvas | 7ms
Math.floor(x), Math.floor(y), cnv, renderDOM | 18ms
Math.floor(x), Math.floor(y), cnv, renderCanvas | 1235ms
Math.floor(x), Math.floor(y), img, renderDOM | 18ms
Math.floor(x), Math.floor(y), img, renderCanvas | 7ms

A few things to note is my method of benchmarking is currently very naive as this is a proof-of-concept. I will be looking into more solid forms detailed in this great post. The other thing to note is some of these tests are essentially duplicates. The renderDOM method doesn’t use the type placeholder so it generates combinations that have already been run. This isn’t really a problem and is more to do with how you define your templates and placeholders.

Analysing the data

Once we have this data we need a way to understand it and derive facts. I imagine a big table with the placeholders, functions and result as the columns and the combinations as the rows. You will be able to filter by placeholder values and sort ascending or descending on the result column.

Browsers

Running these tests against different browsers can be useful to determine cross-browser optimization or things to avoid. It is therefore important to be able to view and compare all the results and how they performed on which browsers. To display this in a table, the execution time column would have to include the result from different browsers. This could be done by adding a column for each browser result and keeping the main result as an average.

These ideas are still very early stage and I have only recently managed to get code executing from placeholders and generating combinations. I will do more research to determine how it can be more useful for existing projects and how to best display the data. Maybe even a GUI along the lines of JSPerf could make it more helpful.

Entity Component Systems: Inheritance vs Composition

My methodology of choice for game development is something known as an Entity Component System. Entities are game objects, they have no functionality until you apply components. This avoids long chains of inheritance so is easier to maintain and reuse.

There are two ways to implement Entity Component Systems, through composition or inheritance.

Crafty uses an entity component system through inheritance. An entity starts its life as a simple object, when you add a component the entity inherits all the functionality. It is similar to one layer of multiple inheritance (without the diamond problem) or mixins.

This makes abstraction easier where components can reference any other components without needing to know which component it is so long as they both implement the same interface. Crafty does this for the DOM and Canvas components.

There is an obvious problem with the lack of namespacing: naming collisions. I personally haven’t come across this yet (probably because I know the names of the internals) but it seems others have. It’s also not very elegant as your entities end up as big blob objects.

Composition seems to be the preferred way of doing things. Through composition you would create an instance of the component and give the entity a reference to it. This may seem elegant but how do components talk to each other? The only way to go about component communication is by giving the component a reference back to the entity.

CompA = Class(Component, function() {
    this.method = function() {
        this.owner.getComponent("CompB").method();
    }
});

We can get a direct reference to another component through the entity (this.owner) and we have component communication. But there are a few problems with this solution. First of all it’s hideously verbose but worst of all it creates a tight coupling between CompA and CompB. What if we change the name or can’t be sure what the component will be (say if there were two components that implement the same interface)?

The solution to this is messages or events. Tell the entity the component wants to send a message to all other components that want to listen. Other components can register a callback to those messages and decide what to do.

CompA = Class(Component, function() {
    this.method = function() {
        this.owner.sendMessage("doSomething");
    }
});

CompB = Class(Component, function() {
    this.method = function() {
        this.owner.recieveMessage("doSomething", this.doSomethingHandler);
    }

    this.doSomethingHandler = function() {
        //no coupling! :)
    }
});

Now the components are completely seperate from each other and can be individually replaced without worrying about dependencies. I mentioned my distaste for verbose solutions but luckily in the land of JavaScript we can make nice short cuts.

CompB = Class(Component, function() {
    this.onDoSomething = function() {
        //no coupling! :)
    }
});

The message dispatcher will just see if any components have a function called “on” + the message name and execute it.

While this approach is very elegant and decoupled it’s not a perfect solution. What about a component that changes the position of the entity. Sending a message each time gets tedious especially if that component is never going to change or be replaced (such as a Position component). In these situations keeping a reference isn’t so bad:

CompB = Class(Component, function() {
    this.init = function() {
        this.Position = this.owner.getComponent("Position");
    }

    this.onDoSomething = function() {
        this.Position.x += 10;
    }
});

My personal preference is through composition and message passing. It seems to be more flexible and has no real drawbacks.