Starting Point for a Puzzle Game Built with XSLT, SVG and Javascript
This one's for the casual game developers and the SVG folks I've been working off and on (okay, mostly off) on a simple puzzle game done in SVG and Javascript. I started on it almost a year ago and the idea was to just put up something simple as a guide to building SVG games. I got something that sort of worked pretty easily, but each time I added a feature it seemed like I had to rewrite the whole game. I guess that's just part of developing in a green field. One of the issues that bothered me most throughout the work I did was that I was transforming level files from a generic XML to SVG in the browser. I knew that every browser that downloads the level would perform the exact same transformations and every user would have to wait a few seconds while it happened. I also had to deal with the rather hairy Javascript code that handled those transformations and debug it every time it broke on one of the platforms I'm trying to support. Not every browser has a debugger as accessible as Venkman (and at the time I don't think there was a Venkman version for Deer Park). I'd rewrite the code, get a little more capability in it and tweak it for a day or two, then shelf it again until Jeff or Candace bugged me again to stop talking about it and get something done. Okay, so I finally did another rewrite on it a month or so ago that fixes the issue that I'd avoided for so long. See, I'd wanted to keep it in just Javascript and SVG since I thought that made things simpler. There's no build step that way and the design of the game is more obvious. Scripting languages don't generally need the kind of development pipeline that compiled languages do. In C or C++ the source code has to be built before results can be seen. In Javascript or HTML, the source is the executable. When XML is used to store information though, there's always some kind of interpretation that happens to display it. That can happen right when it's accessed (like viewing an SVG or XHTML document) or there can be interpretation first that creates another document that's actually viewed. The latter transformation can be done with XSLT.
I was resisting XSLT. Using XSLT I can transform the level files once each on the server (or before uploading to the server) and have each level turned into it's own standalone SVG document. That SVG document only knows how to play one level of the game, so it's smaller and simpler than an SVG document that knows how to load, parse and play any level of the game. For a proof-of-concept, what I have now seems okay, but I have to explain more since the server is doing some of the work.

How the Game Works

As it stands now, version 0.3 of Toggit (the game) works like this for a player:
  1. Visit the page with the list of levels (instructions may show up here one day too)
  2. Click a link to play one level of the game
  3. Each level has a simple puzzle to solve, once it's solved the status box tells you it's solved (there's no way to advance to the next level from in-game yet)
  4. Back up and play another level
The puzzle is just a matter of turning all the toggits green by clicking on them. Each time you click on a toggit, that toggit and all it's neighbours change state. When you mouseover a toggit, it will react and so will it's neighbours. The level is solved when the text at the bottom says "Level Passed." Take some time to try it out now. On the server things work like this (links here go to source code):
  1. toggit.php gets a request with no valid level specified, so it looks at levels.txt and lists any valid game level documents that it finds in there
  2. toggit.php gets a request with a valid level specified, so it outputs the contents of the SVG file
Step 2 on the server (outputting the SVG file) could have been done by transforming the level on the server when it's requested, but these levels can be entirely resolved before that time. There's no need for repeatedly transforming the same XML here. If the levels could be dynamically updated then a transform step would be warranted and pretty simple to do on the server. As it is I have Instant Saxon at home so I just transformed to SVG then uploaded the files. That makes the PHP file easy to explain here, but there's a whole lot of room for improvements in this step. I have a lot of ideas but they're hard to explain without examples, so I'll have to wait until I can make those examples to show. Now that it's clear what's happening, here's a little more detail on how each part works, with snippets from the source.

Into the Game Components - Step-by-Step Guide

  1. toggit.php: the Game Intro and Container (source)
  2. levels.txt: A list of available levels (source)
  3. toggitLevel3.xml: Example of the level files (source)
  4. toggit-level-transform.xsl: The transformer and template (source)

toggit.php: the Game Intro and Container

I explained basically everything that toggit.php does above. Here's a walkthrough of the tricky bits. $filename = 'levels.txt'; // levels.txt contains a list of relative (filesystem) paths to levels that will be read into an array ... $file_content = file_get_contents($filename); $levels = explode(",",$file_content); This reads the text file levels.txt in to a variable then splits that string into an array of strings called $levels. I could have read an XML description of levels instead or kept the levels in a database. This is the direction I'm going to move in since more information than just the file name will be needed for a complete game. // check if the level was passed in and if it's a number in the range 0 ... number of levels (level 1 is index 0) if (isset($_GET['level'])&&(is_numeric($_GET['level']))&&($_GET['level']>=0)&&($_GET['level']<count($levels))) { ... This code checks to see if the URL from the browser includes the part "?level=#" where # is a number that's valid for the levels that exist. The levels are indexed from 0 to the number of levels-1. The code checks if the level variable is there (isset()), is a number (is_numeric()) and the range it's in (with the >= and < parts). It might look like overkill since all these URLs come from inside toggit.php anyway, but remember that anybody can type in whatever URL they want. This is part of scrubbing user input, but I don't know if it's perfect. $info = @stat($level); // make sure the level file is really there if($info) { header("Content-type: image/svg+xml"); $output .= "<" . "?xml version=\"1.0\" encoding=\"utf-8\"?" . ">\n"; $output .= file_get_contents($level); }
stat() gets information about a file. The @ is a shortcut to prevent it from outputting some error message to the viewer if something goes wrong. If the file exists and is readable then $info will have some information about the file, I don't care what that information is here, just that the call succeeded. That should mean that file access is safe. If the stat() call failed then I guess the user gets a blank page. If it works then the header for SVG content is sent and an XML prolog is placed in the output buffer. When I code PHP, I usually use a variable like $output as a simple way to collect up all my output then I call printf() or echo just once and send the whole document. This way the user doesn't get half the page then wait on the server for the rest (in general that is). I could get the same result by turning output buffering on. The level SVG document is read into the output variable with the call to file_get_contents().
$output = '<html><head</head><body><div><ul>'; $level_index = 0; // no level requested, make a list of links to each level foreach ($levels as $level) .. If no level was specified then an HTML document is built in the variable $output. The foreach loop iterates over the level file names and emits a list item for each level. $info = @stat($level_filepath); // make sure the level file is really there if($info) { $output .= '<li><a href="' . $level_serve_url .'?level='. $level_index . '">Level ' . ($level_index+1) . '</a> last updated ' . date("F j, Y, g:i a",$info['mtime']) . '</li>'; } Each level is numbered by it's position in the list or array, not by it's name. This is more important than it sounds. I've done it this way so as not to expose information about the contents of the server filesystem to visitors. It's hidden if you don't count this post where I tell the world where to find everything... If you look in my example you can read the files, but there are ways to put the level files outside the directory tree for the webserver. Then it can be possible for the PHP interpreter to read the contents of the file through a call to a function like stat() or get_file_contents() but the webserver won't allow anyone to just enter a URL and see the contents of the file.

levels.txt: A list of available levels

Here is list.txt in it's entirety: deploy/toggitLevel1.svg,deploy/toggitLevel2.svg,deploy/toggitLevel3.svg For this proof of concept I just read the level file names in and present a list. For a complete implementation (as I mentioned earlier) I'll need more detailed information about the levels. It could be XML or a database table or even a layer that uses one or the other underneath without the main game code knowing the difference. The kinds of information that would end up in here would be level names, difficulty settings, high scores, and maybe even some function names if they were customizable (instead of being hardcoded in the XSLT).

toggitLevel3.xml: Example of the level files

The game levels use a namespace that has no DTD for now, xmlns:tg="" version="0.3" This hasn't caused any issues for me, but I will need a DTD or schema to validate against if I ever get to the point where there are other consumers of the level files. Other consumers could be middleware for building level files or another transformer that makes a DHTML or XAML version of the playable game. Also, I think my use of namespaces has been pretty sloppy here - this is an artefact of all the rewrites this code went through. Don't assume that the 'tg' is necessary or correct everywhere that I've used it. The root node is arbitrarily called gameboard. The gameboard node contains the toggits and levelscripts nodes. <tg:toggits> <tg:toggit id='p1' x='135' y='145' tg:state='up' stroke-width='10' /> <tg:toggit id='p2' x='785' y='145' tg:state='up' stroke-width='10' /> <tg:toggit id='p3' x='352' y='383' tg:state='up' stroke-width='10' /> ... <tg:toggit id='p7' x='135' y='860' tg:state='up' stroke-width='10' /> <tg:toggit id='p8' x='785' y='860' tg:state='up' stroke-width='10' /> </tg:toggits> The toggits node contains a list of toggit elements. Each toggit has an id, position and starting state of up or down. The toggit elements are used later by the XSLT to make svg:use elements (which I'll refere to as toggits in the context of the playable game). The id, x and y are transferred to the svg:use elements by the XSLT. Then the Javascript that makes the game playable refers to each toggit by its id. The tg:state attribute controls whether the toggit starts up or down. This requires a little explanation. Here I finally get to vent about why I was initially so upset about the implementation of SVG in Firefox. Hold on, I'm going to get a drink... Firefox doesn't do SVG filters. That means that I can't make my really pretty floating coloured glass thing work with the native SVG implementation in Firefox 1.5. The toggits in this game were originally supposed to be these lit up floating pretty flowerlike things that could float high or float low (roughly the same filter with different settings for feOffset). When you pushed one down, it's neighbours would pop up. I thought about ways to add animated effects to this with SMIL and load a nice backround (with feImage) that could be altered by the lighting. The idea wasn't a complex game, just a pretty game that could show people how nice SVG could be.
Firefox sunk that idea. So I started looking for other things that would be obvious and intuitive to a player and trying to figure out how to properly serve something up for the different user agents and all that. Of course I didn't sit down and spend a week working on this full time. In case you haven't guessed already, I have other things I'm obliged to do during the day besides building web sites and SVG demos. I messed around with using Adobe SVG viewer in Firefox 1.5. I tried simulating the lighting effects produced by filters with gradients in Firefox. In the end I decided that the lighting I had wasn't enough on its own to give the player an idea of what's going on. Okay, that's enough complaining from me. If it were that important to me I'd quit my job and commit my time to volunteering to test and work on SVG filters for the Mozilla foundation. So now in my game the states "up" and "down" mean "red" and "green". Pathetic, I know. tg:levelscripts function getNeighbourList() { var toggitList = new Array(); toggitList["p1"] = ["p3"]; toggitList["p2"] = ["p4"]; toggitList["p3"] = ["p1", "p4", "p5"]; toggitList["p4"] = ["p2", "p3", "p6"]; toggitList["p5"] = ["p3", "p6", "p7"]; toggitList["p6"] = ["p4", "p5", "p8"]; toggitList["p7"] = ["p5"]; toggitList["p8"] = ["p6"]; return toggitList; } The levelscripts node contains Javascript code that will be inserted into the game level. Right now this is just a function that tells which toggits are neighbours. The getNeighbourList() function is called by code embedded into the XSLT. The code from the XSLT will be copied into every level. This looks simple, but it really shows that this can be used to start building a framework where level files really contain everything that any user needs to know about a level in the game. This is a very basic example of the Inversion of Control design pattern. Just create a Javascript interface that the level has to implement for each of the potential consumers. The functions could include things like
  • getting information about resources the level needs (so the server could optimize the way levels are compiled and served to the user),
  • handling special items or events that are unique to the level, or
  • providing screenshots for the user to see what's coming up in the level
  • sending scores back to the server

toggit-level-transform.xsl: The transformer and template

The XSLT file is rather lengthy, but most of it is just copied straight into the output SVG. Without the template for tg:gameboard, it's under 40 lines, and some of that is probably unnecessary. There are three templates in the transformation:
  • <xsl:template match="tg:gameboard">
  • <xsl:template match="levelscripts">
  • <xsl:template match="tg:toggit">


The template for tg:gameboard is basically a copy of a working game level. The nice thing about this strategy is that you (as a developer) can create one working level then parameterize it to make many levels. The shitty thing about this is that you (as a developer) will have a rotten time trying to remember to copy changes that you've made as a result of debugging back into the XSLT file. And of course any level you're debugging in will most likely exist in an output directory that gets clobbered when you next build. Be careful. If you figure out a good way to fix this in the development pipeline then let me know. The parts of the gameboard that are replaced with pieces from the level look like this: <xsl:apply-templates select="tg:levelscripts" /> This calls the template that match the tg:levelscripts tag and inserts the output from the template at this point in the XML DOM being created. For more information, have a look at apply-templates in the XSL Transformations spec.


<xsl:template match="levelscripts"> <xsl:copy /> </xsl:template> That's it. The contents of the tg:levelscripts node is copied into the output document.


<xsl:template match="tg:toggit"> <xsl:choose> <xsl:when test="@tg:state='up'"> <!-- up is red --> <use id="{@id}" x="{@x}" y="{@y}" stroke="green" stroke-width="{@stroke-width}" tg:state="{@tg:state}" fill="red" xlink:href="#toggitShape" onmouseout="toggit_mouseout(evt)" onclick="toggit_click(evt)" onmouseover="toggit_mouseover(evt)" /> </xsl:when> <xsl:otherwise> <!-- down is green --> <use id="{@id}" x="{@x}" y="{@y}" stroke="red" stroke-width="{@stroke-width}" tg:state="{@tg:state}" fill="green" xlink:href="#toggitShape" onmouseout="toggit_mouseout(evt)" onclick="toggit_click(evt)" onmouseover="toggit_mouseover(evt)" /> </xsl:otherwise> </xsl:choose> </xsl:template> The code for tg:toggit is a little more complex. It creates an svg:use element for each tg:toggit node found in the source level XML file. Parts that look like id="{@id}" mean that the value of the id attribute in the source should get copied into the id attribute of this element. The xsl:choose, xsl:when and xsl:otherwise deal with the initial value of the tg:state attribute on the toggit. Remember that this is only the initial state of the toggit. When the game is being played, the SVG agent has no idea that this XSLT even exists. The state at runtime is controlled by Javascript. This template show how easy it is to create an SVG document from some XML. I'm doing this for a game, but the logic could easily be adapted for many other purposes (leave a comment if you've got one, I'd like to see it). If you want more explanation, I've also done this in a simple HTML example and an SVG chart made from static data. I also did something with my simulated lighting example where I went into a lot more detail on how I ran the XSLT transform on Windows. Finally, in case you skipped to the end and missed it, here's the game and here's some source.
Your rating: None Average: 1.7 (3 votes)

[...] Rob also has a great post on this topic. [...]

Hey can u guys email me a tutorial on how to make web based sapce games or stuff like that

Hi Dave,
I'm working on some more SVG and DHTML stuff and I'll post it here when I get something worth showing. It might be a while though, E3 is next week and I've got a lot of other stuff on the go.

hey guys,do you have some web match picture game code with java script