collision_triangle
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.
/*
** 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(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;
}
/*
** 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;
}
}
** 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;
}
}
Contributors: Big J, xot
History:
Mar 17, 2007 - xot submits the original script
Jul 27, 2009 - Big J spots a typo


[Please Login]
Related: