An Original Approach to Web Game Development Using SVG

Keywords: SVG, browser game, Inkscape, Java-Script, DOM, json, PHP

Olivier Cueilliez


Abstract


Since the raise of the Internet era, many browser-based on-line games have been created. When these games were developed in respect to Web standards, these have been limited by the inherent stateless and text-base nature of the Internet. Hence, these games are turn by turn based, graphically limited and hardly compatible from one browser to another; these are the reasons why developers usually prefer to implement browser games using plug-ins.

While standards are not ready for real-time browser games yet, it is already possible to provide better graphics for a better gaming experience. Today, SVG is well supported in all major Web browsers, and is a stable standard compared to HTML 5.

This paper presents an attempt of creating a browser game based on SVG. Some SVG games can already be found on the Internet [R1] [R2] but these are just simple games and are not massively multi-players. During the process, the question of how to leverage SVG at different steps of the development was raised. Many different technologies were needed, but SVG remains the guiding principle throughout the article.

The game itself is supposed to be a strategic/role playing game; turn by turn based where players can live adventures and build civilizations in a fantasy world.

The work related to this article was done as a hobby and is the result of 2 years of development, mainly over nights and week-ends.


Table of Contents


1. Overview
2. Using SVG for the Design of the Game
     2.1 Creating Maps
          2.1.1 Map Requirements
          2.1.2 General Map Generation Strategy
          2.1.3 Processing SVG Layers and Generating Maps
          2.1.4 Problems and Future Work on Map Design
     2.2 Creating Other Resources
          2.2.1 Drawing SVG Resources
          2.2.2 Exporting SVG Resources to JSON files
          2.2.3 Problems and Future Work on Resource Design
3. Creating a game graphic engine with SVG
     3.1 Game User Interface Development With SVG
          3.1.1 Integrating SVG Components into the Game UI
          3.1.2 SVG User Interface Component Samples
          3.1.3 Problems and Future Work on UI Components
     3.2 Game Graphic Engine Development With SVG
          3.2.1 Problems and Future Work on SVG Game Engine
     3.3 Performance considerations
4. Conclusion
5. What's next?
Bibliography

1. Overview

In this article, I will first describe different approaches to handle SVG resources with Inkscape and PHP at design time:

I will then propose strategies that use SVG to render the user interface and game environment in the browser:

In the course of the article, I will point out different problems found while dealing with the SVG standard and SVG tools. I will give recommendations about what I believe is the right approach for designing a browser-based game using SVG. I will also point out inherent performance problems and how, again, SVG provides enough flexibility to solve them.

An SVG game prototype has been already built but is not playable yet (Runes and Relics Prototype). This is only provided as a demo.

2. Using SVG for the Design of the Game

Most of the development effort for a game is often related to resource design. Creating a game based on SVG is not different from creating any other games on that matter. And as often in the development industry, one of the main problems is to find the easiest and the fastest way to create decent tools for the design of resources. The term “resources” mainly includes maps that define areas where the game takes place; graphics such as environment elements (trees, bushes, etc.), units (characters, monsters), buildings (towers, houses, ruins, etc.), portraits and so forth.

The following sections describe different ways of defining, processing and exporting game resources with SVG being the main technology used to handle data.

Map resources require special attention because they are critical for a strategic game and also because everything else is built on top of them.

After exporting resources, the final storage formats were designed for easy and fast access and for a straight forward rendering at run-time.

Creating Maps

Map Requirements

Maps are very important for a strategic game. Maps determine the main strategic elements. As the atmosphere of the game was already pretty much defined, requirements that would model maps became obvious:

General Map Generation Strategy

Creating a tool to design map is an extremely time-consuming task. It quickly appeared that using an existing drawing tool was probably a cheap way and a good starting point to design maps. Patches of colors can be used to identify elements. It was also quickly found that a drawing tool specialized in vector images would be more flexible than a drawing tool for raster images: A few tests with Inkscape and the Gimp showed that manipulating shapes (copying, pasting, moving, rotating, enlarging, etc.) was way easier with Inkscape than with the Gimp. So it was decided to use Inkscape to create maps. The next step was to setup a series of color conventions and their meaning in the different layers of the map. What was not obvious was what type of map elements would need to be define in what layer. Layers (SVG:g elements in Inkscape) were unavoidable to ease the processing of colors.

The definition of the following different layers and the chaining of the map processing steps are the result of numerous attempts to create consistent and strategic-game-compliant landscapes with SVG. A layer corresponds more or less to one step of the map generation process:

Layer 1: This is the background layer - If nothing else is defined inside the upper layers at a given pixel position, the blue color of the background layer will be used and a square of ocean will be created.

Layer 2: This is the ground types and relief types layer. It is a bit confusing to handle at first because a set of colors is defined for every existing ground type. Each color defined for a ground type corresponds to a different relief type. Not all relief types are defined for each relief types. For example, it is not possible to have a very uneven relief type for the desert ground type. The following table shows the list of colors per ground type/relief:

groundtypes_colors.png

Figure 1: Color Codes for Ground Types and Relief Types

Layer 3: This is the altitude layer. To simplify the design of maps, only 6 levels of altitude are defined. More could be easily added if a map designer wanted it. Every level corresponds to a fixed altitude. Every level increments the altitude by 10, starting at 0 for the “Flat” altitude, up to 50 for the “mountain” altitude”.

relief_colors.png

Figure 2: Color Codes for Altitude Levels

Layer 4: This is the rivers and lakes layer. It needs to be after the altitude layer because lakes and rivers are flatten and this is done according to the altitude. Only 2 colors are defined for this layer: One for lakes, another for rivers.

water_colors.svg

Figure 3: Color Codes for Waters

Layer 5: This is the starting areas layer. Players cannot build in some map areas but can in some others. This topic is not related to SVG and will not be discussed here. But this last layer is also used to generate random details on maps automatically, with no additional work from map designers. These random details are aimed at breaking the monotony of the landscape.

Processing SVG Layers and Generating Maps

A PHP script is used to process the different layers of a map created using Inkscape. The main goal of the script is to convert every pixel of every layer into a square with an altitude and a ground type. Each corner of a square may have a different altitude than the other corners of the same square if the square is part of a mountain or hill slope. The altitude goes from 0 (sea level) to 63 (highest mountains) which is enough to create an interesting relief from a strategic point of view. Squares are grouped in 2-dimension areas of 64 x 64. Each area is stored in the same binary file with the .rra extension (referring to the name of the game, “Runes & Relics Area) in a nested folder structure. For example, area 001,001 (containing squares from 64,64 to 127,127 in a map) is nested as follows:

map_folder_structure.png

Figure 4: Map Files Nested in Folders

This structure has many benefits:

The PHP script is run using a command line (this needs PHP-CGI to be installed). The process of converting a map into many area files is done through the following steps:

  1. The Inkscape file containing the drawing of a map is converted to raster images. The PHP script processes the SVG file by hiding or displaying layers one by one (the background layer is always part of an image) and then invoking Inkscape using a command line to export every layer as a raster image. In the following example, a map with 256 x 256 pixels is exported to PNG:
    		inkscape working_map_000_000.svg --export-png=map_ground_type_000_000.png --without-gui  --export-area=0:7936:256:8192
    		

    The result of the operation is showed below:
    Ground and Relief types Relief Rivers and Lakes
    map_ground_type_000_000.png
    map_relief_000_000.png
    map_misc_000_000.png

    Table 1: Exporting SVG layers to PNG files

  2. The Ground types & Relief types layer is processed. Several sub-steps are performed here:
    1. As pixels are processed, new file areas are created
    2. The ground type (forest, plain, etc.) is extracted from each pixel (corresponding to a square in the game map) and is stored in the corresponding area file
    3. The relief type (smooth, uneven, etc.) is extracted from each pixel (corresponding to the same square in the game map as above) and is temporary stored in the same area file. This piece of information will be useful when the relief is effectively processed at step 3.
    4. All non-ocean squares are set to an altitude of 1. When rivers are processed at step 3, river square's altitudes are decreased by 1 for a better visual effect (this creates beds of rivers). Ground square corners next to the ocean are not set to an altitude of 1; this gives a shoreline effect.
      step1_coast.png
      All ground square altitudes are set to 1 and ground squares next to the ocean are processed a bit differently

      Figure 5: First Step in Landscape Generation

  3. The Relief layer is processed. This is the most complex process, but only one operation is performed: Create hills and mountains. As each color corresponds to a given altitude, the script detects changes between colors on the map, that is between altitudes, and then build slopes around the colored patch edges. The relief type (smooth, uneven, etc.) is also used here to create more or less steep slopes. As showed on the diagrams below, the relief type also determines how far from the edge the slope should be calculated. If this slope goes too far or meets the ocean, it ends, creating a cliff.
    relief_types.png
    Different slopes are applied depending on the color of the relief type that the script detected.

    Figure 6: Relief Types

    step2_relief.png
    If the relief goes out of the ground scope defined at Step 1, it is not processed

    Figure 7: Result of the Relief Generation Step

  4. The Lakes & Rivers layer is processed. After step 3, the main relief is defined and it is easier to add lakes and rivers on top of it. Besides the processing of pixels to create lakes and rivers, many other processes happen to break a bit more the monotony of the landscape. The following sub-steps are performed:
    1. Random lakes are created. These lakes are smaller than the ones manually created with Inkscape. With a set of parameters, it is possible to control the number and the average size of the lakes to create for a map. In the future, it would also be possible to change these parameters per group of areas to create more or less lakes in different regions of a map. Creating a lake is simple: This is done by applying a flood-fill algorithm at a random pixel to create a lake square and then by applying a decremented chance that surrounding pixels should be lake squares too. The patch of color corresponding to each lake is merged with the existing in-memory raster image of lakes and rivers layer so that the same process is applied to both manually-created and automatically-created lakes.
    2. Lakes are created in area files by processing the lake color in the raster image loaded in memory. A lake may be placed on the slope of a hill or mountain, but this is fine: The algorithm just takes the lowest altitude of all squares where the lake should be created, decrement it by one and flatten all lake squares to this altitude, creating a depression in the slope. Finally, the borders of the lake are made smooth. If, during the process, it happens that a square of a lake is defined on an ocean square, the lake is entirely canceled, be it a manually or a randomly created lake.
      step3_lake1.png step3_lake2.png

      Figure 8: Examples of randomly generated lakes

    3. Rivers are created in the area files by processing the river color in the raster image loaded in memory. The altitude of river squares are lowered by 1. If a river pixel is defined on top of an ocean square, the river square is not created, the square remains an ocean square. Unlike lakes, river borders are not made smooth. This gives a “river bed” effect.
      step3_river1.png step3_river2.png

      Figure 9: Rivers and Lakes Generation

    4. Additionally, random knolls are added to break once again the monotony of the landscape. Predefined knoll patterns are used, randomly rotated with a maximum altitude that is set according to the relief type for every small hill. If a knoll square is defined on an existing lake or river square, it is ignored, thus, creating a cliff
      step3_river_knoll.png

      Figure 10: Example of a randomly generated Knoll

  5. The Starting areas layer is processed. This is the last step, and this is where the final details are added to the existing areas. Many small algorithms are used here, and the order in which these are run is also important:
    1. Oceans are finalized. Now that shorelines are well known, ocean squares are defined as shallow if they are close (2 squares) from a shoreline. Otherwise, these are defined as deep. This process takes cliffs into account
      step5_shoreline.png
      Deep and shallow ocean squares are processed depending on the surrounding relief

      Figure 11: Processing Oceans

    2. Forest squares are processed. For each forest square, 4 trees are randomly created for a nice rendering effect.
    3. Just like the way random lakes were created at step 4, random woods are also created in areas with almost the same algorithm
      step5_wood.png

      Figure 12: Example of a Randomly Generated Wood

    4. Ground details are added. This sub-step is not completely implemented yet, mainly because of the lack of graphics to render. A small set of predefined details are used per ground type, for example flowers and mushrooms for plain and forest ground types.

Problems and Future Work on Map Design

During the implementation of the map processing script, many problems have been found, but none of them could not be worked-around or were serious enough to be fixed:

Creating Other Resources

Be these other resources environment elements (trees, bushes, plants etc.), buildings (houses, fences, ruins, etc.) or units (characters, monsters, armies etc.); drawing and exporting these resources from Inkscape so they are ready to be sent to a web browser is fairly simple and straight.

Drawing SVG Resources

Just like maps, drawing SVG resources is done using Inkscape. Drawing with Inkscape would be technically quite simple, given that the user interface is very friendly, but a few rules are needed to make resources easy to export and render in an SVG document.

First of all, an artist needs to draw using only a few SVG features (i.e. using SVG:path elements). He should avoid using curves, gradients, filters and should limit the number of SVG elements needed to draw a resource. These rules are needed d because of performance problems that could occur when rendering complex SVG elements in the browser, and also because not all browsers can handle all SVG features.

resource_example_tree_cleaned.svg

Figure 13: Example of a Resource

Second, an artist (or someone else) needs to identify what a resource is and how it will be handled when exported or rendered. This is a tedious but necessary step. To identify the different properties of a resource (which is usually made of several SVG elements), the designer has to use a set of specific XML attributes that are directly added to the SVG documents where resources are defined. Inkscape provides an XML editor so that attributes could be added conveniently while drawing resources.

The following examples explain the role of XML attributes in the exporting or rendering operations (this is not an exhaustive list):

resource_svg_code_example_tree.png
This is a sample of SVG code for the Tree Resource

Figure 14: SVG Code Excerpt for a Resource

Once a resource has been created and properly tagged in an SVG document, it is ready to be exported.

Exporting SVG Resources to JSON files

Just as for map files, resource SVG documents are exported using PHP scripts. There is a PHP script for every type of resources, such as a script for environment element graphics, another script for character graphics, etc. but they share the same classes behind the scene as the code to process them is often similar. In the process the XML attributes are read to extract the specific properties of resources, elements or sub-elements. These properties are different from one type of resources to another (and is the reason why this is done using separate scripts). In general, the name of an SVG resource file contains information about the type of the resource so that the PHP script could easily identify what it is currently processing. The script may abort the export if it does not identify the expected file naming convention. The result of an export operation is one or more Json files (this is explained later in this section).

The export of a resource file consists more or less of the following operations:

  1. Make a backup copy of the resource SVG file, check naming convention and open it.
  2. Clean the file:
    1. All references to specific Inkscape and sodipodi namespaces elements and attributes are removed
    2. All coordinates are rounded (removing irrelevant decimals reduces the size of exported data significantly)
    3. Useless style attributes are removed
  3. Start to process SVG elements.
  4. Finally, the Json file is stored in a file repository and is ready to be sent to the browser when requested.
{"north":   
  {"els":     
    {"top":       
     {"SVGEls":
       [{
         "d":"M -34,-102 L -38,-104 ... L -47,-110 L -34,-102 z",
         "style":"fill:#B3730D;stroke:#000000;stroke-width:1;",
         "df":{"rr_part":"leaves"}
        }]
      },
     "tree1":
      {"SVGEls":
       [{
         "d":"M 18,-154 L 38,-145 ... L -1,-153 L 18,-154 z",
         "style":"fill:#CC9900;stroke:#000000;stroke-width:1;",
         "df":{"rr_part":"leaves","rr_size":"LM"}
        },
        {
         "d":"M 18,-154 L 38,-146 ... L -15,-153 L 18,-154 z",
         "style":"fill:#CC9900;stroke:#000000;stroke-width:1;",
         "df":{"rr_part":"leaves","rr_size":"S"}
        },
        ...
       ]
      },
     "tree2":{...},
     ...
    }
  },
 "east":{...},
 "south":{...},
 "west":{...}
}

Storing resources in Json files has many advantages:

Problems and Future Work on Resource Design

Many issues are still to be addressed:

3. Creating a game graphic engine with SVG

Game User Interface Development With SVG

Usually, a game user interface (UI) is unique and follows a graphic style that fits well with the atmosphere of the game. The SVG technology allows a game designer to create UI components with any desired style. Actually, SVG is probably more versatile than any existing framework based on a Web technology on that matter. UI components can be designed with very little efforts using a few SVG primitives. Moreover, the vector nature of SVG is such that every component, say a button group, can be designed only once and will be easy to adapt to any screen size and resolution using SVG transformations. There are existing UI frameworks based on SVG [R3] that propose UI components but using SVG and the DOM to render the game UI is so easy that no such framework is necessary and would not be as flexible as a game would require, though such a framework may be desirable for an SVG-based Web Site or Professional application. SVG is simply the ultimate UI technology for the Web!

Once again, designing a UI component is done using Inkscape. This is even easier than designing game resources because there is no need to add specific “rr_*” attributes to identify special properties. The only required modification to the SVG document is to rename SVG group or element Ids so that they can be easily retrieved in the DOM using Java-script.

A component could be copied from an SVG document created with Inkscape and pasted directly to the main game SVG document and would be easily rendered by a browser. But this is a messy operation as the destination SVG document would contain a lot of useless SVG/Inkscape/Sodipodi elements. Just like for game resources, cleaning the SVG document containing UI components is better. The export script is simple, it just gets rid of useless SVG elements and all Inkscape/sodipodi elements. It also rounds up values for SVG:filter, SVG:gradient, SVG:rect and SVG:path elements.

At some point, APIs that automatically map SVG elements to Java-script events were added to avoid doing it manually after export. It appeared to be a wrong approach because the mapping can easily be done when SVG components are initialized in the browser.

Some components may be reused several times or must be created dynamically. For these components, the export script will create Json objects instead of keeping the SVG format. The UI engine will create SVG elements from Json objects on the fly when needed.

Integrating SVG Components into the Game UI

Once a UI component is designed, cleaned and copied to the main SVG document of the game, it needs to be hooked to the game engine. This is performed as an initialization step once the main SVG document is fully loaded into a browser. The way UI components are handled in the game always follows the same pattern:

SVG User Interface Component Samples

A first interesting example of SVG UI component is the main frame. The main frame surrounds the UI and consists of 8 elements: The 4 corners and the top, bottom, left and right borders. Borders are simple SVG:rect elements while corners have been designed using Inkscape. The main frame handles all other UI components. It is also responsible for resizing/rescaling other components when a resize event is detected. Resizing is performed by using the current width and height of the browser window and by calculating the new position and size of every sub-element. In terms of SVG, every SVG component (an SVG:g element) is ajusted using the translate and the scale transformations.

<g id="rootView">
	<rect id="background" x="0" y="0" width="100%" height="100%" style="fill: rgb(208, 208, 208);"/>
	<!-- Debug console -->
	<g id="consoleFrame" transform="translate(230, 35)"/>
	<!-- Main UI frame -->
	<g id="mainFrame">
		<g id="mapLayout">...</g>
	  	<g id="actionBar" display="inline" transform="translate(341, 476) scale(0.765625)">...</g>
	  	<!-- Left panel with character summary frames -->
	   	<g id="characterSummaryGroup">...</g>
	 		<g id="borders">
			<rect x="36" y="1" width="1294" height="14" />
			<rect x="36" y="522" width="1294" height="14" />
			<rect x="1" y="36" width="14" height="465" />
			<rect x="1351" y="36" width="14" height="465" />
		</g>
		<g id="corners" style="...">
			<g id="topLeftCorner">
				<path d="M 1,1 L 34,1 L 34,25 L 25,25 L 25,34 L 1,34 L 1,1 z" />
				<path d="M 7,7 L 29,7 L 29,20 L 20,20 L 20,29 L 7,29 L 7,7 z" />
			</g>
			<g id="topRightCorner" transform="translate(1331)">
				<path d="M 1,1 L 34,1 L 34,34 L 10,34 L 10,25 L 1,25 L 1,1 z"/>
				<path d="M 7,7 L 29,7 L 29,29 L 15,29 L 15,20 L 7,20 L 7,7 z" />
			</g>
			<g id="bottomLeftCorner" transform="translate(0, 502)">
				<path d="M 1,1 L 25,1 L 25,10 L 34,10 L 34,34 L 1,34 L 1,1 z" />
				<path d="M 7,7 L 20,7 L 20,15 L 29,15 L 29,29 L 7,29 L 7,7 z" />
			</g>
			<g id="bottomRightCorner" transform="translate(1331, 502)">
				<path d="M 10,1 L 34,1 L 34,34 L 1,34 L 1,10 L 10,10 L 10,1 z" />
				<path d="M 15,7 L 29,7 L 29,29 L 7,29 L 7,15 L 15,15 L 15,7 z" />
			</g>
		</g>
		<g id="decoration">...</g>
		<g id="topDecoration" transform="translate(608, -68) scale(0.75)">
			<g id="timeBackground" transform="rotate(0, 101, 101)">...</g>
			<g id="timeTop">...</g>
		</g>
		<!-- Character control -->
		<g id="charControl" display="none">...</g>
		<!-- map control -->
	  	<g id="mapControl" display="inline" transform="translate(928.88, 349.05) scale(1.07404)">...</g>
	</g>
	<text id="mapCoords">...</text>
	<g id="hintGroup" display="none">...</g>
</g>

Here is the result when the main frame is resized:

main_frame_1.png main_frame_2.png

Figure 15: Main Frame Before and After Resizing

Not only the frame is resized to fit the new window area, the number of buttons in the action bar (a reusable button group component) at the bottom of the frame is also reduced.

While designing the game UI, it became obvious that a debug console displaying messages in real time would be valuable. The SVG debug console is just a set of messages that are displayed and that vanish after a few seconds. Again, designing such a component with the following Java-script code was very straight forward:

/**
 * RRConsoleLine
 * Definition of a single line in the R&R console.  
 */ 
function RRConsoleLine(row, SVGContainer, yOffset) {
	var style = "stroke:none;font-size:12px;fill:#FFFFFF;"; 
	this.SVGLine = document.createElementNS(SVG_NS, "text");
	this.SVGLine.setAttribute("id", "consoleLine_" + row);
	this.SVGLine.setAttribute("style", style);
	this.SVGLine.setAttribute("y", yOffset);
	this.SVGLine.appendChild(document.createTextNode("line_" + row));
	SVGContainer.appendChild(this.SVGLine);
}

RRConsoleLine.prototype = new RRBase();

RRConsoleLine.prototype.setMessage = function(msg) {
	while (this.SVGLine.firstChild)
		this.SVGLine.removeChild(this.SVGLine.firstChild);

	this.SVGLine.appendChild(document.createTextNode(msg));
}

RRConsoleLine.prototype.getMessage = function() {
	return this.SVGLine.firstChild.textContent;
}

/**
 * RRConsole
 * Definition of the R&R console which is basically a set of lines to display.
 */
function RRConsole(lineCount) {
	this.REFRESHRATE = 5000; // Number of milisecond to wait before console lines may be moved.
	this.lineCount = lineCount;
	this.lines = new Array(lineCount);
	// The RRConsole class is hooked to the corresponding SVG element here
	this.consoleFrame = document.getElementById("consoleFrame");

	for (var i = 0; i < this.lineCount; i++) {
		this.lines[i] = new RRConsoleLine(i, this.consoleFrame, i * 16);
 	} 
	this.lastUpdate = new Date().getTime();
}

RRConsole.prototype = new RRBase();

RRConsole.prototype.pushMessage = function (msg) {
	for (var i = 0; i < this.lineCount - 1; i++) {
		this.lines[i].setMessage(this.lines[i + 1].getMessage());
 	}
	this.lines[this.lineCount - 1].setMessage(msg);
	this.lastUpdate = new Date().getTime();
}

RRConsole.prototype.Refresh = function() {
	var newUpdate = new Date().getTime();
	if (newUpdate - this.lastUpdate >= this.REFRESHRATE) {
		this.pushMessage(""); 
	}
}

The draw back of this design is that adding many lines of messages in the SVG document is very slow, every character being an SVG element. Such a console is only useful for debugging purposes and while it could be interesting to have the same kind of console in the game itself, the number of messages and the length of messages should be strictly limited. Moreover, every time the console is refreshed, lines should be creating using a DOM Parser and should not be directly added to the DOM tree (in order to improve performance).

The last example is a special group of buttons used to rotate/zoom/translate the map demonstrating that any shape is suitable to create buttons in SVG.

main_interface_map_controls.svg
Creating such an original control could be impossible in HTML

Figure 16: Map Control

Once created with Inkscape, all these UI components were very simple and very fast to implement.

Problems and Future Work on UI Components

While designing components, it was found that not all filters were implemented in all browsers. Moreover, while some browsers implement filters, the rendering process could take 1 or 2 seconds for a single SVG element. So it was decided to avoid using SVG filters as much as possible for now, not only for the UI components but also for the game resources displayed in the main view.

Another problem lately found is the auto-resize feature of the browser window. While the auto-resize feature is nice for computers, it is not suitable for phones and tablets: Every time a player tries to zoom in a part of the windows because it is too small, the game rendering engine resizes everything and the UI is rendered again as it was first initialized. Instead, the Java-script code responsible for this feature should be disabled for mobile devices. Their browser's zooming/moving capabilities are just performing well enough.

Game Graphic Engine Development With SVG

The graphic game engine is responsible for rendering a piece of map at the center of the game UI. It is basically an isometric 3D engine. This engine does not handle real 3D at all though some experiments have been done showing that it was possible. But if real 3D was to be used, WebGL technology would have been used instead of SVG.

In the isometric view, translations, rotations and different zoom levels are handled with very little effort thanks to the SVG technology. The graphic engine performs the following steps every time the surrounding of a player's units or character needs to be rendered:

  1. Get the data from the server: Ground, relief and simple details are retrieved from area files while units, buildings and other resources are retrieved from Json files. All data are retrieved for N x N squares centered on the player's unit or character; N depends on player profile, character/unit capabilities and zoom level. All messages between the server and the browser are sent via XMLHTTPRequest embedded in a Json object.
  2. Render the isometric view, square by square, starting by the upper one and ending by the lower one so that details in the back are rendered behind details at the front. For each square:
    1. Render the ground. A flat square is basically rendered in a 200 x 100 pixels diamond; and all elements to render in this diamond were defined in order to keep the same proportion at design-time.
    2. Decide whether environment elements and other resources should be rendered on top of the square, and render them as needed. The current orientation of the map defines what side of the environment element should be rendered. Resource elements are filtered, i.e. small details are not rendered if the map is zoomed out.
  3. Once everything is rendered, a single transformation is used to adapt the squares of the map to the window in the browser.

Rendering elements on top of the ground is a bit tricky: Ground is 3D, resources are 2D. So for every type of resources, the position must be pre-calculated as shown on the following diagram for trees (4 trees per square = 4 positions):

tree_positions.svg
Positions of trees are calculated depending on the altitude of every corner

Figure 17: Positioning Trees in a square

This is a big limitation because this cannot be done for all resources : Building positions cannot be adjusted and must be rendered on top of flat squares. In terms of game rules, players need to flatten the ground before they could build something on top of it.

game_screenshot1.png

Figure 18: Zoomed-out view of the administrative mode

game_screenshot2.png

Figure 19: Zoomed-in view of the administrative mode

game_screenshot3.png

Figure 20: Zoomed-in player view, trees are displayed with more details

Problems and Future Work on SVG Game Engine

The rendering process of the map is definitely the most CPU-consuming operation in the game UI. A few algorithms have been fixed in order to improve performance significantly:

Performance considerations

Some performance tips have been given already in the previous sections, this section summarizes them for easy reference. Note that with these tips, it is possible to generate an SVG browser application without having to write code to specifically handle browser limitations and specificity.

More SVG optimization tips were proposed on Holger Will's Web site [R7] .

4. Conclusion

This game prototype was first developed to see how SVG could be leverage to create browser games. But programming SVG (including Java-script) was less than 5% of the development effort (not counting graphic design done in SVG). More than a year was spent developing the script to create the map and that was not expected. Designing resources even with an excellent editor such as Inkscape was also time-consuming. But the main feeling about SVG is that it is easier to handle than HTML. It is supported by browsers in a more stable way than HTML is. This is so true that not a single line of specific code was needed so far in the prototype to support all 5 major browsers.

The only serious issue related to SVG is performance. In the future, browsers may use hardware acceleration for SVG as they are today for HTML and that should improve performance dramatically. Performance on cell phones and tablets are still a concern. Java-script performance was great and was never a source of trouble compared to rendering SVG.

At last, SVG is an excellent technology to design browser-based game as far as timing is not important. This of course means that today real-time browser games cannot use SVG in an intensive way. HTML5 may be a better choice for such games [R6] .

5. What's next?

The prototype [R8] should soon move to a beta version, but still many tasks await:

Bibliography

[R1]
Online SVG Games - Online SVG Games Web Page Page
[R2]
SVG Game creation tutorial - a slot machine - Holger Will - SVG Game Tutorial Web Page
[R3]
SPARK - SVG Programmers Application Resource Kit - Christopher T LewisPhilip MansfieldAlastair FettesGlenn MacDonald - SPARK Web Page
[R4]
DOM Parser - Mozilla Foundation - DOM Parser Web Page
[R5]
Optimizing JavaScript Code - Gregory BakerErik Arvidsson - Optimizing Java-script Code Web Page
[R6]
SVG or Canvas? Сhoosing between the two - Mihai Sucan - Choosing between SVG and Canvas
[R7]
SVG Optimization Tips - Holger Will - SVG Optimization Tips Web Page
[R8]
Runes and Relics Game in SVG - Olivier Cueilliez - Runes and Relics Prototype

XHTML rendition made possible by SchemaSoft's Document Interpreter™ technology.