Easy way to create fixtures for complex objects?

F

FeNniX

Guest
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.
 
F

FeNniX

Guest
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:
F

FeNniX

Guest
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