collision_triangle

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. image

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

X WARNING: This script will not work if 'Treat uninitialized variables as value 0' is enabled in the Game Maker Global Game Settings.

Downloadcollision_triangle(x1,y1,x2,y2,x3,y3,object)   Returns true if there is a collision between the given triangle and the given object or instance.
/*
**  Usage:
**      collision_triangle(x1,y1,x2,y2,x3,y3,object)
**
**  Arguments:
**      x1,y1     first point of triangle
**      x2,y2     second point of triangle
**      x3,y3     third point of triangle
**      object    an object or instance to check for collision
**
**  Returns:
**      (true) if there is a collision between the given
**      triangle and the given object, (false) otherwise
**
**  Notes:
**      Must be initialized with collision_triangle_init() before use.
**
**  GMLscripts.com
*/

{
    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)   Must be called once before collision_triangle() can be used. It creates a collision mask of the given size. The larger the size, the more accurate collision_triangle() will be.
/*
**  Usage:
**      collision_triangle_init(size)
**
**  Arguments:
**      size      size of the test triangle in pixels
**                increase size to increase accuracy
**
**  Returns:
**      nothing
**
**  Notes:
**      Creates an object, a sprite, and a global variable called objCollisionTriangle
**
**  GMLscripts.com
*/

{
    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;
    }
}

Click if you've used this script[Please Login]
Projects: 5

 Contributors: Big J, xot

 History:
Mar 17, 2007 - xot submits the original script
Jul 27, 2009 - Big J spots a typo


comments powered by Disqus