NOGDUS

Articles, Tutorials, and other things. => General Programming => : Richard Marks March 24, 2009, 06:28:25 PM



: Manual SVG Creation
: Richard Marks March 24, 2009, 06:28:25 PM
Manual SVG Creation

Okay before you say that I'm completely insane, let me explain. ;D

I wanted to see how fast I could put together some isometric artwork, and I ended up messing with Inkscape as I said in another thread around here...however, with 360KB SVG files and horrendous formatting in them, its very difficult to
work with.

I'm here to show you that it is indeed possible if not outright easy to write the art by hand. (I love that statement)

You will need five things to follow along with me.
  • Ubuntu Linux OS (I'm using version 8.04 Hardy Heron..you can use the latest if you like)
  • Eye Of Gnome Image Viewer (type eog at a terminal and if it opens then you've got it)
  • A text editor. I'm using gedit.
  • Firefox (should be installed in nearly every Linux OS) You will need at least version 3.0
  • irb (Ruby interpreter..I'm using it as a simple calculator..you could use the gnome calculator if you like.)

Okay, arrange your "workspace" like I have done below:

(http://storage.ccpssolutions.com/richard/howtosvg/howtosvg-workspace-ss1.png) (http://storage.ccpssolutions.com/richard/howtosvg/howtosvg-workspace-ss1.png)

I've set the "Always on Top" properties of the terminal and the eye of gnome windows.
Right-click the title-bar of the windows, and check the "Always on Top" box.
gedit just sits in the background waiting to be typed in :D

First lets get an empty SVG file created.
in your terminal, type
:
$ cd ~
$ mkdir HowToSVG
$ cd HowToSVG
$ touch blank.svg
$ gedit blank.svg

Now, blank.svg should be open in gedit, and now we write our boiler-plate code:
:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="BlankSVG"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="320" height="224"
style="enable-background:new">
<defs>
</defs>
<g id="BaseLayer" >
</g>
</svg>

Save the file, and in your terminal type:
:
$ cp blank.svg tutorial_a.svg
$ gedit tutorial_a.svg

Now, lets edit tutorial_a.svg to show something..

Between the <defs> and </defs> tags we are going create a simple red 64x32 isometric tile.
:
<path id="IsoTile"
d="M 32,0 L 64,16 L 64,16 L 32,32 L 0,16 z"
style="stroke: none; fill: red;" />

Now, in order to make it show up, we need to USE it.
Between the <g id="BaseLayer"> and </g> tags, we add our code to use the tile we created:
:
<use x="0" y="0" xlink:href="#IsoTile" />

Save your file, and in eye-of-gnome use the File menu to open up tutorial_a.svg

You should see this:
(http://storage.ccpssolutions.com/richard/howtosvg/howtosvg-tutorial_a_results-ss1.png) (http://storage.ccpssolutions.com/richard/howtosvg/howtosvg-tutorial_a_results-ss1.png)

More to come later.
I will explain all of what we did later. Sorry, but I'm tired right now and need a break. 8)

...here is a sneak peak at what the next tutorial will be on:
(http://storage.ccpssolutions.com/richard/howtosvg/howtosvg-tutorial_b_results-ss1.png) (http://storage.ccpssolutions.com/richard/howtosvg/howtosvg-tutorial_b_results-ss1.png)

Want a challenge? Create An 8x8 checker board SVG file. :D
Here is the use section for the image above:
:
<use x="128" y="32" xlink:href="#DarkCell" />
<use x="96" y="48" xlink:href="#LightCell" />
<use x="160" y="48" xlink:href="#LightCell" />
<use x="64" y="64" xlink:href="#DarkCell" />
<use x="128" y="64" xlink:href="#DarkCell" />
<use x="192" y="64" xlink:href="#DarkCell" />
<use x="32" y="80" xlink:href="#LightCell" />
<use x="96" y="80" xlink:href="#LightCell" />
<use x="160" y="80" xlink:href="#LightCell" />
<use x="224" y="80" xlink:href="#LightCell" />
<use x="0" y="96" xlink:href="#DarkCell" />
<use x="64" y="96" xlink:href="#DarkCell" />
<use x="128" y="96" xlink:href="#DarkCell" />
<use x="192" y="96" xlink:href="#DarkCell" />
<use x="256" y="96" xlink:href="#DarkCell" />
<use x="32" y="112" xlink:href="#LightCell" />
<use x="96" y="112" xlink:href="#LightCell" />
<use x="160" y="112" xlink:href="#LightCell" />
<use x="224" y="112" xlink:href="#LightCell" />
<use x="64" y="128" xlink:href="#DarkCell" />
<use x="128" y="128" xlink:href="#DarkCell" />
<use x="192" y="128" xlink:href="#DarkCell" />
<use x="96" y="144" xlink:href="#LightCell" />
<use x="160" y="144" xlink:href="#LightCell" />
<use x="128" y="160" xlink:href="#DarkCell" />


: Re: Manual SVG Creation
: Richard Marks March 24, 2009, 10:51:56 PM
Manual Isometric Scene Creation: Part I

Okay, I took it up a notch now. 8)

Check out the simple scene that I'm going to show you how to make:

(http://storage.ccpssolutions.com/richard/howtosvg/howtosvg-isowalls-ss1.png) (http://storage.ccpssolutions.com/richard/howtosvg/howtosvg-isowalls-ss1.png)

Cool huh? :D
Lets talk a little about the code before I show it to you.

I'm using a standard 2:1 ratio (the tile width is the height times two) for the isometric tiles.
The scene is comprised of several groups, in a hierarchical format.
In the definition (defs) section we first define the various components of our scene.
First we define the two tiles that will be used to create the floor.
The checker board pattern floor is then created in its own group object.
Next we define a simple wall group object.
Finally we have the scene group object which uses the wall and floor group objects.
After the definition (defs) section, we have a base layer to setup our scene background,
and then we call the scene group object and lastly we place a nice border around our scene.
This format allows for easy scene manipulation.

Lets see the code a little at a time.

The tile definitions are first:
:
<!-- Basic Iso Tiles are 64x32 -->
<path id="DarkCell"
d="M 32,0 L 64,16 L 32,32 L 0,16 z"
style="stroke: none; fill: black;" />
<path id="LightCell"
d="M 32,0 L 64,16 L 32,32 L 0,16 z"
style="stroke: none; fill: white;" />

Now, I'm going to explain the d="" stuff only once, so pay attention. ;D

Lets break down d="M 32,0 L 64,16 L 64,16 L 32,32 L 0,16 z" one step at a time.

M 32,0 -- move the "pencil" 32 pixels to the right of the origin (upper left-hand corner of the drawing)

L 64,16 -- draw a line from the pencil's position (32,0 as we set above) to 64,16 (64 pixels right and 16 pixels down from the origin)

L 32,32 -- draw a line from the pencil's position (64,16 since we have moved to draw the previous line) to 32,32 (I'm not going to explain the coordinates again)

L 0,16 -- draw a line to 0,16

z -- close the path (be sure you always do this for closed shapes)

OK? we're good right?
The style stuff is VERY simple
stroke: none; means we do not want any stroke (the border of the path object)
fill: black; means we want to fill the path object (polygon..our tile!) with the color black. (I know black isn't a color, shut up!)

id="DarkCell" this assigns a name that we can refer to this object by later. Don't use spaces or weird characters. Alpha-numeric and underscores are OK.

Next lets see the checker board floor code:
:
<g id="CheckerBoard5x5">
<!-- Simple Checkers Board 5x5 -->
<use x="128" y="32" xlink:href="#DarkCell" />
<use x="96" y="48" xlink:href="#LightCell" />
<use x="160" y="48" xlink:href="#LightCell" />
<use x="64" y="64" xlink:href="#DarkCell" />
<use x="128" y="64" xlink:href="#DarkCell" />
<use x="192" y="64" xlink:href="#DarkCell" />
<use x="32" y="80" xlink:href="#LightCell" />
<use x="96" y="80" xlink:href="#LightCell" />
<use x="160" y="80" xlink:href="#LightCell" />
<use x="224" y="80" xlink:href="#LightCell" />
<use x="0" y="96" xlink:href="#DarkCell" />
<use x="64" y="96" xlink:href="#DarkCell" />
<use x="128" y="96" xlink:href="#DarkCell" />
<use x="192" y="96" xlink:href="#DarkCell" />
<use x="256" y="96" xlink:href="#DarkCell" />
<use x="32" y="112" xlink:href="#LightCell" />
<use x="96" y="112" xlink:href="#LightCell" />
<use x="160" y="112" xlink:href="#LightCell" />
<use x="224" y="112" xlink:href="#LightCell" />
<use x="64" y="128" xlink:href="#DarkCell" />
<use x="128" y="128" xlink:href="#DarkCell" />
<use x="192" y="128" xlink:href="#DarkCell" />
<use x="96" y="144" xlink:href="#LightCell" />
<use x="160" y="144" xlink:href="#LightCell" />
<use x="128" y="160" xlink:href="#DarkCell" />
</g>

Okay, this needs a little explanation. 8)
If you don't know what is going on here, we are reusing our tile path objects (remember we gave them IDs?) using the use tag.
We set the X and Y positions of each of the tiles to create a diamond-map checkerboard pattern.
I indented the code to represent the way that the tiles are placed from top to bottom, left to right.
It makes it easier to read I think. :)

The g tag stands for GROUP, and it lets us place a bunch of objects under a single ID that we can use, in this case it is CheckerBoard5x5.

Next we define the isometric wall group object.
Lets see the code for that:
:
<g id="IsoRightWall5x4x1Over2">
<!-- Isometric Right Wall. Dimensions are half a tile's height in thickness, five tiles in length, and four tiles in height. -->
<path id="IsoWallSWFace_LEFT"
d="M 0,0 L 160,80 L 160,144 L 0,64 L 0,0 z"
style="stroke:none; fill: red;" />
<path id="IsoWallSWFace_RIGHT"
d="M 160,80 L 176,72 L 176,136 L 160,144 L 160,80 z"
style="stroke:none; fill: blue;" />
<path id="IsoWallSWFace_TOP"
d="M 0,0 L 16,-8 L 176,72 L 160,80 L 0,0 z"
style="stroke:none; fill: yellow;" />
</g>

Nothing new here, the coordinates were calculated one at a time by deciding the size of the wall.

:
<g id="Scene">
<g id="FloorLayer" opacity="1.0">
<use x="0" y="0" xlink:href="#CheckerBoard5x5" />
</g>
<g id="WallLayer" opacity="1.0">

<use x="144" y="-24" xlink:href="#IsoRightWall5x4x1Over2" />
</g>
</g>

Here you can see that we have nested group objects.
This makes it easier to keep things organized.
I've created 2 "layer" groups that make up the scene.
The floor and wall are on separate layers, hence they are separate group objects.
Also note that we are reusing the group objects that we previously defined.
Very, very, useful. 8)

Now we've finished up defining everything, lets see the final presentation code:

:
<g id="BaseLayer" opacity="1.0">
<path id="Base"
d="M 0,00 L 320,0 L 320,224 L 0,224 L 0,0 z"
style="stroke: none; fill: #6C7E9F;" />
</g>

I wanted a nice blue shade for my background.
We just create a path object that is a rect the same size as our scene, and fill it.

Now, we reuse the scene group object, placing it in yet another group, that I've called SceneLayer:
:
<g id="SceneLayer">
<use x="0" y="32" xlink:href="#Scene" />
</g>

Lastly we add a nice border around the scene:
:
<g id="DecorativeBorderLayer">
<path id="DecorativeBorder"
d="M 0,00 L 320,0 L 320,224 L 0,224 L 0,0 z"
style="stroke: black; stroke-width: 2px; fill: none;" />
</g>

The fill is set to none so that we can see the scene through the rectangle that we created.
stroke-width lets us specify the border's thickness. Two pixels looks good to me.


Thanks for reading!
Have fun!
Show me your hand-written SVG scene creations! 8)


Sorry, the copyright must be in the template.
Please notify this forum's administrator that this site is missing the copyright message for SMF so they can rectify the situation. Display of copyright is a legal requirement. For more information on this please visit the Simple Machines website.