You are currently viewing the GMLscripts.com static mirror. Forum access and script submissions are not available through this mirror.

Invert GMLscripts.com

collision_triangle

WARNING: Due to the obsolescence of object_add() and object_add_event(), some or all of the work done by the script collision_triangle_init() will have to be done manually.

This script works similarly to built-in collision_*() functions. It uses a right-triangle-shaped sprite mask to detect collisions with pixel accuracy (unlike other simpler and faster methods). Because any triangle can be split into two right triangles, the script can manipulate this single collision mask to fit any triangle using only scaling and rotation.

collision_triangle

NOTE: This script will eventually be replaced with a version that works more like the built-in collision_*() functions of GameMaker:Studio. It will return an instance id rather than the true or false value it returns now.

collision_triangle(x1,y1,x2,y2,x3,y3,object)
Returns true if there is a collision between a given triangle and a given object, false otherwise.
COPY/// collision_triangle(x1,y1,x2,y2,x3,y3,object)
//
//  Returns true if there is a collision between a given
//  triangle and a given object, false otherwise.
//
//  NOTE: Initialize with collision_triangle_init() before first use.
//
//      x1,y1       first point of triangle (filled), real
//      x2,y2       second point of triangle (filled), real
//      x3,y3       third point of triangle (filled), real
//      object      object or instance (or all), real
//
/// GMLscripts.com/license
{
   var x1,y1,x2,y2,x3,y3,object,xmin,xmax,ymin,ymax,d12,d13,d23,d14,d24,t,dx,dy,x4,y4;
   x1 = argument0;
   y1 = argument1;
   x2 = argument2;
   y2 = argument3;
   x3 = argument4;
   y3 = argument5;
   object = argument6;

   // Bounding box check
   xmin = min(x1,x2,x3);
   xmax = max(x1,x2,x3);
   ymin = min(y1,y2,y3);
   ymax = max(y1,y2,y3);
   if (not collision_rectangle(xmin,ymin,xmax,ymax,object,false,false)) return false;

   // Triangle perimeter check
   if (collision_line(x1,y1,x2,y2,object,true,false)) return true;
   if (collision_line(x1,y1,x3,y3,object,true,false)) return true;
   if (collision_line(x2,y2,x3,y3,object,true,false)) return true;

   // Find long side, make it (x1,y2) to (x2,y2)
   d12 = point_distance(x1,y1,x2,y2);
   d13 = point_distance(x1,y1,x3,y3);
   d23 = point_distance(x2,y2,x3,y3);
   switch (max(d12,d13,d23)) {
       case d13:
           t = x2; x2 = x3; x3 = t;
           t = y2; y2 = y3; y3 = t;
           d12 = d13;
           break;
       case d23:
           t = x1; x1 = x3; x3 = t;
           t = y1; y1 = y3; y3 = t;
           d12 = d23;
           break;
   }

   // From (x3,y3), find nearest point on long side (x4,y4).
   dx = x2 - x1;
   dy = y2 - y1;
   if ((dx == 0) && (dy == 0)) {
       x4 = x1;
       y4 = y1;
   }else{
       t = ((x3 - x1) * dx + (y3 - y1) * dy) / (d12 * d12);
       x4 = x1 + t * dx;
       y4 = y1 + t * dy;
   }

   // A line constructed from (x3,y3) to (x4,y4) divides
   // the original triangle into two right triangles.
   // Fit the collision mask into these triangles.
   d14 = point_distance(x1,y1,x4,y4);
   d24 = d12 - d14;
   with (global.objCollisionTriangle) {
       image_angle  = point_direction(x1,y1,x4,y4);
       image_xscale = d14 / size;
       image_yscale = point_distance(x3,y3,x4,y4) / size;
       if ((x1 > x4) xor (y3 < y4)) image_yscale *= -1;
       if (place_meeting(x4,y4,object)) return true;
       image_xscale = -d24 / size;
       if (place_meeting(x4,y4,object)) return true;
   }
   return false;
}
collision_triangle_init(size)
Required to initialize collision_triangle() before first use.
COPY/// collision_triangle_init(size)
//
//  Required to initialize collision_triangle() before first use. Creates
//  an object, sprite, and global variable __objCollisionTriangle. A large
//  test triangle improves accuracy at the expense of memory usage.
//
//      size        size of test triangle in pixels, real
//
/// GMLscripts.com/license
{
    if (not variable_global_exists("objCollisionTriangle")) {
        var color,object,size;
        size = argument0;
        object = object_add();
        object_set_persistent(object,true);
        object_event_add(object,ev_create,0,"size = "+string(size));
        global.objCollisionTriangle = instance_create(0,0,object);
        draw_clear_alpha(c_black,1);
        color = draw_get_color();
        draw_set_color(c_white);
        draw_triangle(size,size,size,0,0,0,false);
        draw_set_color(color);
        global.objCollisionTriangle.sprite_index = 
        sprite_create_from_screen(0,0,size,size,true,true,false,true,size,0);
        global.objCollisionTriangle.visible = false;
    }
}

Contributors: xot

GitHub: View · Commits · Blame · Raw