In the run up to implementing some relatively complicated mesh management (including collision detection, triggers and game mechnics) for our main title in development (Dead West) we wanted to try out a few methods in our component architecture-based framework. There'll be posts on this later - suffice to say component-based development is kicking the ass of the bloated-and-object-oriented alternatives.
Our entry in the Ludum Dare October Challenge, Ludum Racer (soon to likely be called Dwarf Derby) was the perfect platform for this - it's a simple top-down racer with relatively basic physics and flat collision data. Most importantly, it's based on the same component architecture that Dead West is based on.
So, that's something of a round-about away of getting to the point of this post -- we wanted to try using Illustrator as a level/track design tool. Whilst we could've easily used Vertex Helper or similar for the Dwarf Derby project, Dead West has a complicated, layered set of co-ordinate-based game data (that Illustrator is well suited to managing).
The plan (and thus far successful execution) was this:
- Create nav mesh (just triangles for the purpose of this) in Adobe Illustrator
- Export from Illustrator to SVG
- Load that SVG in-game using TouchXML
- Build whatever data structures we need in memory by querying the XML/SVG document with XPath statements
This required some specific methods and tweaks, so I've brought those together below in a deliberately basic how-to. You'll need to embelish this with your own data and outputs, but it should provide a reasonably solid process to build upon.
Illustrator - setting up layers and creating shapes
Setup a couple of layers - you'll likely want a background reference layer upon which you'll draw the require geometery.
In the example above, we've got a "reference art" layer, that contains a flattened version (from a Photoshop original) version of the level art and a "triangles" layer, that contains all the geometry we want to use.
It's important that you place the shapes that generate your in-game data on dedicated layers. When we get to the SVG stage you'll see why.
Create your polygons (we're using triangles here, but any polygon would work in effectively the same way) using the line tool. With the tool selected:
- Click and drag to make the first edge (then release the mouse)
- Hover the mouse of the end point of that edge so you see "anchor" appear
- Click and drag the second edge (then release)
- Connect the triangle by clicking from the end anchor of the second edge to the start anchor of the first edge
So far we just have a collection of edges, and as you draw out more polygons a direct export to SVG will result in a confusing mess of unconnected co-ordinates.
In order to distinguish the polygons, we must group their edges - select the 3 (or however many if you're not using triangles) edges and then hit CMD+G (or right click, Group).
Exporting to SVG
In Illustrator, use save-as and select "SVG (svg)" - not "SVG Compressed".
In the save options dialog for SVG, check you're using v1.1 and switch image location to "Link" - unfortunately you have to do this every time.
If you take a look at the SVG document, you'll see why we grouped the edges of our polygons, and why we collected all relevant shapes on a single layer -- most everything useful in SVG is a "g" element. Later using TouchXML and some XPath queries, we can use this structure to get at exactly what we need.
Loading the SVG in your iOS project
You need to get TouchXML running in your project first - I'd recommend this excellent TouchXML installation guide at foobarpig.com. Note that you'll need to download TouchXML itself from github, not the old Google code location.
Test you can compile once TouchXML's included in your project, then add an #import "TouchXML.h" to the relevant class and load up your XML -- in the example below we've a simple method that loads an SVG file, sets up the SVG namespace and executes a test query (specifically populates an NSArray with all of the triangles from our "triangles" layer).
At this point it's over to you - we'll be stepping over that array and building an in-memory array of our geometry for some simple collision detection.
A couple of important points to note:
- Illustrator's origin is top-left, so you need to transpose any coordinates accordingly.
- If you are just wanting the polygon nodes, then you only need to pay attention to the x1 and y1 attributes (see SVG sample above) as the x2 and y2 coordinates of the first edge will be the same as the x1 and y1 of the second edge.
A couple of less important but otherwise useful points:
- There's nothing stopping you from pre processing the SVG (XSLT would be a great way to do this), or to transpose it to another data format (for Box2d for example).
- You can easily add additional data (particularly for debugging) to you data by simply adding Illustrator text elements to the polygon groups. They will get output into the SVG in "text" elements, which would be ignored when querying for "g" elements with the XPath above.
- XSLT and XPath are wonderful tools if you're working with XML a lot - I can thoroughly recommend Doug Tidwell's XSLT book if you want to learn more - I've had a copy beside my desk for longer than I care to remember.
Update: TouchXML is now at https://github.com/TouchCode/TouchXML