Getting started
What is ExtremePhysics?
ExtremePhysics is a 2D rigid body simulation engine designed for Game Maker. The DLL is written in C++.
ExtremePhysics classes
ExtremePhysics uses a number of classes (types of resources):
-
World: This class connects the other classes. You can create multiple worlds but most of the time one world is all you need.
-
Polygon: Polygons are used to define the vertices of polygon shapes.
-
Body: A body is the equivalent an object in Game Maker. Usually every object in Game Maker is associated with one body.
-
Shape: Shapes are used to define the shape of a body. There are three types of shapes: box shapes, circle shapes and polygon shapes. One body can consist of multiple shapes.
-
Force: Forces can be added to bodies to simulate some effects, e.g. a rocket engine.
-
Contact: This is a special class. You can't create or destroy contacts, because contacts are created and destroyed automatically by ExtremePhysics during the simulation when different shapes collide. Contacts can be used to detect collisions.
-
Joints: Joints are used to connect bodies. There are multiple types of joints.
-
View: Views can be used to speed up the simulation for games that use views. Parts of the world that are out of view can be put to sleep to save processing time.
This image shows how the classes are connected:

Hint
All angles in ExtremePhysics are in radians.
Initializing ExtremePhysics
If you are using the DLL (instead of the extension), you have to initialize ExtremePhysics before you can use it. This isn't very hard:
// If the name of the DLL file is ExtremePhysics.dll,
// this should work:
extremephysics_init();
// If the DLL is not in the working directory,
// you can use this instead:
extremephysics_init("path/to/ExtremePhysics.dll");
Note that the game start event is executed after the create event, therefore it's a good idea to create an empty room (room_gamestart) with one object (obj_gamestart) that executes this code before going to the next room, to make sure this code is executed before anything else.
If you forget to initialize the DLL, you will get an error message when you try to use the scripts ("undefined variable global.define_ep_functionname").
Creating a world
Creating a world is easy:
global.world = ep_world_create();
After creating the world, you should change the settings of the world:
ep_world_set_settings(global.world,1,20,10,0.1,0.5,0,0.5,1);
I will explain the meaning of this code in a separate tutorial.
Creating a static body
There are two kinds of bodies: static and dynamic. Static bodies can move, but their movement isn't influenced by other bodies. The movement of dynamic bodies can be influenced by other bodies (even static bodies). Static bodies are used for things that can not be moved by other bodies (e.g. the ground, walls, platforms that move at a fixed speed).
I will show you how to create a simple static box. First you have to create the body:
body = ep_body_create_static(global.world); // global.world: the id of the world you created.
However, without any shapes the body isn't very useful. The next step is to add a box shape:
shape1 = ep_shape_create_box(global.world,body,32,32,0,0,0,1); // global.world: the id of the world. // body: the id of the body you created. // 32,32: the size of the box. // 0,0,0: the relative coordinates of the shape (x,y,rot). // 1: the density of the box (not used for static bodies).
This code will create a static box, but the box won't collide with anything. The collision system ExtremePhysics uses takes three values: collision mask 1, collision mask 2 and group. Collision mask 1 and collision mask 2 are 32-bit unsigned integers. Collision mask 1 stores the layers the shape belongs to, collision mask 2 stores the layers the shape should collide with. Every bit is one layer, so you can use up to 32 layers. If collision mask 1 matches collision mask 2 or collision mask 2 matches collision mask 1, the bodies will collide. But if they are in the same group (not group 0), they will never collide.
// pseudo-code
if (body1.mask1 & body2.mask2 != 0 or body1.mask2 & body2.mask1 != 0) and (body1.group == 0 or body1.group != body2.group) {
// collision
} else {
// no collision
}
Groups are useful if your game uses lots of small groups of bodies that can't collide, like cars (the wheels shouldn't collide with the car, otherwise they can't overlap).
ep_shape_set_collision(global.world,body,shape1,1,1,0); // 1: collision mask 1 (binary 00000000 00000000 00000000 00000001). // 1: collision mask 2 (binary 00000000 00000000 00000000 00000001). // 0: group (0 means no group).
The next step is to change the material of the box:
ep_shape_set_material(global.world,body,shape1,0.5,0.4,0,0); // 0.5: coefficient of restitution. // 0.4: friction. // 0: normal surface velocity. // 0: tangential surface velocity.
Finally the box is moved to the correct position:
ep_body_set_position(global.world,body,x,y,degtorad(image_angle)); // x: x coordinate of the body. // y: y coordinate of the body. // degtorad(image_angle): rotation of the body, in radians.
Creating a dynamic body
Creating dynamic bodies is almost the same as creating static bodies. There is one extra argument for dynamic bodies: norotation. If norotation is true, the rotation of the body will not be influenced by other bodies (because the moment of inertia of the body is infinite).
body = ep_body_create_dynamic(global.world,false); // false: this body can rotate.
You have to set the center of mass, mass and moment of inertia of the body before you can use it. The easiest way to do this is calling ep_body_calculate_mass. This function will calculate the center of mass, mass and moment of inertia of the body based on the shapes you have added to the body.
// call this function after adding the shapes: ep_body_calculate_mass(global.world,body);
Circle shapes
You can create circle shapes in the same way you create box shapes:
shape1 = ep_shape_create_circle(global.world,body,32,0,0,0,1); // 32: the radius of the circle. // 0,0,0: the relative coordinates of the shape (x,y,rot). // 1: the density of the circle (not used for static bodies).
Polygon shapes
Creating polygon shapes is more complicated, because you have to create a polygon first. A polygon can be used by multiple bodies, so usually you can create all polygons immediately after creating the world.
global.poly_triangle1 = ep_polygon_create(global.world,3); // 3: number of vertices. ep_polygon_set_vertex(global.world,global.poly_triangle1,0,-10,-10); // 0: first vertex. // -10,-10: coordinates of the vertex. ep_polygon_set_vertex(global.world,global.poly_triangle1,1,+10,+10); // 1: second vertex. // +10,+10: coordinates of the vertex. ep_polygon_set_vertex(global.world,global.poly_triangle1,2,-10,+10); // 2: third vertex. // -10,+10: coordinates of the vertex. ep_polygon_initialize(global.world,global.poly_triangle1);
There are two things you have to take in mind:
-
Vertices have to be declared in clockwise order (in a left-handed coordinate system).
-
All polygons have to be convex. If a body is concave you have to create multiple convex polygons. You can use multipolygons to accomplish that.
shape1 = ep_shape_create_polygon(global.world,body,global.poly_triangle1,0,0,0,1); // global.poly_triangle1: the id of the polygon. // 0,0,0: the relative coordinates of the shape (x,y,rot). // 1: the density of the polygon (not used for static bodies).
Warning
You can't destroy a polygon if it's still in use.
Simulating
You have to call ep_world_update_contacts and ep_world_simulate_step to simulate one step. Usually this is done in the end step event of the controller.
ep_world_update_contacts(global.world); ep_world_simulate_step(global.world);
After simulating a step you have to update the position and orientation of the objects in Game Maker to see the results of the simulation.
x = ep_body_get_x(global.world,body); y = ep_body_get_y(global.world,body); image_angle = radtodeg(ep_body_get_rot(global.world,body));
Destroying ExtremePhysics resources
When you destroy an object in Game Maker, you have to destroy the body too:
ep_body_destroy(global.world,body);
Don't forget to destroy the world when the player leaves the room:
// room end event ep_world_destroy(global.world)
Hint
When a world is destroyed, all polygons, bodies, contacts, joints and views that belong to the world are destroyed. When a body is destroyed, all shapes and forces that belong to the body are destroyed.
Good luck!
Comments
N1k10s |
Comment #1: Sat, 5 Jun 2010, 9:47 (GMT+1, DST) I am simply amazed. Thank you so much for these tutorials. I shall stop by every now and then to see what might have been added. I would say that I am an intermediate when it comes to programing and that this is far beyond me. However, your tutorials make perfect sense. One question: Are these codes free to use in other programs? It is exactly what I need for a game of mine created with GM. |
Maarten BaertAdministrator |
Comment #2: Wed, 23 Jun 2010, 16:37 (GMT+1, DST) Quote: N1k10s
I am simply amazed. Thank you so much for these tutorials. I shall stop by every now and then to see what might have been added. I would say that I am an intermediate when it comes to programing and that this is far beyond me. However, your tutorials make perfect sense. One question: Are these codes free to use in other programs? It is exactly what I need for a game of mine created with GM. The code in this tutorial is of course completely free. The source code of the DLL is distributed under the terms of the GNU Lesser General Public License, which means you can use it in any project, but if you start making changes to the source code you have to make those changes public under the same or a similar license. If you're just using the DLL or the extension in GM, then it is "free to use, also for commercial games". |
Cklester |
Comment #3: Sun, 26 Sep 2010, 22:21 (GMT+1, DST) Maarten, could you provide me with an example room of a soccer ball being dropped at an angle from a height and bouncing on a solid floor until it stops? I think that would go a long way in helping me understand how to set up the world and how to attach a sprite to a physics object. Thank you! Edit: I'm using GMP8 Last modified: Sun, 26 Sep 2010, 22:22 (GMT+1, DST) |
Maarten BaertAdministrator |
Comment #4: Tue, 28 Sep 2010, 23:56 (GMT+1, DST) Quote: Cklester
Maarten, could you provide me with an example room of a soccer ball being dropped at an angle from a height and bouncing on a solid floor until it stops? I think that would go a long way in helping me understand how to set up the world and how to attach a sprite to a physics object. Thank you! Edit: I'm using GMP8 I've added a simple platform example yesterday, it should give you a good idea where to start :). |
Cklester |
Comment #5: Wed, 29 Sep 2010, 2:30 (GMT+1, DST) Cool! Thanks, Maarten. I'll check it out. |
Tbone |
Comment #6: Thu, 7 Oct 2010, 5:32 (GMT+1, DST) I was trying to create a simple dynamic ball to fall down onto the static blocks, but this didn't work out well. Can anyone figure out the problem please. I really would like to learn how to use this. The link is here http://www.speedyshare.com/files/24599850/Try_at_Extreme_Physics.gmk -Thanks in Advance : ) Last modified: Fri, 8 Oct 2010, 17:35 (GMT+1, DST) |
Maarten BaertAdministrator |
Comment #7: Sat, 16 Oct 2010, 15:12 (GMT+1, DST) Quote: Tbone
I was trying to create a simple dynamic ball to fall down onto the static blocks, but this didn't work out well. Can anyone figure out the problem please. I really would like to learn how to use this. The link is here http://www.speedyshare.com/files/24599850/Try_at_Extreme_Physics.gmk -Thanks in Advance : )
It should work now. |
Tbone |
Comment #8: Sat, 16 Oct 2010, 16:21 (GMT+1, DST) Ohh...Duh! Thanks Maarten Baert. :D I would use ep_body_set_gravity like this right? ep_body_set_gravity(global.world,body,0,y+100); Last modified: Sun, 17 Oct 2010, 10:12 (GMT+1, DST) |
Ross93 |
Comment #9: Wed, 2 Mar 2011, 2:50 (GMT+1, DST) Hey there I've been using this physics engine and I love it! I've written a bit of code which can easily turn this into a top-down / birds-eye view physics engine... xx=ep_body_get_xvel_center(global.world, argument0) yy=ep_body_get_yvel_center(global.world, argument0) arot=ep_body_get_rotvel(global.world, argument0) if xx !=0 then xx*=floor_friction if yy !=0 then yy*=floor_friction if arot != 0 then arot*=floor_friction ep_body_set_velocity_center(global.world, argument0, xx,yy,arot) where floor_friction is a decimal number between 0 and 1 (1 being no friction and 0 being lots of friction) If all your bodies have 0 gravity, then if you put this in the step event you will have a working top-down physics engine. I know this is probably elementary stuff but it might help some people :) Cheers |
Maanu40 |
Comment #10: Wed, 2 Mar 2011, 15:51 (GMT+1, DST) Help! When I give the code: ep_world_set_settings(global.world,1,20,10,0.1,0.5,0.1,0.5,1); In the Create-event, the code editor says that there is a wrong number of arguments in this function. :S Please answer! Maanu40 |
Joona |
Comment #11: Fri, 4 Mar 2011, 16:00 (GMT+1, DST) Quote: Maarten Baert
Quote: Tbone
I was trying to create a simple dynamic ball to fall down onto the static blocks, but this didn't work out well. Can anyone figure out the problem please. I really would like to learn how to use this. The link is here http://www.speedyshare.com/files/24599850/Try_at_Extreme_Physics.gmk -Thanks in Advance : )
It should work now. Hi |
Maarten BaertAdministrator |
Comment #12: Sat, 5 Mar 2011, 18:39 (GMT+1, DST) Quote: Ross93
Hey there I've been using this physics engine and I love it! I've written a bit of code which can easily turn this into a top-down / birds-eye view physics engine... [...] where floor_friction is a decimal number between 0 and 1 (1 being no friction and 0 being lots of friction) If all your bodies have 0 gravity, then if you put this in the step event you will have a working top-down physics engine. I know this is probably elementary stuff but it might help some people :) Cheers You can also use ep_body_set_damping in the create event, that function does exactly the same :). Quote: Maanu40
Help! When I give the code: ep_world_set_settings(global.world,1,20,10,0.1,0.5,0.1,0.5,1); In the Create-event, the code editor says that there is a wrong number of arguments in this function. :S Please answer! Maanu40 That code works for me. Are you sure you're using the latest version (2.2)? Quote: Joona
Hi That example uses GM's movement system (direction, speed, gravity, ...), which is not compatible with ExtremePhysics. You should replace them by ExtremePhysics functions, e.g. ep_body_apply_impulse to move towards the target, ep_body_set_damping to simulate friction, ... Last modified: Sat, 5 Mar 2011, 19:00 (GMT+1, DST) |
Joona |
Comment #13: Sat, 5 Mar 2011, 20:45 (GMT+1, DST) Quote: Maarten Baert
Quote: Joona
Hi That example uses GM's movement system (direction, speed, gravity, ...), which is not compatible with ExtremePhysics. You should replace them by ExtremePhysics functions, e.g. ep_body_apply_impulse to move towards the target, ep_body_set_damping to simulate friction, ... Ok, thanks, but now I have even bigger problem. |
Maarten BaertAdministrator |
Comment #14: Tue, 15 Mar 2011, 20:02 (GMT+1, DST) Quote: Joona
Ok, thanks, but now I have even bigger problem. Well, you have to understand the normal movement system first. Otherwise you won't understand the ExtremePhysics functions either. Did you read the official Game Maker tutorials? |
De |
Comment #15: Wed, 21 Mar 2012, 9:46 (GMT+1, DST) hi, |
Maarten BaertAdministrator |
Comment #16: Wed, 28 Mar 2012, 22:02 (GMT+1, DST) Quote: De
hi, That's probably because the flat surface consists of many separate blocks in your game. You can reduce the effect by using a higher framerate (60 instead of 30) or substeps, i.e. simulating multiple steps per actual frame. The only way to actually eliminate the effect is to use a single shape for the entire surface. Take a look at the 'merging walls' example, if your game is grid-based that should be enough. |