| Flash Tools | How To... | Examples | Download | Installing | Resources |
No Logo

Flash Shape

Display Items

Sprites

Follow Path

Multiple Paths

Direction Reversal

Svg2Flash

Why SVG?

How does it work?

Defining Shapes

Defining Paths



How To Flash Tools

This is a step by step guide for usage of the flash-tools library. All the classes a I use are extensions of the Ming classes and therefore it's not a problem to mix Ming classes with FlashTools classes.

One thing to keep in mind is that the SWF/Flash coordinate system is defined starting in top left hand corner and extending downwards and right, i.e:

    Origin(0,0) .---------> Positive X
                |
                |  
                |     
                V
             Positive Y


Any negative values and values greater than the movies dimension are "off screen". Note though, it is ok to define a shape that uses negative or large coordinates, as long as when it is added to the movie, the shape is scaled/moved to fit into the movie.

The following describes how to construct an Flash animation using Flash Tools and tries to describe this in detail. If you have comments or questions or problems please send me an email.

All the example code show here is included in the examples directory in this directory.

Flash Shape

In the beginning, there is the FlashShape for drawing shapes (circles, retangles, beziers, ellipses...). Besides giving these shapes color and fill, FlashShapes can't really do anything else. In order to include images, you need to use a SWFBitmap and fill a shape using the bitmap. There is a helper class for this: FlashImage. Example 1 demostrates using a shape:
01     shp = FlashShape()
02     shp.setLine( 2, clr=FlashColor.red )
03     shp.drawRectangle( Point( 40, 40 ), 20, 20 )
04     
05     m = FlashMovie()
06     m.setBackground( clr=FlashColor.white )
07     m.setDimension( 100, 100 )
08     m.setRate( 10 )
09     m.add( shp )
10     m.nextFrame()
11     m.save( 'example1.swf' )
Example 1: Shape


Lines 1 to 3 defines our shape. It has no fill but a line width of 2 pixels and red stroke color. The rectangle (line 3) is defined such that the center of the shape is at (50,50): top left hand corner is located at (40,40) and the width and height are both 20 pixels.

You always need a FlashMovie, it's basically the entire animation and every flash film has exactly one movie. The movie is created in line 5, it has a size of 100 by 100 (line 7) and it shows 10 frames per second (line 8). The dimension defines the viewable region of the film: if the shaped defined outside of this dimension, it would not be seen.

In line 9, we add our shape to the movie. Note, that because we drew a rectangle (line 3) centered at 50,50, it is located in the center of the movie. This is only possible because we knew, when we constructed our shape, that the movie will be 100 by 100.

Line 10 creates the single frame that makes up the movie. Note, that without the nextFrame(), the movie would not display the shape: a frame is not automatically created when an object is added to the movie. Finally, line 11 saves the SWF file.

Using Display Items

You may have noticed that there is not much animation in example 1, here we now add animation. To do this we require a DisplayItem (DI) object. A DI allows modifications of the shape once it has been added to a movie.

Using a DisplayItem, you can skew, move, rotate, scale, ... the shape once it has been added to the movie. The intention is that the shape is modified using the DI once per frame so as to create an animation. The DI reference remains valid the entire movie or until remove() is called.
01     shp = FlashShape()
02     shp.setLine( 2, clr=FlashColor.red )
03     shp.drawRectangle( Point( -10, -10 ), 20, 20 )
04     
05     m = FlashMovie()
06     m.setBackground( clr=FlashColor.white )
07     m.setDimension( 100, 100 )
08     m.setRate( 10 )
09 
10     di = m.add( shp )
11     di.moveTo( 50, 30 )
12 
13     m.nextFrame()
14     di.moveTo( 50, 40 )
15 
16     m.nextFrame()
17     di.moveTo( 50, 50 )
18 
19     m.nextFrame()
20     di.moveTo( 50, 40 )
21 
22     m.nextFrame()
23     m.save( 'example2.swf' )
Example 2: Animation


Lines 1 through 3 create the shape, this time however, the rectangle is defined such that the center point of the shape is (0,0). This has the advantage that when we construct our movie, we can position the shape anywhere without worrying about a shape specific offset.

Line 10 adds the shape to the movie, however this time we keep a reference to the display item object that is returned when adding the shape to the movie. Note that we can not explicitly create a DisplayItem instance, rather this is created by the movie object we when add something to the movie.

Line 11 moves the shape to position (50,30) in the same frame (frame 0) where it was added (inserting a m.nextFrame() between lines 10 and 11 would cause a jump at the beginning of the movie).

Line 13 sets the frame pointer of the movie to frame 1 and line 14 moves the shape to position (50,40). Line 16 sets the frame number to 2 and line 17 moves the shape to (50,50). Line 19 sets the frame number to 3 and line 20 moves the shape to (50,40). Line 22 commits the moveTo in line 20 to the movie.

Because the film automatically loops, the shape seems to move up and down. This is because at the beginning of the film the shape is located at (50,30) and at the end it's located at (50,40). It is not necessary to set the number of frames for the movie, it does this automatically.

Using Sprites

This is about animating an animation! This is done using a Sprite which is the same as a movie except we can't save a sprite to a SWF film but we can added numerous (probably infinitely many?) sprites to a movie.
01     shp = FlashShape()
02     shp.setLine( 2, clr=FlashColor.red )
03     shp.drawRectangle( Point( -10, -10 ), 20, 20 )
04 
05     spr = SWFSprite()
06     di = spr.add( shp )
07     for idx in range( 36 ):
08         di.rotate( 10 )
09         spr.nextFrame()
10     
11     m = FlashMovie()
12     m.setBackground( clr=FlashColor.white )
13     m.setDimension( 100, 100 )
14     m.setRate( 10 )
15 
16     di = m.add( spr )
17     for idx in range( 0, 100 ):
18         di.moveTo( 50, idx )
19         m.nextFrame()
20 
21     m.save( 'example3.swf' )
Example 3: Animating an animation


Lines 1 to 3 create our rectangle. Line 5 creates the sprite containing the shape. Notice that the sprite is added to the movie (line 16) and not the shape. Line 6 adds the shape to the sprite, and lines 7 through 9 create 36 frames in which the shape is rotated by 10 degrees in each frame. Note that if the shape was not centered at (0,0), then the rotation would move the entire shape around the origin.

If we now add the sprite to the movie, we would have simply have a rotating rectangle somewhere in the movie. What lines 17 through 19 do is move the shape from the top of the movie to the bottom.

If the movie is too slow, the rate in line 14 can be increased so that the shape appears to move quicker.

In the next example does exactly the same but slightly differently.

Following Paths using FlashSprite

Now we will use path specifications and the followPath method to move blocks along predefined paths.
01     shp = FlashShape()
02     shp.setLine( 2, clr=FlashColor.red )
03     shp.drawRectangle( Point( -10, -10 ), 20, 20 )
04 
05     spr = SWFSprite()
06     di = spr.add( shp )
07     for idx in range( 36 ):
08         di.rotate( 10 )
09         spr.nextFrame()
10     
11     fs = FlashSprite()
12     l = Line( Point(0,0), Point(0,100) )
13     fs.followPath( spr, [ l ], 0, 100 )
14     fs.done()
15     
16     m = FlashMovie()
17     m.setBackground( clr=FlashColor.white )
18     m.setDimension( 100, 100 )
19     m.setRate( 10 )
20     di = m.add( fs )
21     di.moveTo( 50, 0 )
22     m.save( 'example4.swf' )
Example 4: Using followPath


The difference here is that we use a FlashSprite to make the rotation animation move along given line. We then add the FlashSprite directly to the movie instead of creating the line animation in the movie. This has a side effect in that the main movie now only has one frame containing a Sprite with 100 frames. In example 3, we created a movie with 100 frames each moving the animation sprite.

Lines 1 to 9 are the same as in example 3. Line 12 defines the line along which the rotation-sprite is to move. Lines are defined using begin and end points. Line 13 tells the FlashSprite to add the rotation sprite and then move it along the given line. The 0 and 100 are frame numbers and tell the FlashSprite to start at frame 0 and be at the end of the line at frame 100.

Line 14 advises the FlashSprite that we are done with adding shapes to it and that it should build a complete SWFSprite. This needs to be called before adding the FlashSprite to a movie (or another sprite). A FlashSprite is an extension of SWFSprite which basically allows a user to spring around in the frames and adding shapes to any frame, this is not possible with SWFSprite: once nextFrame() is called, there is no going back.

The followPath method computes the number of frames required and then requests (via the get_points(...) method) the required number of points (one for each frame) from the path. Once all points are available, the followPath(...) adds the shape to the sprite and then does successive nextFrame() calls. For each frame it does one moveTo(..) call on the display item that was returned as it added the block to the sprite.

In order to position the rotating rectangle to the middle of the movie, line 21 does a moveTo(..). This shifts the sprite to the middle. Without this the animation would occur on the very left edge of the movie.

In the next example, we will create exactly the same animation but using a third technique: frame hooks.
01     def shape_hook( display_item, frame_num ):
02         display_item.rotate( 10 )
03 
04     shp = FlashShape()
05     shp.setLine( 2, clr=FlashColor.red )
06     shp.drawRectangle( Point( -10, -10 ), 20, 20 )
07     shp.follow_path_frame_hook = shape_hook
08     
09     fs = FlashSprite()
10     l = Line( Point(0,0), Point(0,100) )
11     fs.followPath( shp, [ l ], 0, 100 )
12     fs.done()
13     
14     m = FlashMovie()
15     m.setBackground( clr=FlashColor.white )
16     m.setDimension( 100, 100 )
17     m.setRate( 10 )
18     di = m.add( fs )
19     di.moveTo( 50, 0 )
20     m.save( 'example5.swf' )
Example 5: Using followPath


In this example we only have a single sprite which does both the move and the rotation of the shape. It does this by using a hook that is called for each new frame that is created, i.e. 100 times as the FlashSprite has one hundred frames (line 11). So basically two things happen to the shape for each frame of the sprite: moveTo and rotation. In the previous examples it was two sprites/movies responsible for the movement of the shape, here only one sprite.

The frame hook is defined in lines 1 and 2. Notice that as argument it is passed a DisplayItem instance (the one for the corresponding shape) and the frame number of the frame currently being created. In this case, the frame number ranges from 0 to 99 (inclusive). Line 7 assigns the frame hook to the shape. The hook is not specific to the shape and can be assigned to any other shape.

The name of the hook must be 'follow_path_frame_hook'. The followPath(..) method will check for a function or method with this name on the object passed in. The hook is called after followPath(..) has done the 'moveTo' on the display item. The hook could do a further moveTo call on the display item, but this would be a little counter-productive!

The next example demostrates how to following several paths.

Several Paths

FollowPath accepts a list of paths which the given block will follow in the given frame range. The individual path do not need to be connected although if they are not, then the block will appear to "jump" from the end of one path to the beginning of the next.
01     def shape_hook( display_item, frame_num ):
02         display_item.rotate( 10 )
03 
04     shp = FlashShape()
05     shp.setLine( 2, clr=FlashColor.red )
06     shp.drawRectangle( Point( -10, -10 ), 20, 20 )
07     shp.follow_path_frame_hook = shape_hook
08     
09     fs = FlashSprite()
10     l1 = Line( Point(0,0),   Point(0,100) )
11     l2 = Line( Point(0,100), Point(50,50) )
12     l3 = Line( Point(50,50), Point(0,0) )
13     fs.followPath( shp, [ l1, l2, l3 ], 0, 100 )
14     fs.done()
15     
16     m = FlashMovie()
17     m.setBackground( clr=FlashColor.white )
18     m.setDimension( 100, 100 )
19     m.setRate( 10 )
20     di = m.add( fs )
21     di.moveTo( 10, 0 )
22     m.save( 'example6.swf' )
Example 6: Several paths to follow


The square follows a triangle, returning to it's origin. It moves faster, this is because it needs to cover more ground but has the same number of frames to do so. In order to slow it down: a) modify the number of frames from 100 to something larger in line 13 or b) decrease the rate of the entire film in line 19.

Lines 10,11 and 12 define the three lines along which the shape moves. The lines follow on from one another, i.e. where one ends the other begins, thus there is a continous movement. This is not a requirement and we could easily have used three random lines but then the shape would jump. Replacing the lines 10-12 with the following demostrates that:

10     l1 = Line( Point(0,0),    Point(50,50) )
11     l2 = Line( Point(50,0),   Point(50,50) )
12     l3 = Line( Point(0,50),   Point(50,50) )
Example 6a: Non-continous paths

Direction Reversal

In example 6 the square moves anti-clockwise along the triangle path, example 7 shows how we can reverse the order in which the points for the lines are returned so that the square moves clockwise:

01     def shape_hook( display_item, frame_num ):
02         display_item.rotate( 10 )
03 
04     shp = FlashShape()
05     shp.setLine( 2, clr=FlashColor.red )
06     shp.drawRectangle( Point( -10, -10 ), 20, 20 )
07     shp.follow_path_frame_hook = shape_hook
08     
09     fs = FlashSprite()
10     l1 = Line( Point(0,0),   Point(0,100) )
11     l2 = Line( Point(0,100), Point(50,50) )
12     l3 = Line( Point(50,50), Point(0,0) )
13     l1.reverse()
14     l2.reverse()
15     l3.reverse()
16     fs.followPath( shp, [ l1, l3, l2 ], 0, 100 )
17     fs.done()
18     
19     m = FlashMovie()
20     m.setBackground( clr=FlashColor.white )
21     m.setDimension( 100, 100 )
22     m.setRate( 10 )
23     di = m.add( fs )
24     di.moveTo( 10, 0 )
25     m.save( 'example7.swf' )
Example 7: Directional reversal


Lines 13-15 are new and advise the lines to return their points in reverse order (method followPath requests from each path a set of points which are used to move the block). A further modication is the order of paths: l3 and l2 swapped position in line 16: order of the paths is important when using followPath.

Of course reverse works with any path, replacing lines line 10 through 16 with:
10     cir1 = Circle( Point( 50, 50 ), 30 )
11     cir1.reverse()
12     cir2 = Circle( Point( 50, 50 ), 30 )
13     fs.followPath( shp, [ cir1, cir2 ], 0, 360 )
Example 7a: Circle
10     rect1 = Rectangle( Point( 20, 20 ), 80, 60 )
11     rect1.reverse()
12     rect2 = Rectangle( Point( 20, 20 ), 80, 60 )
13     fs.followPath( shp, [ rect1, rect2 ], 0, 100 )
Example 7b: Rectangle
10     ellip1 = CenterPointEllipse(Point( 50, 50 ), radii_x = 60, radii_y = 30)
11     ellip1.reverse()
12     ellip2 = CenterPointEllipse(Point( 50, 50 ), radii_x = 60, radii_y = 30)
13     fs.followPath( shp, [ ellip1, ellip2 ], 0, 360 )
Example 7c: Ellipse


As a result of reversing the path segment, the square seems to ping-pong from one end to the other of the path. Also the point where the shape begins to move along the path is differs: a) Rectangle: top left hand corner as defined in the constructor and b) ellipse and circle both start at the furthest right hand side point.

This might not be a problem for the above examples, however when combining two or more shapes it becomes a problem:
01     def shape_hook( display_item, frame_num ):
02         display_item.rotate( 10 )
03 
04     shp = FlashShape()
05     shp.setLine( 2, clr=FlashColor.red )
06     shp.drawRectangle( Point( -10, -10 ), 20, 20 )
07     shp.follow_path_frame_hook = shape_hook
08     
09     fs = FlashSprite()
10     ellip = CenterPointEllipse(Point( 70, 50 ), radii_x = 30, radii_y = 20)
11     rect = Rectangle( Point( 0, 30 ), 40, 40 )
12     fs.followPath( shp, [ ellip, rect ], 0, 360 )
13     fs.done()
14     
15     m = FlashMovie()
16     m.setBackground( clr=FlashColor.white )
17     m.setDimension( 100, 100 )
18     m.setRate( 20 )
19     di = m.add( fs )
20     di.moveTo( 10, 0 )
21     m.save( 'example8.swf' )
Example 8: Ellipse and rectangle path


Here the square jumps from the start of the ellipse to the start of the rectangle. To avoid this, we add the following between lines 11 and 12:
12     ellip.setStartPoint( Point( 40, 50 ) )
13     rect.setStartPoint( Point( 40, 50 ) )
14     rect.reverse()
Example 8a: Creating a continous path


Now the shape continous along a smooth path without jumping. The point (40,50) happens to be on the perimeter of both shapes, this does not need to be the case. Any point may be passed to setStartPoint(...) but the point that is the closest to the start point and on the perimeter will be returned as the first point.

Also, setting a start point only makes sense when using "closed" shapes, because a line or bezier is not continous, setting a start point will cause a jump: the only "smooth" path along a line is starting at either end but not in the middle!

Line 14 does a reverse on the rectangle: this ensures that the square does a figure-8 and not two-3s. We could have done a reverse on the ellipse, this would have produced a figure-8 but in the other direction.

svg2flash: Converting SVGs to Flash

Scalable Vector Graphics (SVG) is a W3C standard for the representation for vector based graphics. There are a number of tools for creating SVG images, including Gimp, Xfig and InkScape (see Resources for links).

Why SVG?

  • Vector based: this is important since SWF/Flash is also vector based.
  • XML based: easy to read(!!) and easy to parse and intepret
  • Open standard: this allows graphic tools to use this as an representation for vector based graphics.


SVG also has support for animation and scripting and text and ... i.e. lots of the functionality that SWF provides. Obviously, it would be great to have a 100% SVG to SWF converter but this is not what Svg2Flash does (yet)!

The intention of the Svg2Flash converter is to convert basic SVG images to Python code so that they may be included in other Python code that generates the SWF animation. Although the generated Python code can also be used to generate a static SWF.

How does it work?

Svg2Flash converts basic shapes (see Section 9 of the SVG specification version 1.1 (SVG1.1)) and paths (Section 8, SVG1.1) to their Flash Tools equivalents. Also it supports group elements (Section 5.2, SVG1.1) but only attributes that effect the color or fill specifications of elements. CSS style specifications are also supported.

The methods described below are all defined on the 'SVGImage' class. This class can be included in using the 'as' form of the import to allow multiple generated classes to be included:

from svg_image_1 import SVGImage as SvgImage1
from svg_image_2 import SVGImage as SvgImage2
...
Hi, I'm empty!
Including several Images


For each of the shape and path definitions found in an SVG image, three methods are generated: geomXX(), clrFillXX() and shapeXX() where XX ranges from 01 to the number of elements found. The 'geom' methods returns the pure geometry of the shape/path in form of a Path (see flash_geometry/path.py), 'clrfill' returns a dictionary containing the color and fill specification for the shape. These are indexed using the SVG1.1 attribute names, i.e. stroke-width, stroke, fill, etc. The 'shape' methods return a FlashShape instance which is a complete shape, i.e. a combination of 'geom' and 'clrfill'.

Because the order of the shape definition might change, shape definitions may be accessed using their 'id' value. That is, if a shape has an id attribute, then the above values can be obtained using three extra methods: getGeometry(name), getColorFill(name) and getShape(name) where name is id.

Two other methods are defined: getAllShapes() which returns a list of FlashShapes containing all the shapes and paths, getViewbox() which returns the viewbox specification (Section 5.1.2, SVG1.1). This returns a list of: min-x, min-y, width and height. Also, calling the generated python file directly using python will create a 'output.swf' which is basically the SVG image in form of a Flash animation.

A couple of notes: the coordinates are not scaled and are returned as defined in SVG, although the default SWF generated by the main function centers image. Most of the values for stroke-linecap and stroke-linejoin are not supported becuase these are non-trivial to convert. Only shape, path and group elements are supported, all other elements are TODOs.

Options that can be passed to svg2flash:

  • --input
    name of the input svg file. Defaults to input.svg. Can also be '-', then svg2flash will read from standard in.
  • --output
    name of the output python file. Defaults to output.py. Can also be '-', in which case the output is sent directly to standard output. Useful for doing compilation on the fly:
    svg2flash --input=some.svg --output=- | python - 
  • --swf
    name of the SWF file to generate if the generated python is executed directly. Defaults to output.swf.

Defining Shapes

The following is a circle example. The SVG file defines a circle with a radius of 3.41229 pixels, center at (288.242,85.8223). The fill is blue but with an opacity of 0.5 (ranges from 0 to 1). Stroke color is yellow and the width is 2. The full code can be found in the files example9.svg, example9.py and example10.py in the example directory.
05 <svg xmlns="http://www.w3.org/2000/svg"
06      width="400" height="400"
07      viewbox="0 0 400 400">
08 
09   <circle 
10     fill="blue"
11     fill-opacity="0.5"
12     stroke="yellow"
13     stroke-width="2"
14     id="circle"
15     cx="288.242" cy="85.8223" r="3.41229"/>
16 
17 </svg>
Example 9: SVG Circle definition


The generate Python class contains the three generated methods for the shape. Also shown are the methods for accessing the shape via its id value. The constructor method (__init__(self)) creates a lookup table for mapping the Ids to their corresponding index values.
08 class SVGImage:
09 
10   # Shape Name: circle
11   def clrfill00(self):
12     opes = {}
13     opes['stroke'] = 'yellow'
14     opes['stroke-width'] = '2'
15     opes['fill'] = 'blue'
16     opes['fill-opacity'] = '127'
17     return opes
18   def geom00(self):
19     opes = Path()
20     opes.append( Circle( Point(288.242, 85.8223), 3.412290 ) )
21     return opes
22   def shape00(self):
23     shp = FlashShape()
24     shp.setLine( 2, clr=getColor( 'yellow' ))
25     shp.setLeftFill(shp.addSolidFill(clr=getColor('blue').setA(int('123'))))
26     shp.moveTo( Point( 288.242, 85.8223 ) ) # circle
27     shp.drawCircle( int(3.41229) ) # circle
28     return shp, None
29 
30   def getViewbox(self):
31     return [ 0, 0, 400, 400 ]
32 
33   def getGeometry(self, name):
         <... snip ...>
39 
40   def getColorFill( self, name ):
         <... snip ...>
46 
47   def getShape( self, name ):
         <... snip ...>
53 
54   def getAllShapes( self ):
55     return self.__allshapes
56 
57   def __init__(self):
58     self.name2shape = {}
59     self.name2shape['circle'] = 0
60     self.__allshapes = []
61     for idx in range(1):
62       self.__allshapes.append( eval( 'self.shape%02d()'%idx ))
Example 9a: Python generated from the SVG specification


The follow is an example of using the generated python class.
01     from example9 import SVGImage as SVGCircle
02 
03     img = SVGCircle()
04     
05     def shape_hook( display_item, frame_num ):
           <... snip ...>
14 
15     spr = SWFSprite()
16     cpt = img.getGeometry( "circle" )[0].getCenter()
17     di = spr.add( img.getShape( "circle" )[0] )
18     di.moveTo( -cpt.x, -cpt.y )
19     spr.nextFrame()
20     spr.follow_path_frame_hook = shape_hook
21     
22     fs = FlashSprite()
23     fs.followPath( spr, [ Point(50,50) ], 0, 70 )
24     fs.done()
Example 10: Using SVG Images


Line 01 is the import of the SVGImage class. In this case, it is not necessary to give the imported class a new name since there is only one SVGImage we're using. The variable 'img' is then an instance of the class.

Lines 15 to 20 define an encapsulating sprite which translates the shape. Line 16 obtains the geometry shape, which we know is a circle and there is only one geometry shape (see geom00() in example 9a), so calling getCenter() is ok. The coordinates of the center point is SVG user space and when adding the shape to the sprite, the shape needs to translated from the center point to the origin (line 18).

The hook defined in lines 5-13 is added to the encapsulating sprite in line 20. Line 23 places the sprite directly in the middle of the movie and the calls the sprite hook 70 times.

Defining Paths

This time we will define a path in an SVG image and use this path make shape follow this path. The code for this example: example11.svg, example11.py and example12.py. The SVG was generated using the SVG-Export script-fu, the source XCF: example11.xcf.
11   <circle __id__="_fc#e51616_sc#e51616_sw0_tpcircle_nmshape-fg_"
12     fill="#e51616"
13     stroke="#e51616"
14     stroke-width="0"
15     __type__="circle"
16     id="shape-fg"
17    cx="23.375" cy="50.3438" r="4.50022"/>
18   <rect __id__="_fc#416dea_sc#416dea_sw1_tprect_nmshape-bg_"
19     fill="#416dea"
20     stroke="#416dea"
21     stroke-width="1"
22     __type__="rect"
23     id="shape-bg"
24     x="15.875" y="41.75" width="14.8159" height="16.9377"/>
25   <path __id__="_nmpath_"
26     id="path"
27     d="M 9,11.25
28        C 22.75,3.75 62.75,3 81.75,12.5
29        C 95.25,22 96.75,69.75 85.75,87.25
30        C 70.75,96 41.25,98 24.75,90.25
31        C 13.25,76.75 14.75,34.75 24.75,27
32        C 33.75,19.75 58.25,19 68.75,28
33        C 81,37.25 79,67.5 72,75
34        C 61.5,82.25 49.5,85.5 36.5,74.75
35        C 28,66.75 27.5,47 36,40.5
36        C 47,34 51.5,34.75 60.25,40
37        C 67.5,48.25 67.5,57 61.75,66
38        C 56.75,69.75 53.75,71.5 47.25,66
39        C 43.25,61.75 44.5,58.25 47,54.75
40        C 59.5992,46.7138 57.75,65.75 52,60
41        C 52,60 9,11.25 9,11.25 Z"
42 />
Example 11: SVG Specification


The following code uses the SVG:
01     from example11 import SVGImage as PthImage
02 
03     img = PthImage()
04 
05     def shape_hook( display_item, frame_num ):
           <... snip ...>
10         
11     spr = SWFSprite()
12     cpt = img.getGeometry( "shape-fg" )[0].getCenter()
13     di = spr.add( img.getShape( "shape-bg" )[0] )
14     di.moveTo( -cpt.x, -cpt.y )
15     di = spr.add( img.getShape( "shape-fg" )[0] )
16     di.moveTo( -cpt.x, -cpt.y )
17     spr.nextFrame()
18     spr.follow_path_frame_hook = shape_hook
19 
20     fs = FlashSprite()
21     fs.followPath( spr, img.getGeometry( "path" )[1:], 0, 200, True )
22     fs.done()
Example 12: Using a path specification from SVG image


Line 1 and 3 import and initialise an instance of the SVG image. Lines 11 through 18 construct the encapsulating sprite with the shape, which defined using two parts: a background and a foreground (in this case a blue rectangle and red circle).

Line 21 retrieves the path specification minus the first path segment which happens to be a single point corresponding the initial moveTo operation of the SVG (Example 11, Line 27). The last argument of line 21 indicates that the followPath should equal space the points over the entire length of the path.


Thanks to SourceForge! Contact Author