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);