Custom HTML Tags

I have to mention that “Custom HTML” is really an oxymoron. When you start adding tags that aren’t part of the official standard, then you really have an XML document that the browser attempts to interpret as HTML. Think of this as a technical exercise. Two things led me to this exercise.

New HTML 5 tags

I’ve been doing a lot of reading about HTML5 and some of the new tags that are specified (my favorite such article is here). In this article, Mark Pilgrim suggests going ahead and using the new tags now, even though browser support is limited. Most of the new tags don’t display as anything special, and are only semantic (such as the header, footer, article, or nav tags) and will render the same as a normal span tag. And just like a span tag, you can apply CSS to them as you wish. Except for Internet Explorer, which requires a little JavaScript tricker to make it work:

 
John Resig goes over this trick in detail in one of his excellent blog postings.

Evented Programming

The second piece of this puzzle was an article/video that came along with the 1.4 release of jQuery, where Yehuda Katz discusses his approach to creating widgets on your web pages. He reasons we should make these widgets to function as if they were built into the browser in the first place. For example, say you’d like a tabbed control on your page. The usual approach would be to draw the individual tabs and panels as divs or spans, and attach code to each tab to hide and show their associated panel when clicked. Something like this:

Continue reading “Custom HTML Tags”

Spawn of Satan

Or spawn of me, at any rate.

Events in MFoN take place in the form of “Encounters”. There are combat encounters, store encounters, conversation encounters, and so on. Each 32×32 pixel square in the game can potentially contain any number of encounters (it’s the same “grid” on which the players move). Each encounter in each square can have a different chance to appear. For example, some of the Haystacks in the old version had a 10% chance to cause a sneezing fit when entered or searched, and a 0.0001% chance of giving you a Vorpal Needle (a particularly nice item). When checking an area, the game rolls a random number, then goes to get any encounters that have that high a chance. One of the resulting list is picked at random. So if the “roll” was 5.23, you would get a sneezing fit. A roll of 11.777 meant you got nothing, and a roll of 0.0001 or less meant you had a 50/50 chance of getting the Vorpal Needle or a sneezing fit.

With the changes to combat, some new problems came up. Your opponent(s) would need to show up someplace accessible on the screen. The initial solution was to let the combat encounter specify a distance at which the enemy would appear, and let the game find something accessible at that distance from your character, on whatever square he/she triggered the encounter. Unfortunately, “accessible” wasn’t necessarily anywhere close. If you were standing next to a wall, it could put the enemy on the other side of the wall, even though to get to you it would have to step 40 paces.

A prime example is the “Rats in the Garden” quest. It’s a simple kill-the-rats quest, where you’re supposed to hunt down and kill rats infesting the garden. It would make the most sense for them to therefore appear in the garden somewhere, but they were showing up on the other side of the wall, inside the fortified building, or behind the well…usually anywhere except the garden.

So I added Spawn Points. Now I can specify exactly where a particular actor can pop up on a given map. I can give the rats various spawn points in the garden, so that when they spawn, they’ll appear in the garden where it makes sense.

I can do other neat stuff with this too. If you’re walking through a dangerous town, I can have spawn points for difficult-to-reach snipers, which might not be anywhere near you, but could have a clear line of sight. The sneaky possibilities are tantalizing. And the action looks a lot better, too.

Head in the Clouds

There’s something I’ve always wanted to do with Muties, but could never figure out how to do.

I wanted to be able to have some graphics on top of the characters. Like semi-transparent clouds scudding over the characters’ heads, open windows, or maybe some fencing the player visually walks behind. The problem is that once you put a graphic (or any HTML element) in front of another, the one you covered is isolated from the mouse.

Let me give an example: On the screen you have noble Bob, minding his own business. Bob is a 32 x 32 pixel graphic…specifically he’s an image (IMG) tag. That image tag has events for mouseover (“display the tooltip”), mouseout (“hide the tooltip”), and click (“pick Bob to talk to him”). Now we draw a chain-link fence in front of him by adding another image tag that covers Bob, and has an appropriate cross-hatched pattern to it. You can see Bob through the fence, but when you move the mouse over Bob, you’re actually moving it over the chain-link fence covering Bob. While the fence graphic displayed might very well be mostly transparent, the element itself is solid. The fence is getting the mouseover, mouseout, and click events now…not Bob. Now of course you could monitor the mouse coordinates, run a few calculations, and search through elements on the page to find something besides the fence that is in the same place (IE: Bob). But that’s ugly, potentially painful, and certainly messy. Then you have draggable items. You’d have to do that mess to find them, then update their position every time the mouse moved.

But today I had a brainstorm. I added another image, which I dubbed “Clouds”. Then I created a map element, which is used to make an image map. A map tag contains any number of area tags, which define a clickable region on the image to which the map is attached. In my case, I left the map empty.

When an actor (character) or tooltip is added to the map, I know their coordinates. So instead of hooking up a tooltip to the image of the actor (or a blank spacer graphic for raw tooltips), I dynamically create an area element and insert it into the map element. The area element gets the mouse events. The new area event is associated with the actor, so that if the actor is moved, it’s fairly trivial to move the area tag also.

Really that’s all there is to it. The area tag’s mouseover triggers the appropriate tooltip, and the area’s click event triggers the same call the actor click did. To the user, it just seems like they’re clicking on the actor like they were before. But now I have a cloud layer that can contain some interesting effects.

Oh, and to solve the drag and drop problem of items, I cheated. Store items work like loot items now, in that a container appears on the screen, and you click on that to open a window containing the actual items. 🙂

XML vs. Databases for Static Content

With the new way conversations are handled in Mutant Freaks of Nature, I had to write a new editor to manage them. The conversations are actually structured in a classic tree structure, with each NPC branch leading to any number of potential player responses. The player responses, in turn, can each lead to a single NPC branch, or can jump to another branch anywhere else in the tree.

The original version of the conversation trees were stored in two MySQL tables:


tbl_npc_node
:

npc_node_id parent_response_node node_content
1 0 Hi, my name is Bob!
2 2 Nice to see a friendly face.


tbl_response_node
:

response_node_id parent_npc_node node_content
1 1 Yeah? Who cares?
2 1 Hey, good to meet you.

For the astute among you, yes, it does look like I could have used a single table to store both types. I haven’t included other columns unique to each type of node, however. The conversation the tables above represent would go something like this:

Or the other way…

Not a lot of difference, but it may give you an idea of the structure. The problem was that changing one small piece of the conversation changed a row in the database. This meant a call to the server and database hits every time a piece was changed. The structure also meant that building the tree to work on the conversation as a whole was a pile of recursive queries that had to be reassembled into a tree-like structure and edited.

After fixing yet one more problem with the tree editor, I decided there had to be a better way. I reasoned that there had to be a simpler way to store and edit data with that kind of structure. Sometimes we overlook the simple ways, and make things harder than they need to be. The answer to my dilemma was simple XML:

Here’s an early bit of XML from the Tutorial conversation. All the structure I need is there, and without all the hopping about in tables. To update the conversation, I change the file in my favorite XML editor and upload the whole thing.

The only remaining question is performance. A static file sitting on the server is always more efficient that grabbing it from the database, and that’s the catch here. This works well as long as the XML file isn’t being actively modified by an editor, which is the case with conversations. There is some overhead from reading the XML file and navigating to the correct node, but it’s actually pretty minor compared to nested database calls.

Now that that’s out of the way, it’s back to finishing the tutorial.

Mutant CSS Sprites

“CSS Sprites” are one of those things that’s been around for a little bit, but that I’ve only recently read about. Learning about them inspired a slap-myself-on-the-forehead moment. Why hadn’t I thought of that?

“CSS Sprites” are one of those things that’s been around for a little bit, but that I’ve only recently read about. Learning about them inspired a slap-myself-on-the-forehead moment. Why hadn’t I thought of that?

Mutant Freaks of Nature uses a bunch of little icons in the game. There’s several arrows…for example:

Up-Left Arrow Up Arrow Up-Right Arrow

Just the nine navigation icons are 4,663 bytes. The complete collection of icons used on the new front page of the game counts up to 14,702 bytes. More important than the size is how it clogs up the connection. Each graphic downloaded comes with its own connection between the browser and the server, its own headers, and its own cache management. Also, consider that browsers are generally limited to two connections to a server at the same time. The base set of 22 icons requires a stack of round trips to the server before the page can finish loading, and they aren’t the only things being downloaded.

Wouldn’t it be nice if we could download them all at once? Something like this:

Tile graphic

This contains all 22 icons (14,702 bytes individually), but only weighs 11,260 bytes. And it would be a single download! That would save quite a few headers. Fortunately, CSS gives us a way to manage this.

The typical html for one of the icons is something like this:

CSS can help. We create a style class:

Now we can do this a little differently:

The style makes the image 16×16 pixels and puts the tile graphic in as the background. By default it will be set in the upper-left corner of the image. The result will be the upper-left arrow displayed in the image tag. “blank.png” is needed for Firefox, since if there’s no valid image Firefox will completely hide the image. Of course, with the source of the image being just a placeholder now, maybe we don’t really need the image itself:

Yep, that gets you the same result as the img tag, with one caveat. It won’t “flow” like a series of images will. It can still be positioned absolutely, of course

To get different icons in our sprite, we just shift the position of the background graphic with custom styles, like thus:

That displays the little binoculars as the graphic. The background is moved 16 pixels up and left so that the div is framing the binoculars. The rest of the image is hidden.

And that’s the gist of how it works, except for a Mutation we’ve given it. The game engine automatically does some processing on information returned by the server, so we’ve added a little more to that, resulting in a fancy shorthand for our sprites:

The sx and sy custom attributes are converted into the background-position attribute automagically. It might be worth mentioning that at any point we can modify the sx/xy of an existing icon or graphic with a simple command. We could even put that on a timer

I’ll let you figure out what that might mean. 🙂