V2D Game IDE
documentationdownloadforumabout
 

V2D - A Swf to Box2D Visual Layout Tool

Overview

There are a number of 2D physics systems out there. They are very fun to use, and can be very effective when used in games or general UI. However, they can be a pain to set things up in. You must define bounding boxes for your objects, specify joints, angles, rotations, scales... all of this begs for a visual tool to help with the setup. This is such a tool.

This tool allows you to visually create and layout your objects and joints in Flash. These objects are then converted into a simple data structure, which is then used to create your 2D physics runtime world. Like this:

demo  
Layout in Flash (download fla)   Generated Swf

The first engine supported is Box2D. Box2D is a very excellent 2D physics engine used in various languages and target systems. It was written by Erin Catto, and there have been ports and mods to platforms such as Flash, XNA, and Java. This tool initially targets the flash translation by 'skatehead' (real name?), Box2DFlashAS3, which is also excellent. So thanks to everyone on that side, you people are awesome : ).

Contents

Requirements

- Input files need to be Flash 8 swfs (or less)
- Output is for Flex, AS3 (Flash 9 is fine)
- .Net 2.0 runtime
- Source code is editable in (the free) Visual Studio 2008 Express Edition
- V2D (this program) which can always be found at http://www.codeplex.com/swf (download)

Usage

Layout where you want things, including skew, color transforms etc in Flash. Add your joints by dragging on the joint symbols. All bodies and joints can be laid out visually, however you can add or override settings in script.

The swf will be the input the the V2D program. To run this from the command line (assuming you've add it to your path, or it is in the same folder) use:" v2d filename.swf".

If you have downloaded the source, you can also run it from VisualStudio 2008 Express (free edition). Make sure VexTo2DPhysics is set as the startup project (right click the project in the Solution Explorer). Right click the project, select properties, and select the 'Debug' tab. Under 'Command Line Arguments' add the path to your file. Then hit F5 to run.

Output

V2D generates a swfFileName.as file, which contains movieclip, shape and joint data. This data is used by your Flex program to create the Box2D world. This data is converted to an Actionscript file (for now, the data is in AS3 arrays, objects etc). Ultimately the data will with platform independent and will include vector data (a small step once the format stabilizes). The runtime code then reads this data, and creates the objects as appropriate.

It is possible to glue all these steps together with JSFL or Ant.

How to Create the Template Swf File

You create layouts much like you create Flash files. First you create definitions (Symbols), and then you drag them on the stage to create instances. These symbols are little bit specialized, as they also contain the shape definitions of a body (as red outlines). Joints are created by dragging special 'joint' objects on to the stage. These are identified by name - so for example any symbol named "gearJoint" will be considered a gear joint. So be sure to drag the folder called 'Joints' into your Flash file.

Unless otherwise specified, joints will attach to the objects they are over. To set min and max ranges of joints, you use frames two and three. Frame one is always the initial position, frame two the minimum extent, and frame 3 the maximum extent. Lastly you can add specialized settings with actionscript in frame one. If you name the instances, you can add code like: myPully01.density = 3;, and it will be added to the runtime object.

This generator is currently fairly picky, so looking at existing templates is the way to go : ).

Backgrounds

If you drag a regular flash movieclip onto the stage (without special shape definitions), it will be added to the runtime as a regular flash movieclip (it will not interact with physics elements in any way). Scale, rotation and color transforms will be applied. You can access this clip using the instance name you gave it on the stage, in movieclipMap[instanceName]. If you don't wish to have runtime access, you do not need to give it an instance name.

Body Definitions

Body definitions contain two parts, a visual part, which is a movieclip, and one or more shape parts, which defines the convex polygon around the shape. These elements are wrapped in a movieclip to complete the definitions, which can be placed and transformed on the stage as many times as required. The instance on the stage can be given an instance name. This name is used to access the body definition at runtime (bodyMap[instanceName] -- a b2Body object), as well as the movieclip visual (movieclipMap[instanceName]).


Movieclip

The movieclip is what is actually viewed when the engine runs. It can be any valid Flash movieclip, including animation, sound etc. It must contain at least one element that is not a 1px red line with no fill, as that is how shapes are defined. If a visual movieclip is not present there will still be a physics object created, just it will be invisible.

Shape

Shape data is defined using red lines with no fill. The width must be 1 or less. The lines must be straight (if curves are accidentally added, only the end points will be used). As always with Box2D, the shapes must be convex (there is currently no check for this in the code). To simulate concave angles, multiple shapes can be added. These need to be at least grouped or layered separately, or flash will merge them into a single object. There can be a maximum of 8 points per shape without modifying the Box2D code. If a shape isn't present, the object will just be added as a regular movieclip, with no physics applied.

There is also a special shape in Box2D, a circle. This can be defined by using the special 'circleShape' movieclip, and sizing it as needed.

The simplest way to define shapes is using the Pen tool, clicking on all the corner points, finishing at the starting point. Then select this shape and group it before adding a second definition. There is no need to make these shapes into symbols (though that is allowed too), as they will be converted to a set of points and not appear in the runtime file.

So a typical body definition is a Movieclip that contains one visual movieclip (the one you will see) and one or more groups of red outlines with no fill, representing the bounds of the shapes.

Instances

You create instances of Body Definitions just like you create instances in Flash. Drag them onto the stage, and give them an instance name if you want to reference them later in code (in movieclipMap[instanceName]). Instance names are also used to resolve some types of joints. You can apply rotation, scale, and color transforms to the instances as well.

If instance names start with "s_" the instance will be fixed to the background (it will not move, but things can still collide with it).

Actions

Currently only assignment actions are available (there is a full bytecode parser in there, so more is possible if needed). They should appear on frame 1, and take the form instName.property=xx; Other code is allowed, but will be ignored. These will be applied to the object on creation.

Complex objects, like {x:50, y:20}, must be passed as strings. To differentiate between these objects and regular strings, they must begin with the pound sign. So it needs to look like: inst.prop = "#{x:50, y:20}";. You may recognize this as a big fat hack. It is. On the plus side, script is never a requirement, and generally it is a better idea to do these things in your program anyway.

The specific Box2D properties are also recognized, so for example it is possible to set the body2 property of a joint, or the torque of a body. The action properties will always override visually generated properties. This is useful when you have many overlapping shapes, or joints that don't touch shapes. You can also set properties such as density, friction and restitution, which don't have visual equivalents. To set defaults for such properties, use 'world' (eg, world.friction=1;).

Lastly, you can also apply custom properties, these will be added to the movieclips or userData, depending on where they are applied.

Joints

As far as possible, joints are defined visually. This is done by dragging the appropriate joint symbol on to the stage overlapping the object you wish to hinge. The joint symbols will not be exported to the final runtime file.

Instance names are usually required, in order to tell the difference between various joints.

Distance Joint

Distance Joints bind one object to another and maintain the distance between the two points as objects move. They are set using two distanceJoint symbols. These two distance symbols should have the same instance name (this is a mistake in a flash file, but fine for this use as these symbols are for information only, and discarded in the final file).

Required Information

  • What two objects are to be tied together? This is set by default based on which object each joint symbol is over. If a joint symbol is not over an object, the joint will be a pinned to the background. As always, this information can be overriden in code with jointName.body1=bodyInstanceName;
  • Where should the joint attach to on the body? The joint will be attached to the exact location it is over.
  • How far apart should he distance be? This is based on the distance between the joint symbols. To override this, set the 'length' property, jointName.length = 100;.

Optional Parameters

jointName.body1 = instName;
jointName.body2 = "instName"; // can be quoted too, either way
jointName.location="#{x:0,y:0}"; // note a complex object is in a string, that is preceded by a pound sign.
jointName.location2="#{x:10,y:10}"; 

jointName.dampingRatio = 1;
jointName.frequencyHz = 1;
jointName.collideConnected = true;
jointName.dampingRatio = 1;
jointName.dampingRatio = 1;
jointName.density = 1;
jointName.friction = 1;
jointName.restitution = 1;

Sample

 
Layout in Flash (download fla)   Generated Swf


 

Revolute Joint

Revolute Joints are joints that allow one object to revolve around another. They are set using a single revoluteJoint symbol . If the revoluteJoint symbol's center point is within the shape bounds of two instances, they will rotate around each other at that point. If it only touches one object, it will be pinned to the background and rotate around that point. As always, you can select the two bodies with simple assignment code, and this will override any visual settings. The maximum and minimum angles or rotation are set in frames 2 (min) and 3 (max). Frame 1 always represents the start position, and if there is only one frame, the rotation is not constrained.


Required Information

  • What two objects are to be tied together? This is determined by the first two objects that the joint instance is within. If the two objects do not overlap, at least one of them must be set by code (jointName.body2=myInst;). For a single object pinned to ground, only one object needs to be overlapped/specified (unspecified always defaults to ground).
  • Where will the center point of the revolution be? This is always the location of the revolute joint symbol.
  • How can the amount of rotation be constrained? This can be specified visually by using frames 2 (min) and 3 (max). Only one of the objects will rotate, the second is fixed relative to the first. A few tips:
    • it is easiest if the rotating object is on its own layer, and it needs to have an instance name
    • it is helpful to set the rotation point of the object to the revolute joint symbol location (then it rotates on that point)
    • you can edit multiple frames, or turn on onion skinning to see how the rotations look relative to each other and the background.
  • How can the joint be made to turn automatically? By assigning a value to motorSpeed in the first frame's actionscript. jointName.motorSpeed = 10;

Optional Parameters

jointName.body1 = instName;
jointName.body2 = "instName"; // can be quoted too, either way
jointName.location="#{x:0,y:0}"; // note a complex object is in a string, that is preceded by a pound sign.

jointName.min = -1.1; // minimum rotation relative to the original object, in radians.
jointName.max = 1.1; // maximum rotation relative to the original object, in radians.
jointName.enableLimit = true;
jointName.maxMotorTorque = 10;
jointName.motorSpeed = 0;
jointName.enableMotor = true;

Sample

 
Layout in Flash (download fla)   Generated Swf

Prismatic Joint

Prismatic Joints are joints that allow objects to slide relative to each other along an axis. They are set using a single prismaticJoint symbol . If the prismaticJoint symbol's center point is within the shape bounds of both object instances, the two objects will slide relative to each other. If it only touches one object, it will be pinned to the background. you can specify the second object (or both) with simple assignment code, and this will override any visual settings. The axis and extents of the slide are set in frames 2 (min extent) and 3 (max extent). The axis will always be the slope between the object in frames 2 and 3. Frame 1 always represents the start position.

Required Information

  • What two objects are to be tied together? This is determined by the first two objects that the joint instance is within. If the two objects do not overlap, at least one of them must be set by code (jointName.body2=myInst;). For a single object pinned and sliding relative to ground, only one object is needed (unspecified always defaults to ground).
  • Where on the sliding object will the axis pass? The sliding object will always be fastened at the location of the prismaticJoint. Note that the axis is determined by the objects in frames 2 and 3. Ideally these three objects form a line, but if they don't, the line is set by frames 2 and 3, and that segment is moved perpendicularly to itself until it meets the start point
  • How can the amount of slide be constrained? The object will never slide beyond the objects in frames 2 and 3. To view this all at once, you can edit multiple frames, or turn on onion skinning.
  • Can the object be made to slide under its own force? Yes, by assigning a value to motorSpeed in the first frame's actionscript. jointName.motorSpeed = 10;

Optional Parameters

jointName.body1 = instName;
jointName.body2 = "instName"; // can be quoted too, either way
jointName.location="#{x:0,y:0}"; // note a complex object is in a string, that is preceded by a pound sign.

jointName.min = -1.1; // minimum rotation relative to the original object, in radians.
jointName.max = 1.1; // maximum rotation relative to the original object, in radians.
jointName.axisX = 1; // this sets the x value of the slope (y/x)
jointName.axisY = 0; // this sets the y value of the slope (y/x)
jointName.enableLimit = true;
jointName.maxMotorTorque = 10;
jointName.motorSpeed = 0;
jointName.enableMotor = true;

Sample

 
Layout in Flash (download fla)   Generated Swf

 

Pulley Joints

Pulley Joints work much like a real life pulley. There are four points that need to be set, the two for the pulleys, and the two for the objects hanging from them. To set the hanging objects, drag them on to the stage, and then add a pulleyJoint symbol where you want the 'rope' to be attached. There are always two pulleyJoint symbols (because there are two dangling objects), so the pulleyJoint objects need to be given instance names -- if there were two pulley systems, there would be four pulleyJoint symbols, and it would be impossible determine which ones are meant to go together.

The actual pulley locations are set on frame two. Think of these as the 'minimum' distance the pulley rope can be (and frame 2 is always for 'min' values). This is set by moving the hanging object to pulley location on frame two. Note that in actuality, there is a minimum length for that rope set by Box2D. It is actually 2 meters, which is quite large. Due to this, you may feel it is more accurate to use the pulleyJoint symbols on frame two. Either option is supported. Also, if you find that a minimum distance of 2 meters is still a little long for what you width to do, you can set the world scale to be lower. The default is 30, so if you set it to 15, then the minimum is only one meter (yes, that is kind of cheating). You can do this by adding: "world.scale = 15;" to frame one's actionscript. Gravity will automatically be adjusted to remain earthlike when adjusting scale (unless set manually of course).

The axis will always be the slope between the object in frames 2 and 3. Frame 1 always represents the start position.

Required Information

  • What two objects are at the end of the pulleys? There are two pulleyJoint symbols required on frame one. Normally each joint overlaps an object, and these become the two objects dangling at the end of the pulley. As always these can be specified manually in actionscript, using jointName.body1=instName; and jointName.body2=instName;. The ropes are attached to the objects at the location of the pulley joints.
  • Where are the pulleys located? These are set on frame 2. They can be set with either repeated objects, or repeated joints. Which ever is used, it is the center point of these objects that determines the location.
  • What is the total lengths of the ropes? This is the distance between the pulley and the first joint definition. There is an automatic minimum rope length of 2 meters. The maximum length can also be manually set in code, using maxLength1 and maxLength2.

Optional Parameters

jointName.body1 = instName;
jointName.body2 = "instName"; // can be quoted too, either way
jointName.location="#{x:0,y:0}"; // note a complex object is in a string, that is preceded by a pound sign.
jointName.location2="#{x:0,y:0}"; // manually specify the second attach point location

jointName.groundAnchor2 = "#{x:0,y:0}"; // manually specify the first pulley location
jointName.groundAnchor2 = "#{x:0,y:0}"; // manually specify the second pulley location
jointName.maxLength1 = 1; // specify the maximum length of the first rope
jointName.maxLength2 = 2; // specify the maximum length of the second rope
jointName.ratio = 1; // specify how much faster one rope will move relative to the other.
jointName.collideConnected = true; // the two object will collide off each other if this is true

Sample

 
Layout in Flash (download fla)   Generated Swf


Gear Joint

A Gear Joint is used to allow two existing joints to interact with each other. It can be applied to revolute or prismatic joints. As one moves, the other with move in the opposite direction. Like the pulley joint, gear joints do not have to affect each other in a 1:1 ratio. This ratio can be controlled with the 'ratio' property, and can be negative. jointName.ratio = -2;

Required Information

  • What two objects do the gears control? There are two gearJoint symbols required on frame one. Both of these should be given the same instance name. The top most objects that the joint instances are over will be the two geared objects. The objects should both be revolute or prismatic joints (or one of each).
  • What joints to they apply to? The first (topmost) revolute or prismatic joint will be chosen on each object. If there are multiple joints, you can specify this in code (joint1, joint2).

Optional Parameters

jointName.body1 = instName;
jointName.body2 = "instName"; // can be quoted too, either way
jointName.joint1 = jointInstName; // manually specify first joint
jointName.joint2 = jointInstName; // manually specify second joint
jointName.ratio = 1; // how much the first object moves compared to the second. Negative values will change the direction of the slide or rotation.

Sample

 
Layout in Flash (download fla)   Generated Swf


Mouse Joint

todo.

 


Future Development

- Finish the Flex code (eg, each object should be able to be created and destroyed independently, integrate with DDW game framework etc).
- Add error reporting
- Make data format (xml and binary) rather than code gen - doc this format
- generate images from vector/bmp data (using ASDraw format, merge these formats)
- auto wrap objects with shape data
- auto split shape data with concave angles
- Make a version for XNA, or C++
- Make a version for a non Box2D engine
- optimize the Box2D code for AS3
- Make an IDE that isn't Flash based (.Net or SWT)
- explore a possible version for a 3D engine