For this first tutorial/making of, I’m going to explain how to use Inkscape’s extension system to suit it to your game development needs.
First, a few definitions:
- Inkscape is a free open-source vector graphics editor.
- SVG (Scalable Vector Format) is an XML based vector drawing format.
- Python is the programming language used for Inkscape’s extensions.
Let’s start with an example of how I use Inkscape as a game tool for Jump&Slide:
Here I use Inkscape to automatically place and set the attributes of the obstacles in my game, attributes being the obstacle’s sprites and their positions, sounds, movement, etc. You can also see the collision polygon as a blue semitransparent polygon which is automatically parsed as a dictionary containing all its vertices, the obstacle’s particle system origin and type, and the practice mode arrow directly placed visually in Inkscape.
Since SVG is XML based, I write all the attributes with an extension as custom XML attributes of my object; this way changes are saved in my .svg file.
Then another extension is used to output the data as a custom XML formatted string that will be parsed by my game engine, which is shown using the error message box output from Inkscape, as you can see here:
All I have to do left is to copy/paste it into the actual .plist file, which is the parsed in my game engine.
Note that I do the copy/paste part to ensure everything has been written properly, but you can actually output your data directly to a file using Python’s File I/O functions. (UPDATE: I actually ended up doing this, as the output message box method would occasionally crash Inkscape for reasons I couldn’t figure out!)
HOW TO DO IT:
An extension in Inkscape is defined with two files : a .inx header telling Inkscape that the extension exists and optionally setting your extensions user interface (if you need any), and the actual Python .py file (learn more about this here).
These files need to be placed in …\Inkscape\share\extensions.
Basically, what an extension does is getting your working SVG file as a parameter of your Python script, meaning you have access to its entire XML structure, and then it returns a new modified structure (though it is not mandatory to make any changes to it, for example when I output my obstacle list I merely parse the data from Inkscape into my custom XML format but I don’t change the actual SVG file).
Then you’ve got a few useful functions to retrieve and access your Inkscape objects, such as iterating through the current selection, checking the type of the currently iterated object (is it a rectangle, a path, an image, a text…?), and do whatever you want with it!
Let’s see a very basic example: we will parse a polygon straight path data to extract the vertices and output them as XML data.
As we can see in the SVG specifications, a path is made of a “svg:path” node, with the “d” attribute containing the actual path data as a string of commands and coordinates (something like “M 0,0 50,0 50,50 0,50 z” will tell “Move to (0,0), then draw to (50,0), then draw to (50,50), etc. and stop at the ‘z’ command; hence drawing a square with this example).
So here’s the code to get and parse that data with our extension:
#Create the string variable which will hold the formatted data (note that '\n' defines a line break)
outputString = "<POLYGONS>\n"
#Iterate through all the selected objects in Inkscape
for id, node in self.selected.iteritems():
#Check if the node is a path ( "svg:path" node in XML )
if node.tag == inkex.addNS('path','svg'):
#Create the string variable which will hold the formatted data (note that '\t' defines a tab space)
outputString += "\t<polygon>\n"
#The 'd' attribute is where the path data is stored as a string
pathData = node.get('d')
#Split the string with the espace character, thus getting an array of the actual SVG commands
pathData = pathData.split(' ')
#Iterate through all the coordinates, ignoring the 'M' (Move To) and 'z' (Close Path) commands - note that any other command (such as bezier curves) will be unsupported and will likely make things go wrong
for i in range( len(pathData)-1 ):
#If there is a comma, we know that we are dealing with coordinates (format "X,Y") - ignoring any other SVG command (such as 'M', 'z', etc.)
if pathData[i].find(',') >= 0:
currentCoordinates = pathData[i].split(',')
#Get the X and Y coordinates
x = currentCoordinates
y = currentCoordinates
#Add them as a new 'vertice' node containing the coordinates as the 'x' and 'y' attributes
outputString += "\t\t<vertice x=\"" + str(x) + "\" y=\"" + str(y) + "\" /> \n"
#Close the current polygon node
outputString += "\t</polygon>\n"
#Close the main node
outputString += "</POLYGONS> "
#Write the formatted string to Inkscape's error message box
This is an example of what you get:
It is that simple, the rest is up to you and depends of your needs; for example, you could change Inkscape into a polygon-based level editor, where orange polygons would be solid ground and blue polygons would be water, since you can retrieve your objects’ color attributes via the XML structure.
I made template extension files which will be much more easy to understand than my clumsy explanations!
You can download them here (zip, ~75 Ko).
This is how it looks :