Getting started with CoronaSDK and PhysicsEditor

2012-05-24 Andreas Löw Get Sourcecode from GitHub
Final project

Welcome to this complete tutorial for CoronaSDK and PhysicsEditor. You are going to create a small simple application which will drop several items and let them collide.

You are going to learn how to create different objects, set physics parameters and enable fixture based collision handling.

The complete source code to this example project is available on GitHub for you to download and play with.

You can use the demo version of PhysicsEditor for this project.

The assets

Let's have a look at the assets first: We have

Background.png
Background
Apple_00.png
Apple_00
Apple_01.png
Apple_01
Apple_02.png
Apple_02
Duck.png
Duck
Floor.png
Floor
Ball.png
Ball

Getting started with PhysicsEditor

If you do not already have it installed get PhysicsEditor for your platform and install it.

After starting the first thing to do is to set the exporter matching your project - which is Corona:

PhysicsEditor: set exporter

Next drop the objects to the left pane of physics editor to import them

PhysicsEditor: Import Sprites

The Automated Shape-Tracer

Now select the first apple image on the left pane and click on the Automated Shape-Tracer button ( that's the magic wand icon in the tool bar). This opens the Automated Shape-Tracer dialog.

PhysicsEditor: Automated Shape Tracer

The most important control in this dialog is the Tolerance setting. It defines how close the tracer tries to match the shape's outline. The closer the outline to the shape is the more vertexes will be added to the shape.

This is an important aspect for your game - too many vertexes might kill the performance because a lot of calculation time is needed. On the other hand a too high value will create a shape which becomes more and more rough.

It's important to find a good balance for this.

  • 04a-PhysicsEditor-TooDetailed.png
    Too detailed
    Tolerance = 1.0
    Vertexes = 44
  • 04b-PhysicsEditor-GoodTrace.png
    Good Trace
    Tolerance = 4.0
    Vertexes = 13
  • 04c-PhysicsEditor-BadTrace.png
    Low detail
    Tolerance = 10.0
    Vertexes = 6

Now press OK and see the final result in the main window.

Collision parameters

PhysicsEditor: Collision Parameters

Let's now set up the collision parameters. These paramters can be applied per fixture - which means that you can compose a shape from different polygons and set parameters for each of them.

First give the fixture a name - this allows you to identifiy individual parts of a shape later - E.g. the head of a character or other parts. For now type "apple" in the field called Identifier.

Next set the density. The Density multiplied with the area of the shape is the mass of the object. So you decice how heavy the object will be here.

Bounce is the elasticity of an object. An object with bounce=0.0 does not bounce, one with 1.0 is repelled completely from other objects. Set it to 0.3 for the apple.

Friction is the value which contols how objects slide on each other. A value of zero would make an object slide better than on ice. Objects slide less with higher values. Set it to 0.5.

IsSensor tells the object to detect but not to participate in collisions. That means that you'll get collision information but the complete scene behaves as if the object is not there.

Group sets groups for collision - only objects of the same group can collide.

Bit's name, Cat. (Category) and Mask also control the collision behavior of objects. The object's Category value defines what the object is, the object's Mask value tells it what it can collide with. The bit names can be defined like you want - they are just here to give them a better meaning than just assigning numbers. Set "fruit" for the apple.

Now trace and apply the same values to the other apples.

Setting a circle shape

The ball might be approximated by using a polygon but this would be a poor result. It is better to use the circle shape for that.

Corona SDK comes with one speciality: It does not allow setting the center of a circle shape. So if you want to use a circle you must make sure that the sprite is centered.

Now click on PhysicsEditor: Draw ellipse tool icon and use the small circular handle to adjust the size to the ball. Center the circle over the ball shape.

PhysicsEditor: Circle shape

Set the values according to the image.

Adding polygons manually

To avoid objects from dropping from the floor immediately I would recommend adding some walls to the left and right. For this select the floor sprite and click on the polygon tool PhysicsEditor: polygon draw tool icon.

This adds a small triangle. Drag it with the mouse. Doubleclick somewhere along a line to add a vertex. Doubleclick a vertex to remove it.

Adjust the polygon like on the next screenshot. Set the parameters according to the parameter panel.

PhysicsEditor: Polygon shape

Using a multi fixture body

The final shape is the duck. We are going to separate the beak from the body to be able to handle it differently in the collision detection.

Trace the duck as you did with the apple, then remove the beak's vertexes by double-clicking them.

Add a polygon and form the beak from them.

Set the identifier for the beak to "beak", for the rest of the duck to "body".

PhysicsEditor: Multi fixtures

Publishing

Finally press Publish and save the data file as shapedefs.lua. Also save the complete document in case you want to modify it later.

Let's code

Now it's time to dive into the code.

Let's first init the game scene - hide the status bar and activate physics simulation and add our background image:

-- init display
display.setStatusBar(display.HiddenStatusBar)

-- init physics
local physics = require("physics")
physics.start()

-- background image
local bkg = display.newImage("Background.png")

Next let's load the physics data we created before:

local physicsData = (require "shapedefs").physicsData(1.0)

You could set different scaling factory for the shapes to adjust to the display resolution. But this might also scale the object's mass resulting in different behavior.

Now add the floor shape:

-- create physical floor shape
local bar = display.newImage("Floor.png")
bar.x = 160; bar.y = 450
bar.myName = "Floor"
physics.addBody( bar, "static", physicsData:get("Floor") )

This loads the Floor.png, sets it's position and attaches the Floor shape as static body. Easy, isn't it?

The name is used to identify the object during the collision handler later.

Now add a function we can call from a timer to create new items:

-- create a random new object
function newItem()	
    
    -- all items
	local names = {"Apple_00", "Apple_01", "Apple_02", "Ball", "Duck"};

    -- just pick a random one
	local name = names[math.random(#names)];

	-- set the graphics 
	obj = display.newImage(name..".png");
	
	-- remember object's type
	obj.myName = name

	-- set the shape
	physics.addBody( obj, physicsData:get(name))	
	
	-- random start location
	obj.x = 60 + math.random( 160 )
	obj.y = -100
	
	-- add collision handler
    obj.collision = onLocalCollision
    obj:addEventListener( "collision", obj )
end

This function chooses from an array of items and selects a random one. Then loads the according sprite and also assigns a name to it.

This time the body is added as dynamic body - simply by omitting the static parameter.

Also choose a random position somewhere above the scene and finally add a collision handler.

Finally add the collision handler - it will not do much right now - except for printing the collision objects and parts that collide.

The collision event contains the number of the fixture. Use getFixtureId method to retrieve the identifier we set in PhysicsEditor:

local function onLocalCollision( self, event )
    
    -- retrieve fixture names from physics data
    local selfFixtureId = physicsData:getFixtureId(self.myName, event.selfElement)
    local otherFixtureId = physicsData:getFixtureId(event.other.myName, event.otherElement)
    
    -- print collision information
    print( 
        self.myName .. ":" .. selfFixtureId ..
        " collision "..event.phase.." with " .. 
        event.other.myName .. ":" .. otherFixtureId
        )
end

That's it.

Final project

You can download the source code or clone it from GitHub. Have fun!

Did you like the tutorial? Please share!

Source code available for download

The source code is available on GitHub. Clone it using git:

git clone https://github.com/CodeAndWeb/PhysicsEditor-CoronaSDK.git

or download one of the archives:
PhysicsEditor-CoronaSDK.zip PhysicsEditor-CoronaSDK.tar.gz