Middleware for the Win

I've been developing the authentication system, and I have to say, I'm thoroughly impressed with ActionHero. It's an advanced piece of software that keeps surprising me; just when you think you have it figured out, a new problem surfaces, and AH reacts gracefully by giving you yet another option in the form of a solution.

The authentication system is simple: if an action is a login request, generate a new session for the user and store it in cache. Otherwise, search for the user's session in the cache. In both cases, Action Middleware is used to perform the authenticator's pass through behaviour. And in all cases, now that this system is working, all other actions are alleviated from the necessity of verifying users when triggered.

It's also lightning-fast; in most cases I've seen cache-auth activity as performant as 3ms, which is great!

Next I'll be developing character selection and creation.

Sample World

I've been testing the world generation code, and preparing the weather system by exporting a height-map, from which wind direction can be derived. In the interim, here's a sample world output. It's rendered to-scale, and is 2048x1024 tiles.

Please be patient; this file is huge!

One Thing Leads to Another

Tempest consists of a number of components which make up its whole. I've always been fascinated with world generation techniques, and Tempest is a decent example of its employ to produce the foundation for a living, breathing world. One of those features is a believable weather system, which loosely matches the weather found on Earth. Since humidity, temperature and altitude determine weather patterns, I decided a few weeks ago I would attempt to create a reasonable facsimile of the weather patterns we're so used to. I'd completed work on the first two pieces (humidity and temperature), but I needed to extract height data from the map, too.

When I went to the original world-map-to-sprite-map (C#-based) conversion code to make modifications, I found that what I'd written would be difficult to extend, and lacking in performance... not to mention my dwindling experience with C#, since I've not coded in it regularly in 3 years. I'd been meaning to return to it for a rewrite anyway, so I decided to put the main project's development on hiatus in order to pursue this objective. This was, according to my git log, begun 4 days ago.

I'm proud to say, at 8:07pm this evening, I completed my rewrite of the world generation code! This means that the entire feature-set, apart from the binary which generates fractal worlds, is running in native Node.js -- and is it fast! Conversion of a 512x256 world map into a 1024x512 sprite map takes 3.15 seconds.

And now, for the weather...

Reduce, Reuse, Refactor

As Tempest has evolved over time, the technologies employed to implement its feature-set also evolve. When I originally wrote the map generation system, it consisted of a fractal world based map generator (based on this one), a fractal-to-tile-map converter (custom built for compatibility with Tiled), and a Redis-based caching and lookup system for sharing map contents across servers.

Recently, however, I've found it necessary to rewrite the second component in this triad of world building tools; when I originally wrote the Tiled map generator in .NET, I was happy with its performance. But since moving to the Node.js world, I have high expectations for my programs!

So in order to call this project "complete", I've spent the last few days (minus the last 48 hours due to illness) taking the code written in C#, rewriting it in JavaScript, converting the tile-mapping configuration originally stored as XML into JSON, and seeing a marked performance improvement (I don't recall previous benchmarking, but it's currently sitting at around 3 seconds, which I do recall is significantly better), reduced code size (about half), and since the logic is already sussed out, the rewrite isn't going to take much longer (might be today or tomorrow).

The Story So Far

I've been plugging away at base features. The list so far is as follows:

  • Re-implemented map traversal
    • This had been memory-based, local to the application server. Now it's dripping in Promise-y goodness; the map management system loads requests from Redis cache instead. And it's super fast! Typical requests, on my development machine, take 3-12 ms, and up to 20 ms when loading new chunk data.
  • Added world-save
    • Yes, now you can save the world! Actually, it's for storing things long-term. This task runs on a 1-minute timer; everything that needs to be saved to the database is loaded from the Redis cache and stored in MySQL. I don't have much to say about its performance yet, since I am only saving the test character's data. That takes anywhere from 8-43 ms.
  • Implemented window resizing
    • It seems like a small thing, but being able to rotate my iPhone and see the game take its proper dimensions and sizing is a nice thing.
  • Audio subsystem
    • I've never worked with HTML5 audio, apart from an iTunes-alike I wrote in college. However, I've written a custom loader which accepts sound file data from the server on-load, caches sound files locally, and handles any number of sounds dynamically. And on that note...
  • Character footsteps
    • The main character plays a light, grassy footstep when walking around the world. Seems like a small thing, but man does sound add depth to the game.
  • World Clock
    • The game tracks time at a rate of 1:60 (1 second our time is 60 seconds game-time). And with that comes...
  • Day/Night Cycles
    • Truly a cool thing; at 8pm (game-time) the sun begins to set, until near-complete darkness descends around the player at 10pm. And at 4am, the sun begins to rise again, returning the world to full brightness by 6am.

The game is really turning out well, and I'm implementing features at a startling rate. I'm looking forward to the coming weeks.

Next up:

  • Returning the UI to its former glory.
  • Adding proper account, character and family creation.
  • Reinstating multiplayer.
  • Adding chat.

Until next time!