Introducing: Assembled Realms, Build and Play Open-Source MMOs - All From A Browser

When I was eleven years old I had an experience that would eventually set the course for my entire professional life. It was my first day of class in the 6th grade. The middle school was experimenting with a new curriculum that would expose gifted students to a computer in every classroom, the lion-share of which being the venerable Macintosh Classic II.

I immediately began tinkering. Lessons were completed as quickly as possible to afford me more time on the machines. I stayed after school learning AppleScript. I’d create simple slide-based adventure games for my friends to play and solve (think Myst written by a little kid with no graphics at all). I wanted to create more advanced games so I checked out a book from the library that would teach me how to write BASIC. The book had full source code examples that I hungrily reverse engineered and re-imagined.

This early passion to figure out how things work and to make things my friends could enjoy ignited a life long career in software development. Assembled Realms hopes to offer that same sense of wonder and opportunity with a significantly lower barrier to entry. The idea is to provide structured game “engines”, essentially mini working games, to users that serve as the foundation for experimentation, that can be picked apart or completely demolished and rebuilt.

All client and server code is written in Javascript and can be created/edited directly from a browser. No software to download, no platform restrictions. Realm builders can launch their games with a click of a button, receiving a public URL to give to friends. Bugs and improvements can be suggested by the user base, pushing the realm builder to research, explore and learn. Users are introduced to concepts essential to the software development lifecycle - committing, publishing, debugging, etc - in a fun and effective way.

I’m excited to see what the community can produce and am making myself available to help in any way I can.

Assembled Realms

@chasebgale



Introducing: Rocketcharts, Open-source HTML5 Financial/Statistical Charts

Utilizing HTML5′s canvas, I present to you my newest open-source project: rocketcharts. I am following the “release early, release often” mantra for this project, so I’d keep it out of production code for the moment. Speaking of code, how did I generate the above interactive chart?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<script type="text/javascript" src="rocketcharts.js"></script>
<script type="text/javascript" src="jquery-1.5.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var style = new Object();
style.UpColor = {r: 0, g: 255, b: 0};
style.DownColor = {r: 255, g: 0, b: 0};
var settings = new Object();
settings.customUI = true;
var rocketcharts = new Rocketchart();
rocketcharts.init(document.getElementById("rocketchart"), settings);
var googData = [{date: "11/9/2010", open: 17.22, high: 17.6, low: 16.86, close: 16.97, volume: 56218900},
{date: "11/10/2010", open: 17, high: 17.01, low: 16.75, close: 16.94, volume: 17012600},
...
{date: "9/29/2011", open: 14.34, high: 14.39, low: 13.15, close: 13.42, volume: 45776600},
{date: "9/30/2011", open: 13.21, high: 13.44, low: 13.11, close: 13.17, volume: 30232800}];
// rocketcharts.addSeries(title, data, type, style, panel);
rocketcharts.addSeries("GOOG", googData, undefined, style);
// rocketcharts.addIndicator(id, params, series, panel);
rocketcharts.addIndicator("movingaverageconvergancedivergance", undefined, 0);
});
</script>

A View of the Architecture from 30,000 Feet

Before we jump right into how to use rocketcharts, let’s first understand what is going on behind the scenes. If you look at the code above, you’ll notice the first method call: rocketcharts.init(element, settings); “element” points to a container in your DOM, typically a DIV, where you want the chart displayed. Rocketcharts respects any styles you have set for this element and will not resize it; Instead, JQuery is employed to append a canvas, referred to as a chart panel, to that DIV.

“But what is a panel?” If you look again at the code block above, you’ll notice I don’t specify the last parameter of the “addIndicator” call which specifies a panel ID. The lack of a panel being passed creates a new panel for the indicator to be drawn on, i.e. a new canvas appended to the DOM. Adding a new element for each panel, rather than drawing all the panels on one large element, brings several advantages to the table. For one, we can leverage the existing power of a modern browser using JQueryUI to allow effortless user-resizing of the panels. No need to worry about vertical scrolling either, as this is taken care of for us.

Once we have our panels appended to the DOM, the real fun can begin: pixel manipulation. “Am I nerd, a geek or just a passionate developer? Playing with pixels is fun, dammit!” Essentially, rocketcharts performs some initial calculations, then loops through each panel and calls it’s draw method.

The State of Rocketcharts

For the moment, rocketcharts is functionally quite basic. You can add your own Open-High-Low-Close-Date data to the chart. You can add one of three indicators and specify to draw over the primary series or on a new panel. Simple for now but the foundation is in place – adding additional studies/indicators is a simple affair.

Within the immediate future I plan to add zooming and horizontal scrolling, more indicators and a more robust UI allowing the user, rather than you, to manage the chart. I encourage you to follow along with the source, all feedback is welcome and will help keep the momentum of the project high.



Raster Text In HTML5's Canvas

I love HTML5′s canvas. Armed with only a modern browser, we now have access to a plethora of drawing/imaging functionality with no third-party plugins required. Unfortunately, life isn’t all sunshine quite yet, echoed across the web is one resounding cry: “drawText is performance murder.“ Even more unfortunately, the project I am currently building requires heaps (pun intended) of drawText() calls.

So, what to do? How do we quickly get a block of text onto a canvas? The answer is to manipulate the pixels of the canvas directly. I feel that code speaks louder than words, so let’s jump right in. First, you’ll need an image that represents our font:

As you can see, I am using a bitmap font (no anti-aliasing) and I am outputting all characters in order, starting at charcode 33. Note: The lookup function we are going to write today depends entirely on these characters being in order. The next step is to load the font image into an off-screen buffer, or in our particular case, a hidden canvas element.

1
2
3
4
5
6
7
8
var fontImage = new Image();
fontImage.onload = function(){
var bufferCanvas = document.getElementById("bufferCanvas");
var bufferContext = bufferCanvas.getContext("2d");
bufferContext.drawImage(fontImage, 0, 0, 566, 7);
};
fontImage.src = "bitmapfont.png";

Now that we have our image drawn into the canvas, we are able to extract a representative array of pixels and begin processing them. The idea is to iterate over each block (every 4 elements of the array correspond to red, green, blue and alpha channels of a single pixel) and record the significant points for each character.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
var fontPoints = new Array();
var fontImage = new Image();
fontImage.onload = function(){
var bufferCanvas = document.getElementById("bufferCanvas");
var bufferContext = bufferCanvas.getContext("2d");
bufferContext.drawImage(fontImage, 0, 0, 566, 7);
var w = 566;
var fontPixelArray = bufferContext.getImageData(0, 0, w, 7);
// Store pointer directly to array of data to speed up lookups
var fontPixelData = fontPixelArray.data;
var total = -1;
var x = 0;
var y = 0;
var index = -1;
var pointsLength = -1;
for (var i=0; i < 95; i++) {
// Each array element is an array that stores relative x and y coordinates
fontPoints[i] = new Array();
}
for (var i=0; i < fontPixelData.length; i++) {
// Add up the R, G, B values
total = fontPixelData[i] + fontPixelData[i+1] + fontPixelData[i+2];
// If the total = 0 it's a black pixel, if not, we need to record it
if (total > 0) {
x = i / 4 % w;
y = ( i / 4 - x) / w;
// We can derive the character index by dividing by the character width
index = Math.floor(x/6);
x = x - (index * 6);
pointsLength = fontPoints[index].length;
fontPoints[index][pointsLength] = {x: x, y: y};
}
i += 3;
}
};
fontImage.src = "bitmapfont.png";

As illustrated above, we first create an array containing 94 child arrays – each will hold the significant points of the associated glyph; next, we iterate over the CanvasPixelData array in chunks of 4, screening out black pixels. Once we come upon a non-black point, we derive it’s relative coordinates and character index, then add the point to the appropriate array.

At this point, we have an array of coordinates to reproduce every glyph in our original image. As I’m sure you have anticipated, we now need a method we can invoke that will imprint these coordinates onto an existing image. Again, code speaks louder than words:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function setPixel(imageData, x, y, r, g, b, a) {
index = (parseInt(x) + parseInt(y) * imageData.width) * 4;
imageData[index+0] = r;
imageData[index+1] = g;
imageData[index+2] = b;
imageData[index+3] = a;
}
function rasterText(imageData, text, x, y) {
var len = text.length;
var i = 0;
var code = 0;
var characterPixelLength = -1;
var startX = x;
var startY = y;
for (i=0; i < len; i++) {
code = text.charCodeAt(i) - 33;
if (code > -1) {
characterPixelLength = fontPoints[code].length;
for (var j=0; j < characterPixelLength; j++) {
setPixel(imageData,
startX + fontPoints[code][j].x,
startY + fontPoints[code][j].y,
255, 255, 255, 0xFF);
}
}
startX += 6;
}
}

Our new “rasterText” method accepts a string as one of it’s parameters. For each character in this string, we lookup the number of points required to reproduce it, then for each of those points, we call the helper method “setPixel.” You’ll also notice on line 19, we determine the index in our array by subtracting 33 from the character code. A space resolves to -1, but you’ll notice we increase our “startX” outside that condition, so the space is preserved.

Here is how we would use this method from start to finish:

1
2
3
4
5
6
7
var destinationCanvas = document.getElementById("destinationCanvas");
var context = destinationCanvas.getContext("2d");
var imageData = context.getImageData(0, 0, context.width, context.height);
rasterText(imageData.data, "Hello World!", 10, 10);
context.putImageData(imageData, 0, 0);

Awesome! However, I’m sure upon reflection you’ll be identifying the limitations of this technique. Namely, you’ll need to load and pre-process a different image for each font face and font size. Up front costs in terms of your effort, sure, but during testing my aforementioned project, text rendering time was reduced by a mean ~20%.

In closing, the method we built here today is by no means a nail in the text-rendering-poor-performance coffin. What it is, however, is another tool in your arsenal - I urge you to treat it like a scalpel, not a hammer.



User Activity Tracking in ASP.NET MVC3 via Global Filters

When designing enterprise applications I often run into the same request from the business: ‘user tracking.’ Who created this entity? What time? Why was this entity created (origin tracking)? In the past I have seen colleagues create additional columns, such as userId and creationTime, on every ‘trackable’ table in the system. At the time, this made sense; However, with the advent of Global Filters in MVC3, more efficient ways of doing this have become apparent. Let’s jump in head first.

Open up Visual Studio 2010 and your MVC3 project. If you’d like, simply create a new MVC3 Web Application for the purposes of this tutorial. Next, create a folder under the project root named ‘Filters.’ In this folder, create a class named ‘UserActivityAttribute.cs’ – please note, these names can be anything you desire and hold no special meaning. When you’re finished, your solution explorer should look something like the following:

Still with me? Awesome. Open up your newly created class and inherit from ‘ActionFilterAttribute.’ ActionFilterAttribute has several methods you can override which you can read about individually over at MSDN; For now though, let’s focus on ‘OnResultExecuting.’ As you might have guessed, this method is fired before the result is executed. Go ahead and override this method, bringing your class to look something like this:

1
2
3
4
5
6
7
public class UserActivityAttribute : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
base.OnResultExecuting(filterContext);
}
}

Now for the fun stuff! As I’m sure you’ve observed, we get one argument from this method: ‘filterContext.’ From this ResultExecutingContext we will corral all the information we need to track our user’s actions. Which ActionFilterAttribute method to override depends on what type of information you are trying to capture and the same goes for the approach. To that end, let’s say that in your scenario entities are created using the standard ‘Create’ action. Furthermore, assume that after successful creation you redirect to that entities ‘Details’ action.

So, with these assumptions fresh in our minds, what is the first step to isolate the data we want?

1
2
3
4
5
6
7
8
9
10
11
12
public class UserActivityAttribute : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
if ((filterContext.Result is RedirectToRouteResult) &&
(filterContext.RequestContext.HttpContext.Request.RequestType == "POST"))
{
}
base.OnResultExecuting(filterContext);
}
}

As you can see, we check that the result primed for execution is of the type ‘RedirectToRouteResult.’ Additionally, we ensure the request was a POST, the default request type for ‘Create’ methods. Now that we have this in place, let’s extract some information about the RouteData of the Request and filter down further.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class UserActivityAttribute : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
if ((filterContext.Result is RedirectToRouteResult) &&
(filterContext.RequestContext.HttpContext.Request.RequestType == "POST"))
{
var originController = filterContext.RouteData.Values["controller"].ToString();
var originAction = filterContext.RouteData.Values["action"].ToString();
if (originAction == "Create")
{
}
}
base.OnResultExecuting(filterContext);
}
}

Now we have the controller and action of the request, using this information we filter out actions not matching our mock scenario, create calls. The final step is to decide what information to store and to format it accordingly. Let’s assume this application tracks brick-and-mortar stores and the customers that frequent them. We have two different controllers, Customer and Store, and based on what we are creating we want to change the formatting. I’ll let the code do the talking:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class UserActivityAttribute : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
if ((filterContext.Result is RedirectToRouteResult) &&
(filterContext.RequestContext.HttpContext.Request.RequestType == "POST"))
{
var originController = filterContext.RouteData.Values["controller"].ToString();
var originAction = filterContext.RouteData.Values["action"].ToString();
if (originAction == "Create")
{
RedirectToRouteResult redirectResult = filterContext.Result as RedirectToRouteResult;
var form = filterContext.RequestContext.HttpContext.Request.Form;
var destinationController = redirectResult.RouteValues["controller"];
var destinationAction = redirectResult.RouteValues["action"];
var destinationId = redirectResult.RouteValues["id"];
var destination = "/" + destinationController + "/" + destinationAction + "/" + destinationId;
var title = "";
switch (destinationController)
{
case "Customer":
title = form["FirstName"] + " " + form["LastName"];
break;
case "Store":
title = "#" + destinationId.ToString();
break;
}
var action = "Created " + destinationController + " [" + title + "](" + destination + ")";
Tracking.RecordSystemUserAction(action);
}
}
}
}

Too cool, right? I love this stuff. Let’s break it down; First off, we pull out and cast the Result object. Secondly, because we know we are in a post, we pull out the form the user submitted. Thirdly, we extract all of the destination route information and use it to switch and further format. Finally, we bundle all of this up into a nice, human readable string and send it off to our utility method to be saved.

How you format this information is entirely up to you and your use case. As you may have figured out from the psuedo-markup I am generating, in my case I take anything inside the brackets and generate a url from the destination. When history is presented the end user, they see a friendly ‘wall post’ style list, allowing them to easily click through their history.

Ok, so I said that was the last step, I fibbed. Now we have this badass user tracking ActionFilterAttribute, how do we tell MVC3 to execute this code on every request? Under the project root in your Solution Explorer, find and open a file named ‘Global.asax.’ You’ll see a method titled ‘RegisterRoutes.’ Paste the following code above it.

1
2
3
4
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new UserActivityAttribute());
}

Now find the ‘Application_Start()’ method in the same file. Ensure that ‘RegisterGlobalFilters(GlobalFilters.Filters);’ is called within. That’s it. For real this time. When your MVC3 application starts, it will call this method; Behind the scenes, every action method is adorned with the attribute we just created.

The possibilities exposed by Global Filters, coupled with their ease of implementation, makes them an essential card up your sleeve. I’ll leave you with one friendly piece of advice: Remember that these overridden methods will be called with every single request. Make your initial condition as exclusive as possible to save cpu cycles.

Best of luck.