• Hey! Guest! The 37th GMC Jam will take place between May 28th, 12:00 UTC and June 1st, 12:00 UTC. Why not join in! Click here to find out more!

Easy way to create fixtures for complex objects?

FeNniX

Member
if physics object is simple shape you can define fixtures directly, but with a little bit complex objects you should write code. It takes quite a long time finding exact coordinates for each fixture point.

If you have many complex objects is there an easy way to create fixtures for them, other then fixture_bind command?
 

2Dcube

Member
One "easy" way to create many fixtures is to build your own editor. I made one where I just click in the room a few times and press Enter, and the dots connect into a new physics fixture. Then, you'd need to save it into a file so you can load it when needed.

I can share some code if you're interested.
 

FeNniX

Member
One "easy" way to create many fixtures is to build your own editor. I made one where I just click in the room a few times and press Enter, and the dots connect into a new physics fixture. Then, you'd need to save it into a file so you can load it when needed.

I can share some code if you're interested.
That sounds interesting. I would be thankful if you could share it.
 

2Dcube

Member
Ok here is the code to create physics fixtures with the mouse. It's quite a bit but I'll try to explain.

We have 2 objects, objController which handles the making of the fixtures and objFixture of which 1 is used for each physics instance.
objFixture has no code, but I could add some to draw its shape if you're interested.

objController Create event:
Code:
polygon_points = ds_list_create(); // this list will be used to hold the points of a polygon (x and y's) and also to draw it on screen as you're making one.
To make a polygon you hold down Control key and click a few times, and then when you release it turns into an instance with physics fixture.
Please note the polygon should be clockwise and convex.

objController Step event:
Code:
// when we press Control, first clear the list so we start with an empty one each time
if keyboard_check_pressed(vk_control)
    {
        ds_list_clear(polygon_points);
    }

// while we are pressing Control, we add points to the list each time we click somewhere
    if keyboard_check(vk_control)
    {
        if mouse_check_button_pressed(mb_left)
        {
            ds_list_add(polygon_points,mouse_x,mouse_y);
        }
    }

// now the hard part. When Control key is released, we turn it into a physics fixture.
    if keyboard_check_released(vk_control)
    {
        if ds_list_size(polygon_points) >= 6 // we need add least 3 points (3 x + 3 y) which is a triangle
        {
            // check if in correct order (clockwise)
            var sum = 0;
            for(var i=0; i<ds_list_size(polygon_points)-3; i+=2)
            {
                sum +=
                    ((polygon_points[| i+2]) - (polygon_points[| i])) *
                    ((polygon_points[| i+3]) + (polygon_points[| i+1]));
            }
            sum += ((polygon_points[| 0]) - (polygon_points[| ds_list_size(polygon_points)-2])) *
                   ((polygon_points[| 1]) + (polygon_points[| ds_list_size(polygon_points)-1]));
            if sum >= 0
            {
                show_message("not clockwise");
            }
            else
            {
                // check if concave (convex is good)
                var convex = true;
                for(var i=0; i<ds_list_size(polygon_points)-1; i+=2)
                {
                    x1 = polygon_points[| i];
                    y1 = polygon_points[| i+1];
         
                    for(var k=0; k<ds_list_size(polygon_points)-1; k+=2)
                    {
                        if i != k
                        {
                            x2 = polygon_points[| k];
                            y2 = polygon_points[| k+1];
                 
                            var xm,ym;
                            xm = (x1 + x2) / 2;
                            ym = (y1 + y2) / 2;
                 
                            if !point_in_polygon(xm - 2,ym - 2,polygon_points)
                            && !point_in_polygon(xm + 2,ym - 2,polygon_points)
                            && !point_in_polygon(xm - 2,ym + 2,polygon_points)
                            && !point_in_polygon(xm + 2,ym + 2,polygon_points)
                            {
                                convex = false;
                            }
                        }
                    }
                }
     
                if !convex
                {
                    show_message("concave!");
                }
                else
                {
                   
// OK! we're clockwise and convex so good to go.

                    // here we find the smallest x and y points to use as origin for the fixture
                    var minx = room_width;
                    var miny = room_height;
                    for(var i=0; i<ds_list_size(polygon_points)-1; i+=2)
                    {
                        minx = min(minx,polygon_points[| i]);
                        miny = min(miny,polygon_points[| i+1]);
                    }
     
                    // and then we subtract the smallest point from all points (so the smallest point will become 0,0)
                    for(var i=0; i<ds_list_size(polygon_points)-1; i+=2)
                    {
                        polygon_points[| i] -= minx;
                        polygon_points[| i+1] -= miny;
                    }
     
                    // now we use this list to make the fixture with the following script (see below code)
                    fixture_create(polygon_points,minx,miny);
                }
            }
        }
        ds_list_clear(polygon_points);
    }
fixture_create() script:
Code:
var list = argument0;
var inst = instance_create_depth(argument1,argument2,0,objFixture);

/*
     basically we just take the points from the list and add each to the fixture
*/

var fix = physics_fixture_create();
physics_fixture_set_polygon_shape(fix); // tell the fixture we're gonna use a polygon shape for it

for(var i=0; i<ds_list_size(list)-1; i+=2)
{
  physics_fixture_add_point(fix, list[| i], list[| i+1]); // add each x,y pair
}
physics_fixture_set_density(fix,0); // set density to 0 so the fixture isn't affected by gravity (unless you want it to)
physics_fixture_bind(fix,inst); // and we end with "bind" and it's done!

physics_fixture_delete(fix); // fixture is not needed anymore so we can delete it (free up some memory)
You also need "point_in_polygon script", which you can get here: https://www.gmlscripts.com/script/point_in_polygon




Also, so you can see what's happening as you're making a new shape, we draw it on the screen with the below code.

objController Draw event:
Code:
draw_set_color(c_orange);
    if ds_list_size(polygon_points) > 0
    {
        for(var i=0; i<ds_list_size(polygon_points)-3; i+=2)
        {
            draw_circle(polygon_points[| i],polygon_points[| i+1],3,false);
            draw_line_width(polygon_points[| i],polygon_points[| i+1],polygon_points[| i+2],polygon_points[| i+3],2);
        }
        draw_circle(polygon_points[| i],polygon_points[| i+1],3,false);
    }
--------------------------

Let me know if there is a problem or something you want clarified.
This doesn't include any code yet to save/load but it can be done by just using the polygon_points list and saving it as a json file, I can give some pointers if you'd like.
Also, you can draw the shapes using vertexes which is a bit complicated. It depends how you want to draw your shapes.

For now, you could add the following to the objController Draw event so you can see the fixtures:
Code:
physics_world_draw_debug(phy_debug_render_shapes);
 
Last edited:

FeNniX

Member
Too late response from me but still... Thanks for sharing the code. In the end I didn't used it but it gave me an idea. Since you are using mouse to create fixture points, I did the same but with the help of 3rd party program. I downloaded Autohotkey and created simple script. In Fixture editor I click different places where I want the fixture points to be and then completed code gets copied into clipboard. Only thing left is to paste code in create event.
 
Top