If you take a look to the list of the top games in the markets, flash-games portals,etc, what can you see?, there are a lot of 2D games with an outstanding use of physics and visual arts!.
We are here today to study the physics of those games and to understand what are they made of, with Box2D.
But, more than the "what", it is much better to know the "how", first of all, let me ask you a question: if you would have to replicate a physics game mechanic or behaviour, will you have the skills and techniques to do so?
...I asked myself this same question more than a year ago, and the game 6 Dimensions is the answer ,it is a creative box where each dimension contains a different set of game mechanics using Box2d physics, mixed with visual art techniques, that I am sharing with you, because I made this game to improve a game engine called Codea (the guys from Crabitron), and finally, to write tutorials like this, where I wanted you and me to learn about realistic physics, art and game design...,together we are going to improve our game development skills.
I have designed 6 dimensions in my game, I'm using the same idea like a process capable of bring to your mind how are made features, so, before you say anything I'm writting near the dimension , the games from which we are replicating its physics, mechanics and art techniques.
1.The SHAPE Dimension
Thomas was alone, Angry Birds, Crayon Physics
In Crayon Physics: you can craw something in the screen with your fingers or the mouse, for example a circle, a triangle or a rectangle,and, as you release the mouse/touch, the lines will turn into a solid physical object (in the virtual world).
How do you do that?
It is pretty simple actually, you have to save each point coordinate of the trace from the mouse/touch start to end, when the release event occurs, then you call to a function of Box2D that creates a polygon with a serie of points, something like this:
local body = physics.body(POLYGON, unpack( points ) )
You have to know that there is some kind of shape types in Box2D :
used for closed shapes like basic geometry (not circles), it uses a list of vertices (x,y) defined with the order specified by each API
balls, water drops, planets, etc.
for walls, grounds,etc, Lines with only 2 points: start and end.
Like edge but you can close (would be like a POLYGON but is not a convex hull) or not (like EDGE but with more than 2 points)
Once you have defined a body shape, there are different behaviours,or body types:
- STATIC : as it names says, this body will remain static in the assigned x,y (ground, wall, base for a pole or rope,etc.)
- DYNAMIC : it will collide with other objects and move
- KINEMATIC : collide but not move with the dynamics, you can move it not only chaging it x,y but assigning a linearVelocity or applying a force to it too
You have to save the result of that function to a var, then, in the draw loop of the game the properties of that body are accesible, like body.position, body.radius, body.linearVelocity, body.angularVelocity, body.mass, etc.
When the body is created, you may want to define some of its properties, there are interesting things like the restitution,gravityScale and damping, these can turn our physical object into a bouncing or floating one, for example.
Here is a sample of what can be done with this feature of Box2d.
At this point you might want go to the Ray Wenderlich site and follow some of the box2d tutorials and then come back and continue reading with more knowledge...or no.
There are more complexity in Box2D and other games ( Magic Pen ) within this dimension of physics game mechanics, you can draw some things that look likes "nodes" but developers call them "joints", this things are used to put magic glue between bodies, there are some kind of them, depending on the mechanics you want (Codea reference for physics with Box2d , or the Nature of Code videos - processing) and they can be used to create a behaviour between the connected bodies:
- physics.joint( REVOLUTE, bodyA, bodyB, anchor )
the bodies rotate about a single anchor point
- example : a wheel of a car, the red node in crayon physics and magic pen
- physics.joint( PRISMATIC, bodyA, bodyB, anchorA, direction )
the bodies maintain a fixed distance between their respective anchor points. The length of a distance joint is taken from the initial distance between the two anchor points in world space. Setting the frequency and damping ratio of the joint allows for soft spring-like behaviour.
- physics.joint( DISTANCE, bodyA, bodyB, anchorA, anchorB )
Prismatic joints constrain the motion of two bodies along the axis between the two specified anchor points. This allows for telescopic motion, while restricting relative rotation between the two bodies
- physics.joint( WELD, bodyA, bodyB, anchor )
Weld joints constrain the motion and relative rotation between two bodies, effectively turning them into a single body. Due to the iterative nature of the solver, weld joints can bend when put under stress and may fail completely when large forces are involved or several weld joints are chained together to form a larger object
- physics.joint( ROPE, bodyA, bodyB, anchorA, anchorB, maxLength )
Rope joints constrain the maximum distance between two bodies
Example: the ropes of Cut the Rope
1) Create: a body with the points of the touch or a box definition or any other polygonal geometry (a set of 2d points:x,y), set physics properties for what we want it to (different behaviours like Thomas was alone are possible), like if the body is static, it mass, density, gravityScale, and so on.
3) Optional: attach to another body, for example, you can attach the body to a static body which is set as a sensor (not affecting world physics but has collision events) and activate the enableMotor property of the REVOLUTE joint, this also needs motorSpeed, maxMotorTorque and maxMotorForce, defines a rotation for this object. This is a result (dont pay attention to the water, we are going into it next).
3) Visual Art: You have the body, if you want to draw it, not as a shape but like a filled body with color or a texture you may want to triangularize the points to create a POLYGON-shape (mesh) and set the colors or the texture to it.
For the behaviour of boxes from Thomas Was Alone you can set a simple "juice" system animation (evolution of tweeners), so, when you choose a cube and press the jump button (or the collision with the different physics bodies happens), it triggers the juice command = animation like squash, roll, etc., each character has its own animation params, the same goes for physics: mass, linearVelocity, damping, etc.
Angry Birds, (Ray Wenderlich has a tutorial to make that too) , you can create a level by defining different properties to the boxes, draw different sprites or meshes with textures, so, in the collision events you can drown an amount of the "life" or "resistance" of the box-body and change the texture with another one, more appropiate to the current state (broken wood, almost broken glass, broking sprite animation,etc).
You can do the launching of the bird with a simple body:applyForce(vec2(x,y)) function. Each bird has it own mass, damping, info and properties as well...
2.The WATER Dimension
Where is my water? , Sprinkle Ilsands...
When you ask to the Internet coding sages how to make water physics like those games, they end up talking you about Metaballs:
But using metaballs in a game is not so trivial and not too easy to get neither, it has high computational cost, unless you discover some trick and apply it with some art.
That's why you dont see so many games with water physics. I started talking about this some months ago in this forum, and thanks to a lot of people I get a good water physics model for a game.
You can get it here,in the example I am using dynamic balls with CIRCLE bodies from Box2D lib (code inside videolink).
The code is easy to understand, look, the balls are just physic bodies generated with parameters to give them the behaviour of water drops, it is: restitution, friction, damping, linear velocity, then, to draw these balls we are using a technique with a shader (GLSL) and a texture, you will need a mesh to apply the shader, just like a ripple fx or other glsl shader samples that uses textures, we are setting the width and height of the area of the mesh to the whole screen, from the middle:
mesh:addRect(WIDTH / 2, HEIGHT / 2, WIDTH, HEIGHT)
this way we can use the (x,y) position of each ball to paint in the virtual space of the texture (with setContext) of the mesh rect, so, each ball is represented in the texture as a ball painted with a gradient inside the image generated of the ball (200*200) -ballTex -
for k,b in ipairs(balls) do sprite(ballTexture, b.x, b.y) end
then , you have to use the additive blend mode to add all the painted balls to the texture and mix them with a background and a colour.
As I said, each ball has a texture (procedurally generated) , a gradient, this was it can be mixed with other ball textures using a low level filter (the glsl shader).
Where is my water?
You can do the same water fx using different layers for each type of behaviour, or make one layer for all the liquids and one for all the dynamic terrains, then in the shader change the filter values and colors (water, lava, dirty,etc.).
An example of handling the collision within a behaviour can be:
In the collision events you must check what kind of ball is bodyA and bodyB, if one is gas (gravityScale/mass/density is practically zero, so it floats) and the other body is an "ice" polygon, then you turn the ball into water...
if bodyA is lava and bodyB is water, you must turn bodyB into gas, ...it is as easy as change the properties of the ball, so it will change the response in box2d and you do the new drawing the drawLoop of the game.
the static terrains could be just a POLYGON body created with a function that read an image of the whole terrain and build a set of pairs x,y (vec2) of the non-transparent pixels, then return this to the box2d function.
Dynamic terrain could be just a mesh and when you touch it, you will remove the points over that coordinates x,y of the touch, you have to rebuild the physics body with the new set of pairs of the mesh.
And you have just see how to create the water so, here it is an example with all together: water physics and real time terrain modification based on box2d physics.
Pickups, powerups, etc. example:
When a drop of water (physics body CIRCLE) hit a duck (physics body with sensor activated) you must delete that ball and change the animation of the duck for the new state ,until it is completly filled with water, then delete the duck and record the achievement.
Water drops have a little trail,these are drawn using the linearVelocity and angularVelocity properties, you can get the direction and the speed so you can calculate the angle and distance of the trail (opposite direction and distance based on speed).
In fact, there are as many behaviours as you want.
In Sprinkle Ilsands the water shader is different as the one we have studied, only changes something with the particles fx, it has the linearVelocity detail added too, in another way.
But the behaviour could be the same, when the water balls (physics body CIRCLE) hit a fire sensor , it applies whatever it makes the fire goes down, the same for a water mesh in the sea, in the case of a rock you could add some details like particle effects or something like that.
In this dimension we can't find any joint, that's why it may be not necessary, well, in Sprinkle Islands the hose is a rope, which we are going to analyze in the next dimension, and there is a REVOLUTE joint in the hose cone...
3.The ELASTIC Dimension
Contre Jour, Cut the Rope, Ninja Fruit,...
It took me another month to have a working prototype of a rope like those top games...see this one (code inside the video info), but the soft body was easy made once I got the rope finished, as I understand the joints better.
To make a realistic rope you have to create a set of bodies (CIRCLE or POLYGON,your choice) all attached to a STATIC body, the base. The joints used to joining the bodies of the rope can be of two types, DISTANCE or REVOLUTE, but the joint that join the base (STATIC) with the final part (DYNAMIC) must be a ROPE joint to create an elastic rope. Use the restitution property and frequency (hz) to adjust the response/damping/elasticity.
Here is the ROPE (code), and this is the result (video).
To create a soft body, you have to build a set of CIRCLE bodies around another center body (circle is better), which can be STATIC or DYNAMIC, it will affect the rest of the bodies for sure, if you change the types of the joints you will realise how the body can be deformed automatically, you need to draw the whole set with a mesh.
In this game, you can find soft bodies: deformable terrains; and two types of ropes:elastics and ropes with a limit, fixed. These fixed ropes uses a more advanced technique than the elastics, to draw the texture in it shapes you have the properties of the bodies and the joints, i.e., points, types, properties, etc., the method must build a mesh and apply the texture in real time, like in the previous example of the video of the soft body but these guys do this thing better:
Take a look to this: the tech behind the visual art of Contre Jour.
Cut the Rope
This is the perfect example of an Box2d physics set for a rope, the texture is dynamic also, and you can notice the weakness of it in the colors used along the mesh from the base to the ball, where it is attached the sugar.
You can build this rope as we have done in the previous example, the bubble effect can be achieved by setting the physics properties to the ball (candy): mass, density, gravityScale, it will float and you may draw the bubble after the candy with a multiply blend mode. Another way is change the body to a sensor and move it with your own gravity formula, but we are going to study this technique in the fifth dimension.
If the bubble-body-ball collides with the frog or the spikes, or the user touch the bubble, then you would animate the bubble explosion and change the physics properties of the candy again...
if (vec2:distance( bFrog_Mouth, bCandy ) < maxDistance) then
-- change animation of the frog from "idle" to "eat"
-- pause input
-- tween and trigger the end of game at the end of the animation
4.The GRAVITY Dimension
Tiny Wings, JetPack JoyRide, Madcoaster, Whale Trail, ...
You can make your own Tiny Wings with Box2d, there is a tutorial here, and another here, the basis is that, a ball (CIRCLE body) falls with the force of gravity, you can increase the linearVelocity by touching the screen, and when the touch is released in the appropiate part (you can check the height of your sine function) of a hill it would be better for that increase amount...Another way is using only forces.
For the draw loop, add particle effects to the picking, fever states (trails), and so on. The textures can be generated using procedurally images with random colors, gaussian noises to add details, borders, etc...you can see an example here.
You can follow the pattern for this game?, If you have readed the previous examples you must fall into account, you have the same behaviour for the character-body-ball (CIRCLE physics body or other you want),you must be applying forces against gravity, different physics properties for each jetpack, the missile and each vehicle, etc.
The same goes for Madcoaster, Rocket Chicken, Whale Trail and those kind of games...
But this dimension includes other mechanics, like the planetary physics, gravition is a strong field :)
You can use a simple formula to simulate zero gravity with physics.gravity(0,0), the force of attraction of a planet is something like this:
More in this example.
function Planet:attract(m) -- Direction of the force local force = self.body.position - m.body.position local d = force:len() -- = m.body.position:dist(self.body.position) force = force:normalize() local dir = vec2(self.mass/m.body.mass, self.mass/m.body.mass) -- Magnitude of the force local strength = (GRAVITY * self.mass * m.body.mass)/(d*d) force = force * strength m.body:applyForce(force) stroke((1+math.floor(force.y))*110, (1+math.floor(force.x))*110, 10, 255) -- draw line between attractor/mover line(m.body.x+force.x, m.body.y+force.y, (self.body.x), (self.body.y)) end
this function will make the character ball to move around a