GMLscripts.com

Discuss and collaborate on GML scripts
Invert

You are not logged in.

#1 2020-09-09 21:36:11

lostdarkwolf
Member
Registered: 2015-11-19
Posts: 31

convert a sprite mask to binded fixtures (with example)

Here is another example and script. This script can scan a sprite and convert its sprite mask into a bunch of physics fixtures that are built like scanlines. if you want full detail, it can be a bit laggy, but you can reduce detail by increasing the point_precision argument in "physics_fixture_multibind_sprite_lines".

I may end up trying to improve this script in the future.

Physics Destructable Terrain Example (Hosted at host-a.net)

NOTE: I've discovered that the example has bugs, but I'm not sure what the problem is yet.

Expand///physics_fixture_multibind_sprite_lines(point_precision, density*, restitution*, angular_damping*, linear_damping*, friction*, scan_x*, scan_y*)
//
// Binds multiple fixtures to the calling instance.
// The overall shape of the fixtures will roughly match the mask of the local sprite.
// Returns a ds_list that contains all of the individual shapes that were binded to the local instance.
//
// point_precision   precision of scaning for fixtures
// density           physics density for the entire shape.
// restitution       physics restitution for the entire shape.
// angular_damping   physics angular damping for the entire shape.
// linear_damping    physics linear damping for the entire shape.
// friction          physics friction for the entire shape.
// scan_x            where to start scanlines for x.
// scan_y            where to start scanlines for y.
//
// If you don't know where to start scanlines, then omit the last two arguments.
// This script works as scanlines do.
// every individual shape generated by this script has four points.
//
/// GMLscripts.com/license

var var_memory_fixture, var_edge_start_x, var_edge_start_y, var_point_precision, var_cancel_shape, 
    var_density, var_restitution, var_angular_damping, var_linear_damping, var_friction;

var_point_precision=2;
if argument_count>0 var_point_precision=argument[0];
var_density=0
if argument_count>1 var_density=argument[1];
var_restitution=0.1
if argument_count>2 var_restitution=argument[2];
var_angular_damping=0.6
if argument_count>3 var_angular_damping=argument[3];
var_linear_damping=0.6
if argument_count>4 var_linear_damping=argument[4];
var_friction=0.2
if argument_count>5 var_friction=argument[5];
var_edge_start_x=0;
if argument_count>6 var_edge_start_x=argument[6];
var_edge_start_y=0;
if argument_count>7 var_edge_start_y=argument[7];

var var_return_dslist; var_return_dslist=ds_list_create();

fixture_top_offset=floor(sprite_get_xoffset(sprite_index)*image_xscale);
fixture_left_offset=floor(sprite_get_yoffset(sprite_index)*image_yscale);

// if edge_start location is invalid
if not position_meeting(x+var_edge_start_x, y+var_edge_start_y, id) 
or position_meeting(x+var_edge_start_x, y+var_edge_start_y-1, id) { 
 // find a valid edge_start location
 var ii_seen_self;
 ii_seen_self=false
 var_edge_start_y=fixture_left_offset;
 while var_edge_start_y<sprite_width-fixture_top_offset and ii_seen_self=false {
  var_edge_start_x=-fixture_top_offset;
  while var_edge_start_x<sprite_height-fixture_left_offset and ii_seen_self=false {
   if position_meeting(x+var_edge_start_x, y+var_edge_start_y, id) ii_seen_self=true;
   var_edge_start_x+=var_point_precision;
  }
  var_edge_start_y+=var_point_precision;
 }
}
if var_edge_start_y>=sprite_width-fixture_top_offset
and var_edge_start_x>=sprite_height-fixture_left_offset {
 return -1; // sprite mask is empty!
}

scan_point_x=0
scan_point_y=0
var var_x_goto; var_x_goto=0;
var_cancel_shape=false
var var_lose_meeting;

while scan_point_y<sprite_height-var_point_precision {
 var_memory_fixture = physics_fixture_create();
 physics_fixture_set_polygon_shape(var_memory_fixture);
 
 // point 1 and 2
 while (not position_meeting(x+scan_point_x, y+scan_point_y+var_point_precision, id)
        or not position_meeting(x+scan_point_x, y+scan_point_y, id))
 and scan_point_x<=sprite_width+var_point_precision {
  scan_point_x+=var_point_precision
 }
 
 physics_fixture_add_point(var_memory_fixture,scan_point_x, scan_point_y+var_point_precision);
 physics_fixture_add_point(var_memory_fixture,scan_point_x, scan_point_y);
 
 // point 3 and 4
 scan_point_x+=(var_point_precision*2)
 while (position_meeting(x+scan_point_x, y+scan_point_y+var_point_precision, id)
        and position_meeting(x+scan_point_x, y+scan_point_y, id))
 and scan_point_x<=sprite_width+var_point_precision {
  scan_point_x+=var_point_precision
 }
 if scan_point_x<sprite_width scan_point_x-=var_point_precision
 
 physics_fixture_add_point(var_memory_fixture,scan_point_x, scan_point_y);
 physics_fixture_add_point(var_memory_fixture,scan_point_x, scan_point_y+var_point_precision);
 scan_point_x+=(var_point_precision)
 
 while (not position_meeting(x+scan_point_x, y+scan_point_y+var_point_precision, id)
        or not position_meeting(x+scan_point_x, y+scan_point_y, id))
 and scan_point_x<=sprite_width+var_point_precision {
  scan_point_x+=var_point_precision
 }

 if scan_point_x>sprite_width+var_point_precision {
  scan_point_y+=var_point_precision;
  scan_point_x=0;
 }
 
 // finalization
 physics_fixture_set_density(var_memory_fixture, var_density);
 physics_fixture_set_restitution(var_memory_fixture, var_restitution);
 physics_fixture_set_angular_damping(var_memory_fixture, var_angular_damping);
 physics_fixture_set_linear_damping(var_memory_fixture, var_linear_damping);
 physics_fixture_set_friction(var_memory_fixture, var_friction);
 ds_list_add(var_return_dslist, physics_fixture_bind(var_memory_fixture, id))
 physics_fixture_delete(var_memory_fixture);
}

return var_return_dslist;

This is a required script.

Expand///physics_remove_fixture_list(inst, ds_list)
// 
// removes multiple binded fixtures, all stored in a ds_list.
//
// inst      ID of the instance to remove the fixtures from
// ds_list   List of binded fixture IDs that are to be removed from the instance
//
/// GMLscripts.com/license

var ii; ii=0;
repeat ds_list_size(argument1) {
 physics_remove_fixture(argument0, ds_list_find_value(argument1, ii));
 ii+=1;
}
ds_list_destroy(argument1);

Last edited by lostdarkwolf (2020-09-10 08:58:04)

Offline

Board footer

Powered by FluxBB