Like Clockwork

I participated in the GDSE Game Jam over the weekend and ended up making a pretty cool game in a very short period of time. For those who are unfamiliar with game jams, you are given a theme at the start of the competition, and you have to make a game from scratch before Sunday at Midnight, using only freely available tools and art. Once the games are submitted, there is a voting period, and the one with the most votes wins.

The theme for this jam was “There can only be one”. It took a lot of thinking, but I finally thought of, and settled on programmable bots that would fight each other in a 2D arena. I didn’t want the bots to be futuristic, and so the medieval archer game Like Clockwork was born.

Like Clockwork’s documentation and source are available on bitbucket, and you can play it on my App Spot

Note that the battle field will only work in Firefox due to technical limitations. I hope to have a working version in Chrome soon. After this fix is made, Chrome users will have to enable the Experimental JavaScript flag in the browser because Chrome does not support the future JavaScript function yield out of the box.

For this game, I am using a technology stack that is completely new to me: CraftyJS, Blockly, Google App Engine, and the future JavaScript function yield. From a high-level, users stack blocks together in Blockly, then publish the generated JavaScript to Google App Engine’s cloud storage where they (and others) can select bots for battle, which then sends the JavaScript bots to the CraftyJS “battle engine” where you get to watch the bots move around and shoot arrows at each other.

The game took me almost exactly 30 hours of work from start to finish, and a lot of this time was spent reading documentation for the new technologies that I am using in this project. Here’s a rough timeline:

  • Friday, Night Started to use CraftyJS, setting up a grid and going through tutorials
  • Saturday, Mid-day 2D playing field with red squares shooting brown squares using hard-coded “scripts” with only movement and shooting
  • Saturday, Evening Archers shooting arrows with sounds and animation
  • Saturday, Night More scripting functionality: Scanning, stabbing, etc.
  • Sunday, Mid-day Blockly was installed on a new Google App Engine and I could run the battle engine through it. Starting to play with the App Engine cloud storage tutorials. Decided to test in Chrome, whops, yield doesn’t work
  • Sunday, Evening Added a couple custom blocks to Blockly. Listed scripts from App Engine on a web page
  • Sunday, Night Oh boy, I really need to tie the ends together. Managed to get scripts going from end to end, then had a moment or two to add a new block or two, and the last crucial step: Names need to be displayed above the bots. Publish, document, submit.

The end was a bit tight. If I didn’t connect Blockly to the Battle Engine, I would have had nothing. Luckily, I came across very few roadblocks and was able to pull everything together in the last hours of the jam, :)

Here are some screenshots of programming and fighting:

VXc3Pe1

zepIwuH

Wish me luck in the polls!

Changing Hats

Gears are changing! Engine and tool design is phasing out (with a few major exceptions), and game design is in. It feels weird to say it, but during the last 4 years, I’ve had a very nebulous, hand-wavy idea of what I wanted in the end. Now that I’m at the point where I’m adding end-game content, I’m scrambling to figure out what I actually want in the game. What sorts of structures do I want, what kinds of weapons will be used, what kinds of upgrades do I want, what will the scenarios look like, do I want a story line, do I want voice acting, etc. So many questions. For now, I’ll add content bit by bit while finishing off the engine and tools. The content is going to take some play testing to see what works and what doesn’t, so it’s a good thing that it’s easy to add stuff and play around with it.

And for a quick status update: single-unit upgrades are physically working but not pretty, the solar station can now be upgraded to level 2, added auto-healing to all structures, constructing and upgrading units can now be cancelled, and worked some more on the context menus.

Closing the Source

After much thought, I have decided to close Asteroid Outpost’s source code. The current repository will remain as-is, and development will continue in a new, private repository. This saddens and excites me. It has been a pleasure to work in the public eye, being able to link directly to the source, and those proud moments when someone forks your solution. sigh. At least the excitement of what this means overwhelms my sadness. I’m starting to think that the game is at a point where most of the engine is in place, and I can start adding real content. This has been in the back of my head for a while, and it feels like I have been holding off on adding too much content to the open source version. If I ever want to sell the game, there’s got to be a cut-off point, otherwise nobody would buy the full game. That cut-off point is now. I can do this.

In other news, I have created a new Asteroid Outpost YouTube channel. I am unable to move all of my existing videos over from my personal account, but I will just re-upload them. All new content will be on the Asteroid Outpost channel, so subscribe if you want the latest videos.

Working with the Mercurial Particle Engine

I had some troubles getting Mercurial Particle Engine (MPE) to work in my game and I thought I’d share my experiences, how to avoid my mistakes, and how to get it working in your own project.

First off, I downloaded the binaries from their website, started up a particle testing ground and after a few fast fails (effect not initialised exception, etc.), I got some explosions rendering! I thought I was off to a great start until I noticed that I couldn’t scale it. Oh joy, there’s a Transpose property of the Renderer, but in the binary release, it apparently doesn’t pay attention to that. So I grabbed the “mainline” from their repository, which fixes this issue. Not a problem. There were a couple API differences, but nothing to worry about. First thing I noticed is that the RenderEffect method changed from:

// Old, binary release, 3.1
void RenderEffect(ParticleEffect effect);

to

// Mainline, 4.0
void RenderEffect(ParticleEffect effect, ref Matrix world, ref Matrix view, ref Matrix projection, ref Vector3 camera);

With no overloads. I thought: “Great! This can scale my explosion! I’m set”. I also noticed that I didn’t need to initialize my Effect anymore:

// Old, binary release, 3.1
myEffect = Content.Load<ParticleEffect>("BasicExplosion");
myEffect.Initialise();

vs

// Mainline, 4.0
myEffect = Content.Load<ParticleEffect>("BasicExplosion");

Fair enough. Maybe they found a way to initialize the effect inside the custom XML loader, right? Wrong. In the binary release, when I omitted myEffect.Initialise();, it threw an exception in my face. Wonderful! I added the line and moved on. In the mainline version, you need to go through each of your Effect.Emitters, and manually load the texture for them. If you don’t do this, it will happily draw nothing. Yup. Nothing. It will sit there and go if(veryImportantTexture != null){ draw(veryImportantTexture); } else{ /* fap fap fap */ }. Well there goes 6 hours of my life that I’ll never get back. Since I haven’t written an article on Failing Fast, that will be next (or at least very soon). Developers of a public API, scratch that, of ANY API should write code that makes it hard to make mistakes, and when you do make a glaring error (like a missing texture), make it obvious! Throw an exception! Stop executing! What MPE did here is called Failing Slowly. Instead of presenting me with an obvious error that could have been fixed within minutes, it rolled over this obvious error and did nothing. In short, you need to add this when you load your effects:

foreach(var emitter in myEffect.Emitters)
{
    emitter.ParticleTexture = Content.Load<Texture2D>(emitter.ParticleTextureAssetPath);
    emitter.Initialise();
}

Now that I knew my textures were loading, I continued to play around with the world, view, and projection matrices, in combination with the cameraPosition vector, but nothing drew. Hours went by while I researched matrix math, played around with these variables, looked up (outdated) samples of other people using MPE, and played with these variables some more. I finally started copying out bits out of their test suite. I changed my Renderer from SpriteBatchRenderer to QuadRenderer, and wow! It started to render! Now why doesn’t my SpriteBatchRenderer work? I know can use the QuadRenderer in a 2D game, but I wasn’t using Quads elsewhere in my game and would rather stick to the SpriteBatchRenderer.

In the test suite, they did something interesting with the SpriteBatchRenderer: they assigned a value to the renderer’s Transpose property on initialisation. I tried this, and what do you know! Something was rendering, yet again. Now… why does the SpriteBatchRenderer need 4 matices and a Vector3 to do its rendering? It doesn’t. I messed around with the parameters for the RenderEffect(...) method, and nothing changed. It doesn’t pay any attention to any of the 3 Matrix parameters or the camera position variables. All it cares about is that you set the Transpose property to something, anything. It does not assume the identity matrix and will again, draw absolutely nothing if not set. Here’s what you need at a minimum:

myRenderer.Transformation = Matrix.Identity;

Wow… so MPE does not tell you when you are doing it wrong, at all. If you plan to use the SpriteBatchRenderer, here’s a summary of what you need to do:

  • You must load all ParticleTextures manually for each Emitter in your Effects
  • You must set the Transformation property of the SpriteBatchRenderer to anything other than null
  • Completely ignore the world, view, and projection matrix parameters to the RenderEffect method.

Something like this should work (partial code):

GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
SpriteBatchRenderer myRenderer;
ParticleEffect myEffect;

public void LoadContent()
{
    spriteBatch = new SpriteBatch(GraphicsDevice);

    myRenderer = new SpriteBatchRenderer();
    myRenderer.GraphicsDeviceService = graphics;
    myEffect = Content.Load<ParticleEffect>("EffectLibrary\\BasicExplosion");
    foreach(var emitter in myEffect.Emitters)
    {
        emitter.ParticleTexture = Content.Load<Texture2D>(emitter.ParticleTextureAssetPath);
        emitter.Initialise();
    }
    myRenderer.LoadContent(Content);
}

protected override void Update(GameTime gameTime)
{
    MouseState mouseState = Mouse.GetState();
    if (mouseState.LeftButton == ButtonState.Pressed)
    {
        Vector3 pos = new Vector3(mouseState.X, mouseState.Y, 0f);
        myEffect.Trigger(ref pos);
    }
    myEffect.Update((float)gameTime.ElapsedGameTime.TotalSeconds);
    base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    Matrix dummyMatrix = Matrix.Identity;
    Vector3 dummyVector3 = Vector3.Zero;
    myRenderer.Transformation = Matrix.Identity; /* set to your own transformation matrix */
    myRenderer.RenderEffect(myEffect, ref dummyMatrix, ref dummyMatrix, ref dummyMatrix, ref dummyVector3);

    base.Draw(gameTime);
}

Awesomium XNA r2 Released

I have updated the Awesomium XNA component to use Awesomium 1.7.1. The most noticeable changes are: improved performance, syntax changes for various tasks, and the lack of smooth fonts over transparent backgrounds.

For performance, my credits screen no longer jerks (at least on my computer), and the performance graph isn’t causing performance issues. Yay!

Creating shared JavaScript objects that persist across pages has changed. Instead of this:

// Awesomium 1.6
awesomium.WebView.CreateObject("xna");
awesomium.WebView.SetObjectCallback("xna", "StartWorld", StartWorld);
awesomium.WebView.SetObjectCallback("xna", "Exit", Exit);

You do this:

// Awesomium 1.7.1
JSObject jsXNA = awesomium.WebView.CreateGlobalJavascriptObject("xna");
jsXNA.Bind("StartWorld", false, StartWorld);
jsXNA.Bind("Exit", false, Exit);

On that note, you’d think that you could create a persistent JavaScript object at any time, with or without the DOM for your page being ready because this JS object isn’t page-specific. But that’s not the case, Awesomium will throw an error if you try to create a persistent JS object before the DOM is ready. I don’t know about you, but I have two modes for my web-GUI to run in: Web Browser mode, and XNA mode. In web browser mode, the most notable change is the background, it is not transparent, I use a still of the background I use in game. In order to automatically detect if I’m in XNA or not, I check for the existence of the global JS object “xna”. But if making the persistent JS object needs the DOM ready, and onDomReady checks for the existence of this object, I have a bit of a catch 22. If I can guarantee that there is a moment between when the DOM is ready and when JavaScript’s onDomReady fires, I can safely create the shared object before anyone notices, but Awesomium doesn’t provide such a method. I tried the event DocumentReady, but it didn’t do the trick. To work around this, I’ve had to register to the DocumentReady event, load a dummy page, when the event triggers, deregister from the event, then create my persistent JS object(s), then finally load the page I actually want.

private void Init()
{
    // Load some dummy page
    awesomium.WebView.DocumentReady += WebView_DocumentReady;
    awesomium.WebView.LoadHTML("<html><head><title>Loading...</title></head><body></body></html>");
}

void WebView_DocumentReady(object sender, UrlEventArgs e)
{
    // Call this only once
    awesomium.WebView.DocumentReady -= WebView_DocumentReady;

    // Create callbacks for Awesomium content to communicate with the game
    JSObject jsXNA = awesomium.WebView.CreateGlobalJavascriptObject("xna");
    jsXNA.Bind("StartWorld", false, StartWorld);
    jsXNA.Bind("Exit", false, Exit);

    awesomium.WebView.Source = (Environment.CurrentDirectory +  @"\..\UI\MainMenu.html").ToUri();
}

Not pretty, but it works. If you know of a better way, leave it in the comments.

Next major change is how pages are loaded. In Awesomium 1.6, you could do this:

WebCore.BaseDirectory = @"..\UI\";
awesomium.WebView.LoadFile("MainMenu.html");

And in 1.7.1 they’re pushing for people to use DataSources, but you can still get by using:

awesomium.WebView.Source = (Environment.CurrentDirectory +  @"\..\UI\MainMenu.html").ToUri();

Last but not least, fonts are rendered opaquely over transparent backgrounds. This ends up making the soft edges of letters render black. Not great. There are ways around this, but I haven’t looked in to them too much.

Tooltips and JSON Entity Definitions

Tooltips have been on the brain, and I looked into implementing them, but realized I didn’t have anywhere to store the required data. Perfect excuse to move everything into JSON files. I’ve wanted to define my entities in JSON files for quite some time now, but I didn’t have a good reason to do it until now.

I have designed a layered JSON system where each layer overrides or adds values to the previous JSON. Currently, I have defined a base entity, followed by one definition for each entity type, then the most specific data is provided at run time when the entity is created. As I was writing this system, it occurred to me that I could write my unit upgrades in the same JSON and just apply it. So much is possible: reloading these JSON definitions on the fly, tying in the entity editor, and even networking. Everything is coming together, and I’m loving it. Now to actually implement what I set out to do: tooltips. That is my next step.

While implementing this JSON system, I came across a few issues. First was that fastJSON didn’t really want to deserialize to a generic placeholder object where I could apply the layers of JSON one after the other. I am glad I gave Json.NET a try, if for nothing else than the JObject and its collection initializer. It really helps to write C# code that looks like JSON instead of writing out a string that contains JSON data.

The second issue was a humorous fail cascade that caused the starting Solar Station to instantly disappear as the game started. You couldn’t select it, so it wasn’t a sprite issue. The creation code was executing, and all the right components were being created. You also couldn’t press Esc to get the in-game menu to pop up, odd. After some digging, I found out that it thought the game was over, which is normal if there’s no power producers in the game. Since it thought the game was over, it thought the in-game “game over” screen was already up and wouldn’t let me press Esc. Mystery one solved. So my solar station was being deleted, but why? With some more digging, the Armour was zero, so the game thought it ran out of health and deleted it automatically. The JSON showed a non-zero value for Armour, and it was loading, or at least it was being set. The setter for the Armour field had a bounds check that made sure it was 0 <= Armour <= TotalArmour. Oi! My TotalArmour was zero, at least for a brief moment while the Armour was being set. Sigh A setter designed to prevent invalid values can really throw a wrench. After loosening the setter’s rules, everything started working as intended.

Screenshot Blog

I saw an other game developer with a screenshot blog, and I thought it was great idea! So I made one for Asteroid Outpost. You can check out the album on Imgur. The screen shots go all the way back to 2009, man it’s been a while, but I haven’t worked on it full time either. You can see obvious gaps over the summer and winter months. Pretty fun to see how far I’ve come.