Getting started with Shape Workshop
Introduction to physics on the iPhone - Creating a scene in ShapeWorkshop
Now we have Cocos2D setup it's time to create our scene. For simple objects (squares and circles) it's just about possible to create a Box2D scene programatically. For anything more complex, you need to use a scene editor. I've written a scene editor called ShapeWorkshop and in this part of the tutorial I'll explain how it can be used to create your level. First you need to visit this page and download the Beta version of ShapeWorkshop. If, while working through this tutorial, you find any bugs you can report them on this page anyone who reports one bug will get a half price on a pro license of Shape Workshop when the stable version is released. Anyone who reports 4 or more bugs will get a free license.
After you've downloaded ShapeWorkshop fire it up and you should see two windows. One is the canvas and the other is the control panel.
The canvas gives you a space to work on your scene. Here are the main Canvas controls:
- Left click element: selects the element
- Left click canvas: deselect all the elements
- Left click drag canvas: pan the canvas
- Left click one or many elements: move the elements around
- Right click drag: create a selection box to select multiple elements
- Right click on element: incrementally select elements
In the canvas tool bar you can use the zoom to fit control to zoom in on all the objects in the scene or a group of objects. The X and Y position and rotation boxes can be used to fine tune the position and rotation of nodes. You can also lock nodes using the "Lock" check box. This is very useful when you want to display a background image and you don't want it to be clickable. Once a node is locked, use the object list in the control panel to select it again if you want to unlock it.
This other box that appears is the control panel. It gives you a whole range of options for controlling your scene. In this tutorial we're going to touch on most of them. I'll provide more details later.
|Figure 1: The control panel|
Adding objects to the scene:
First we're going to add our objects to the scene. You will need to download the images folder here. Click the "Load path(s) from SVG" button and select jug.svg from the bundle provided. This should load a jug, knife and fork and a plate. Both the images and the paths are automatically generated. The outline points show the outline vertices of the object. For curves, the number of points in the curve can be modified by using the "Refine" button.
Next, click the "Load Sprite" button. Add the following images from the resources bundle:cake.png, icecream.png marshmallow.png, raspberry.png, strawberry.png and table.png.
|Figure 2: Scene after importing elements|
Arrange the images as shown in Figure 2. Image files don't have an outline by default. In order to add them to the simulation we need to create an outline by tracing the image.
Box2D body types:
At this point i think it's worth explaining a bit about Box2D. Box2D has three types of bodies:
- Static: Static bodies don't move at all. They're useful for creating level scenery. Usually static bodies are made using something called a chain. This is a kind of object can be concave or convex and can have any number of points. The only caviat is that it can't move. For static objects this isn't a problem.
- Kinematic: Kinematic objects can move but don't react to forces. They are used for moving scenery like moving platforms. You set their velocity and they will continue at that velocity forever. Chains are also commonly used for kinematic objects too
- Dynamic: Dynamic bodies move and are affected by forces. They will bounce off surfaces and are affected by gravity. In Box2D any dynamic objects need to be convex and have fewer than 8 points. This is very limiting and it's obvious that our scene doesn't fit the bill. Luckily, Box2D does support having more than one shape per object. That means that we can break down our complex shapes into a number of smaller convex polygons. We'll do this using the "Triangulate" button.
Configuring the scene:
Now that you know the basics of Box2D it's worth thinking about how our scene will work. The table will be static as will the knife and fork. These objects are just scenery. The jug will pour at a pre-determined rate this means that it can be a kinematic object. All the other shapes must be dynamic. This means that we need to triangulate the marshmallow, the cake, the ice cream, the strawberry, the raspberry and the bowl.
Tracing the images:
|Figure 3: Initial trace|
Before we can triangulate our dynamic elements we need to trace them. Select the 5 images (don't select the bowl. It's an SVG image so it already has an outline) and click trace. You will get something like in Figure 3. The images are accurately traced but with a very high density of points in the outline. We want to tune the trace until we have the minimum number of points in the outline while still accurately representing the shape of the object.
|Figure 4: Better trace|
You should be able to end up with something like Figure 4.
Do the same with the table but bear in mind that only the top surface needs to be accurately traced. Nothing will be colliding with the legs. Also, remember that we won't be triangulating the table because it's a static object.
Note: Trace works by looking for a loop of transparency around the image. For this to work well, you need to make sure the image is clear on any artifacts and only contains one contignuous block of color.
Triangulate the elements:
Now we're ready to triangulate our elements. Right click the objects in turn to select them all and then click the "Triangulate" button. You should now see black triangles super-imposed on our images. This means that the triangulation has been successful. Sometimes the triangulation will fail because the geometry isn't supported. This can happen when there are co-incident points, loops in the outline or cusps. In these cases it's necessary to change the tracing or SVG parameters and re-triangulate.
If you notice that your bowl contains a large number of triangles you can reduce it's refinement. I found that the bowl worked fine with a refinement level of 20. Select the bowl adjust the "Curvature tolerance" slider to 20 and click "Refine". The triangulation should update but with fewer polygons.
Setting physics properties:
The final step is to set the physics properties or our scene. To do this click on the profiles pane. It's blank because no objects are selected. Select an object to activate the panel. This panel provides a really flexible way to add properties to your objects. We'll be using the two preset profiles: Body Defininition and Fixture Definition but it is possible to create your own profile and store custom data for your game.
|Figure 5: Triangulated elements|
Physics Properties in Box2D:
Before we continue I'm going to explain a bit more about Box2D. Box2D objects are divided into two parts: the body and the fixture.
So why do they split the object into two parts? The way to think about this is to imagine a car. The car is one body because all the bits are fixed together. If the car moves at 30 kph the windows, doors and tyres all move at 30 kph too. That doesn't however mean that all the parts of the car behave the same. If you hit the window it smashes but if you hit the tyre it does nothing. The tyre is grippy but the paintwork is smooth. In Box2D the car is represented as a body. It has a velocity, rotation etc... The parts of the car are fixtures. They all have different shapes, densities, restitutions and frictions. This structure means that in Box2D one body can have many shapes all with different physicsal properties.
Lets look at the properties available for our body definition:
- Fixed rotation: This determines whether the body is allowed to rotate freely
- Allow sleep: This is an optimisation feature. If allow sleep is enabled, when the body comes to rest it will start to sleep. While it's sleeping Box2D will perform fewer calculations on it which saves processing power. If another body hits it, it will wake up and continue as normal
- Velocity: This is the starting velocity of the body. The two commar separated number are the x and y components
- Active: A body which isn't active won't participate in the simulation. It won't move or collide.
- Awake: A body which isn't awake will sleep until it's hit by another object and brought into the simulation
- Type: We talked about this earlier: Static, Kinematic or Dynamic
- Bullet: This flag enables more rigorous calculations for high speed object to stop them passing through other objects
- Inertial scale: This effects how much gravity affects a body. i.e. a body with zero won't be affected by gravity at all. This feature doesn't work in the in-built simulator but does work on the iPhone and Android.
Now let's look at the fixture options:
- Sensor: A sensor don't collide with other objects but is registers when another obejcts hits it. This is useful for managing your game events. A sensor could tell you if your player entered a certain room by registering that the player had passed through the sensor
- Density: This essentially specifies the weight of the object. (To be exact the mass per unit area of the fixture)
- Friction: The degree to which the object slides over another object
- Category Bits, Mask Bits and Group Index: These are used for preventing collisions between certain objects
- Restitution: this determins how bouncy an object is. Specifically, if an object hits a wall, the restitution defines how much of it's velocity it will lose in the collision.
I've tried to keep these descriptions simple and real-worldy. They all have quantitive mathematical definitions
which can be found on Wikipedia of you're interested.
For this simulation we don't need to mess around much with these values.
Now, select all the objects and select the "Body Definition" profile. Then click "Activate Profile". Now click the objects individually and you'll notice that the Body Defintion profile is enabled.
Lets make a preset. Click on the table and set: body type to Static. Now at the bottom of the screen in the presets section type static in the name box. Then click "Add to presets". Now right click select all the static objects: the table, knife and fork; click the static preset, and click "Populate from preset". Now all these objects are static. Now click on the jug and set it's body type to Kinematic.
|Figure 6: After the simulation has been run|
Adding a tag to the Jug:
So we can make the jug pour we need to be able to access it programatically in Java or Objective C. The easiest way to do this is to tag the object. Click on the Tags pane and create a new tag called "jug". Next select the tag, and the jug and click "Add to path".
Running the simulation:
Click the start simulation button in the canvas toolbar and.... nothing happens. That's because there isn't any gravity. Stop the simulation then click on the "Levels" tab and set the gravity to "0, -10" now start the simulation again. You should see all the dynamic objects falling with gravity and bouncing off the static objects. Congratulations! You've created your first physics simulation.
Hopefully that worked and you should end up with as shown in the after image. If it didn't work go through this check list: trace, triangulate, enable body definition, set dynamic/static/kinematic, enable gravity.
Exporting to iPhone
|Figure 7: iPhone bounds config|
Finally we're going to lay the scene out for the iPhone and export the scene to XCode.
Open the "View" menu in the tool bar. Tick the "Show level bounds" box and set the iPhone screen dimensions:
- Width: 320
- Height: 480
- Scale: 2
This should show a black box which represents what will be see on the iPhone. Scale allows you to decide how big your objects should be in relation to the iPhone screen. The black box represents the iPhone screen. Layout your elements exactly as you would like them to appear on the iPhone. You should end up with a scene as shown in figure 8.
|Figure 8: iPhone bounds config|
Exporting the scene
Make sure the scene is saved. If you haven't already done so go File->save to save the scene in your desired location. Next click File->Edit project. In this screen you can choose the location where the iPhone data will be exported. Select the resources directory of your XCode project and click confirm. Next choose a name for your level. Click on the level tab and give call your level table_scene. Also make sure that "Export Level" is ticked.
Now open the publish menu. Make sure that "Export images" and "Pack images" are ticked. When they are selected Shape Workshop will automatically pack your sprites to a sprite sheet and export them to the publish location. Click "Publish to iPhone"
If you are working through the Introduction to physics on the iPhone tutorial series the next part is here: Part 4: Running your scene on the iPhone
Exporting to Android
As explained in the iPhone section set the level bounds to the bounds of your desired Android handset. Then set the android path. Currently Shape Workshop only supports LibGDX. In the examples section of the Shape Workshop download bundle I've included a LibGDX Box2D builder which will build a Box2D scene for LibGDX automatically. If you want to use a different game engine at the moment you would need to adapt the Box2D builder. It should be pretty straight forward.
As with the iPhone click File->Edit project and choose the directory of your android assets. The assets folder in the android project of LibGDX. Then click "Publish to Android".