Welcome to the next part in our ongoing Defold Game Engine tutorial series. In this tutorial we are looking at working with the integrated Box2D physics engine built into the Defold engine.
As always there is an HD video version of this tutorial available here or embedded below.
The Defold engine makes it extremely easy to work with physics but is rather minimal in it’s implementation. Let’s jump right in.
Creating a Collision Object
The heard of implementing physics in Defold is the Collision component. This is composed of two part, the Collision Component that describes the physical attributes of a game object, and the Physics shape, which defines it’s dimensions. I start off by creating this simple Gameobject, the image used in the sprite is 128×128 pixels:
Now we simple add a new physics component to the game object. Right click the Game Object in the Outline, select Add Component, then select Collision Object:
Here are the default properties of a Collision Object:
Type is important and we will cover that shortly. Mass is the weight of the object relative to dimensions, friction is how one surface reacts to another ( think traction ), restitution is the “bouncy-ness” of an object, linear damping and angular damping determine how motion of the object degrades over time, locked rotation determines if the physics simulation will rotate the attached game object or not. Group and Mask are used to determine which collision objects interact with other collision objects. Objects in the same group will collide, while objects not in the same group, or if that particular group isn’t added to the Group value ( comma separated ) will not interact. So think of Group as the physics identity or type(s) this object belongs to, while Mask is the groups that object will interact with.
Next we need to define the shape of our physics object. Simply right click the Collision Object and select Add Shape:
Next pick Box:
In the properties, set the Width and Height to match the size of our source image. Depth is the value along the z-axis and can be left at the default value in most cases.
Now that we have our Collision object define, simply create a couple instances of our game object in the scene and the results are immediately demonstrated.
You probably didn’t want the boxes just dropping out of the world now do you? So we need to create a physics body for the “floor”. We can easily do this by creating a new Game Object in main and adding a physics body to it. Like so:
The problem here is, our newly created floor will be effected by gravity, just like every other object in the scene! This is where the Type of the Collision Object becomes important:
So far we have only used the default, Dynamic. A dynamic object is a fully simulated physics object. It will take part in the simulation, will be part of the simulation and will be affected by the simulation. Static is what we want in this situation. A static object will be part of the simulation, but will not be effected by it. This is your proverbial unmovable force! So other objects in the simulation will be able to hit the collision object and they will be affected by the collision, but the static object will not be changed in any way. Kinematic objects are special objects that are generally moved directly by the character or code but also take part in the physics simulation and will be affected by it ( think that players sprite for example ). Triggers on the other hand are simply shapes in the world that can detect a collision and can be hit, but wont have any affect on anything in the world. They are often used to detect movement, for example the goal area in an air hockey game.
Now with our floor object set to static, our updated results!
So, how exactly do we control global physics properties, such as gravity? These settings are available in the .project file:
Physics and Code
Now that we know how to set up a physics simulation, let’s look at how to deal with it in code. For we are going to look at how you respond to a collision in code. As you might be able to guess, messages are used. Let’s look at a simple program that responds when a collision occurs. Attach a script to your box object and add the following code:
function on_message(self, message_id, message, sender) if message_id == hash("contact_point_response") then msg.post("@render:","draw_line", { start_point = vmath.vector3(message.position.x -40, message.position.y - 40, 0), end_point = vmath.vector3(message.position.x +40, message.position.y + 40, 0), color = vmath.vector4(1,0,0,1) }) msg.post("@render:","draw_line", { start_point = vmath.vector3(message.position.x -40, message.position.y + 40, 0), end_point = vmath.vector3(message.position.x +40, message.position.y - 40, 0), color = vmath.vector4(1,0,0,1) }) end end
This code simply listens for the contact_point_response message which is sent when a collision occurs with the attached game object. When such a collision occurs, this code draws an X centered about the collision point by sending the draw_line message to the render subsystem.
There is a great deal of information about the collision passed along in the message parameter:
As you can see, information on what object was collided with, how fast, groups, velocity, mass etc are all available in the contact_point_response message.
On final topic to cover is occasionally you are going to want to be able to apply force directly to a physics object using code. This is also easily accomplished using the following code:
msg.post("#collisionobject", "apply_force", { force = vmath.vector3(0,5000,0), position = go.get_world_position()})
Again using Defold’s messaging system, we send the apply_force message to our Collision Object component. This applies 5000 newton of force along the Y axis. Added inside our collision handler, it makes for some interesting results!
The Video