Over the last several months, I worked out a whole new interface for Aethora’s battle screen. I’ve learned a lot about javascript in the last couple of years since the original design, and I felt that it was about time to scrap the whole thing and rewrite it from scratch. I’m breaking this article into two parts. The first part here will touch on what was wrong with the old interface a little, and then focus on performance improvements. The second part will focus on “point and click” interface improvements.

Beef with the original

The original design drew the battle map by actually drawing a huge table and putting a map tile in each cell. At the end of every turn, any NPCs that needed to take their turn would do so while the player sat and watched a big “Loading…” box, then the whole page got redrawn, the server globbing a huge amount of HTML back to the browser. The only evidence that any NPCs took their turns was in the battle log.

When you wanted to take an action, you had to first highlight a target. It was like a MMORPG – target first, then act. When you targeted someone, you’d get a list of valid actions depending on whether they were friendly or not, how close you were, and how many Action Points you had left. Some players reported that they often moved PCs one tile at a time, inching their way closer to see when they would be just in range for certain attacks. Many players complained that area-based attacks could not be placed in the center of a group of targets unless one of the targets happened to be standing dead center.


old UI: tabby

The old interface also featured a bunch of tabbed components to the right of the map. They held, individually, information about the character who’s turn it was, the help screen, the chat screen, the battle log, and the “turn order” screen (which showed all the PCs and NPCs in the order in which they get their turns, each with health and defense bars). Tabs are a great way to group UI elements when you are dealing with multiple pages of configuration, but when they hide elements that players want to see constantly, then they just become a nuisance. In particular, not being able to see the battle log and the full list of PCs/NPCs with their current status was a common player lament.

Setting the bar


new UI: everything is visible
I had a couple of goals for the rewrite:
  • no full screen page refreshing
  • show the player what the NPC are doing during their turns
  • minimize the amount of HTML needed
  • separate the javascript from the server-side code in a way so that either could be used without the other (having the mindset of an open API)
  • fit all the elements onto one compact screen with no tabs hiding information
  • improve the user interaction (moving characters and taking actions)
  • keep everything as generic as possible to lay the groundwork for PvP/Co-op in the future
So what about PvP/Co-op? Does this mean it’s not far off for Aethora?

Well, code-wise, there’s not a whole lot to do. The server-side code has to be tweaked a bit to allow multiple parties to participate in a battle. Some game design decisions have to be made:
  • Where will PvP be allowed?
  • What are the consequences?
  • How long will a player have to wait for another player to act before the game passes on their turn…
  • ...or should it act for them rather than pass?
  • And how many turns are passed before someone forfeits?
  • What if it’s co-op?
  • Is the battle lost if someone times out? Or is it a “draw”?
A lot of questions still to answer before we go down that road, I’m afraid.

The first couple of goals kind of go together. What they amount to is a whole lot of javascript. I took advantage of the object-oriented aspects of javascript and roughly mapped some of my server side objects to javascript objects. When the battle window first opens, some HTML sets up the framing of the layout, and then a couple different ajax calls are made: the map tiles, the “mobs” (short for “mobiles”: in other words, PCs and NPCs), the chat log, the battle log, and the actions that are available for the PC with the “current turn”. Each of these calls fills in a different part of the screen (and actually, the actions-load doesn’t trigger until after the mobs are loaded in).

From this point, I can update any individual components as they are needed. When someone moves their character, the only thing that needs to be reloaded is that mob’s stats: to reflect the deduction of movement points and to set their x,y location on the map. If they take an action against another mob, then both of those mobs need to be updated. In both these cases, the battle log also needs to be updated.

Smaller bites of AJAX – or as the kids say these days… AJAJ?

All of these updates are AJAX calls, although as many people have started to point out, AJAX is not always Asynchronous Javascript and XML. In this case, I, like many others, have set aside XML and opted for the much leaner and easier to read JSON data format. So a request is made to the server, the server does some database lookups and some processing, then sends back a pure data response in JSON form. The javascript then takes the data and decides what to do with it. Since the calls are “asynchronous”, the javascript doesn’t have to wait for all the calls to come back to deal with the data; it can start updating the battle log when that data comes in and if the mob data gets in at the same time, it can process that too, more or less simultaneously.

The bonus of this strategy is that calls to the server are extremely short. The server only looks up a small amount of data and slaps it into JSON format on each call. The side effect is that there are more calls to the server. Would you rather have multiple short requests, or single, large requests on your server? If you’re concerned about connections, you might feel as though single large requests would be a better option. However the advantage to many short requests comes in during optimization.

Bastardizing the server-side code

I haven’t mentioned it to this point, but the server side code I am using is Ruby on Rails. I love Rails for the flexibility it gives me in developing database-backed web applications (insert your own favorite ORM / MVC web framework here – I’m not biased against any, I just happen to like Ruby a great deal). Where Ruby and Rails fall behind is on performance. A Rails server uses up huge chunks of memory, and this limits the number of requests it can take at one time.

When Rails runs in development mode, you can watch the log files and take careful note of the database calls that are being made. This feature allows me to look at each of the requests being made one by one and determine that – if somewhere in all those layers that a web app might have – unnecessary hits to the DB are being made. It also allows me to grab those DB queries and throw them into an EXPLAIN statement so I can determine if indexes are being used. Then I can simplify my Rails code and optimize my DB queries as necessary, to maximize the speed of each of those individual AJAX calls.

Why not use more caching? It’s a great way to speed up a web app!

Caching is great, and Aethora takes advantage of HTML caching as well as memcached for caching database-backed objects in memory. However, during a battle, many of the stuff is just changing too fast to bother caching. The battle log is just written as row after row of minimal data, and calls only need to grab the last few rows at any given time. The stats on mobiles are constantly changing during a battle.

The battle log is an example of where the ORM model gets in the way a little. Well, I should say – it gets in the way when it comes to reading the battle log table’s rows – it’s very handy for making table writes easier to code. When reading the battle log, it’s just as easy to go from database row to json as it is to go from object to json.

Items, skills, and actions, however, are all stored in the database as objects, and are more complex to work with. They are great examples of where using class-based objects really makes the code so much cleaner. Since they are fairly static, they get cached with memcache. That not only saves us the extra database call, it also saves the extra processing time it takes the Rails server to transform a database row into an object (because the memcached server in this case is storing a marshaled Ruby object).

And finally, as a major bonus – I was actually able to take some of those simplified queries and plug them into a few lines of PHP. Yeah, that’s right – I can run both Rails and PHP on the same web server – there’s no law against it! So, for example, the battle log – these requests are made constantly while an NPC is taking their turn, so the player gets the impression that they are watching the turn unfold in real time. There is nothing secret in a battle log – no user information or anything. It really is just about grabbing a couple rows of log data and a couple fields of mob data. Using ApacheBench to do a quick speed test, the PHP calls are a little faster than the Rails calls to get the same data. Punch up the number of concurrent connections, and you really start to see a difference: with 5 concurrent connections, the PHP script time was about 2/3rds that of the Rails time. The number of simultaneous Rails processes is limited by memory usage, whereas Apache can fire off PHP scripts by the gobs.

One important thing to note if you’re going to run multiple server-side engines to respond to AJAX calls: be careful not to violate same origin policy. If you need to run different server-side code under different subdomains, make sure to set document.domain (as described in those articles). I’m using the wonderful passenger module, which allows me to run Rails straight out of Apache. In this setup, Apache can bypass Rails to get anything out of the public directory (for images, CSS, javascript, etc). If it finds a php file in the public directory, well then, it’s business as usual. That way I can have: http://mydomain.tld/something/from/rails and http://mydomain.tld/minicall.php – same domain, different server side processing!

That’s it for the performance improvements – I’ll come back and give you another article that focuses on the point-and-click interface improvements.

1 Response to “Rewriting Aethora's Battle Interface - Part 1”

  1. gaming blog Says:

    hello, this is my first time i visit here. I found so many interesting in your blog especially on how to determine the topic. keep up the good work.

Sorry, comments are closed for this article.