Check collision via cairo_clip_extents
"Yang Hong" <[email protected]> Fri, 23 Nov 2018 17:16:54 +0800
| Newsgroups | gmane.comp.lib.cairo |
|---|---|
| Message-ID | <[email protected]> |
Dear Cairo developers
I'm writing a 2D game which need to check collision between
triangle/trapezoid/rectangle/hexagon blocks on the canvas.
I tried to use cairo_clip_extents() to find intersect of triangle and
rectangle, but it doesn't work, because the returned bounding is bigger than
the accurate intersect. Please refer to the attached collision checking
model, I want get the bounding of the area C to check if the triangle is
intersected with the rectangle. This model only works between rectangles,
the cairo_region_t also not help on this.
I also tried cairo_fill_extents, it returns the whole bounding of the
current path, which is not what I want.
While the C area is correctly filled with clip, I want to know is there any
API to get the bound of this area, so I can use it to check if collision
exists. Or is it possible to add API to do so, I have looked into the source
code of cairo, please give me some comment, I'd like to add this API by
myself.
The attached cairo-sandbox.c is the code I used to test the checking model.
gcc -o sandbox cairo-sandbox.c -lcairo -g
./sandbox
eog image.png
Best regards
Hong Yang - TS
--
cairo mailing list
[email protected]
https://lists.cairographics.org/mailman/listinfo/cairo
collision-checking-model.txt
(text/plain, 289 B)
^
/ \ +--------+
/ \ | |
/ \| |
/ \ B |
/ A |\ |
/ | \ |
/ |C \ |
/___________|___\ |
| |
| |
+--------+
cairo-sandbox.c
(application/octet-stream, 6.8 KB)
#include <stdio.h>
#include <cairo/cairo.h>
typedef struct _point point_t;
struct _point {
double x;
double y;
};
double scale = 20.0;
void create_triangle (cairo_t *cr, const point_t *points, int len, int close)
{
const point_t *point = points;
int i = 0;
cairo_move_to (cr, scale * points[i].x, scale * points[i].y);
i++;
while (i < len) {
cairo_line_to (cr, scale * points[i].x, scale * points[i].y);
i++;
}
if (close) {
cairo_close_path(cr);
}
}
static point_t tri4[] = {
{ 3.0, 0.0 },
{ 6.0, 3.0 },
{ 0.0, 3.0 },
};
static point_t rec36[] = {
{ 0.0, 0.0 },
{ 3.0, 0.0 },
{ 3.0, 6.0 },
{ 0.0, 6.0 },
};
static point_t rec915[] = {
{ 0.0, 0.0 },
{ 9.0, 0.0 },
{ 9.0, 1.5 },
{ 0.0, 1.5 },
};
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(point_t))
void sandbox(void)
{
double x1, y1, x2, y2;
const int img_size = 700;
cairo_surface_t * const pix = cairo_image_surface_create
(
/*format =*/ CAIRO_FORMAT_RGB24,
/*width =*/ img_size,
/*height =*/ img_size/2
);
cairo_t * const cr = cairo_create(pix);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
/* use overwriting operator to make clear that overwriting is blocked by clipping */
cairo_set_source_rgb(cr, 1, 1, 1); /* background */
cairo_paint(cr);
//cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
cairo_translate(cr, 20, 20);
////////////
cairo_reset_clip(cr);
cairo_new_path(cr);
create_triangle(cr, tri4, ARRAY_SIZE(tri4), 1);
cairo_set_source_rgba (cr, 1.0, 0.0, 0.5, 0.5);
//cairo_fill_preserve(cr);
cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.5);
cairo_set_line_width (cr, 2.0);
cairo_stroke_preserve (cr);
//cairo_clip(cr);
cairo_translate(cr, 100, 0);
cairo_new_path(cr);
create_triangle(cr, rec36, ARRAY_SIZE(rec36), 1);
cairo_set_source_rgba (cr, 0.8, 0.8, 0.8, 0.5);
//cairo_fill_preserve(cr);
cairo_set_source_rgba (cr, 0.0, 1.0, 0, 0.5);
cairo_set_line_width (cr, 2.0);
cairo_stroke_preserve (cr);
x1 = y1 = x2 = y2 = 0.0;
cairo_clip(cr);
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
//cairo_fill_extents(cr, &x1, &y1, &x2, &y2);
printf("Clip extents: %f, %f, %f, %f\n", x1, y1, x2, y2);
cairo_reset_clip(cr);
cairo_new_path(cr);
cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 0.5);
cairo_stroke_preserve (cr);
////////////
cairo_translate(cr, 120, 0);
cairo_reset_clip(cr);
cairo_new_path(cr);
create_triangle(cr, tri4, ARRAY_SIZE(tri4), 1);
cairo_set_source_rgba (cr, 1.0, 0.0, 0.5, 0.5);
//cairo_fill_preserve(cr);
cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.5);
cairo_set_line_width (cr, 2.0);
cairo_stroke_preserve (cr);
cairo_clip(cr);
cairo_translate(cr, 100, 0);
cairo_new_path(cr);
create_triangle(cr, rec36, ARRAY_SIZE(rec36), 1);
cairo_set_source_rgba (cr, 0.8, 0.8, 0.8, 0.5);
cairo_fill_preserve(cr);
cairo_set_source_rgba (cr, 0.0, 1.0, 0, 0.5);
cairo_set_line_width (cr, 2.0);
cairo_stroke_preserve (cr);
x1 = y1 = x2 = y2 = 0.0;
cairo_clip(cr);
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
//cairo_fill_extents(cr, &x1, &y1, &x2, &y2);
printf("Clip extents: %f, %f, %f, %f\n", x1, y1, x2, y2);
cairo_reset_clip(cr);
cairo_new_path(cr);
cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 0.5);
cairo_stroke_preserve (cr);
////////////
cairo_translate(cr, 80, 0);
cairo_reset_clip(cr);
cairo_new_path(cr);
create_triangle(cr, tri4, ARRAY_SIZE(tri4), 1);
cairo_set_source_rgba (cr, 1.0, 0.0, 0.5, 0.5);
//cairo_fill_preserve(cr);
cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.5);
cairo_set_line_width (cr, 2.0);
cairo_stroke_preserve (cr);
cairo_clip_preserve(cr);
cairo_translate(cr, 100, 0);
cairo_new_path(cr);
create_triangle(cr, rec36, ARRAY_SIZE(rec36), 1);
cairo_set_source_rgba (cr, 0.8, 0.8, 0.8, 0.5);
cairo_fill_preserve(cr);
cairo_set_source_rgba (cr, 0.0, 1.0, 0, 0.5);
cairo_set_line_width (cr, 2.0);
cairo_stroke_preserve (cr);
x1 = y1 = x2 = y2 = 0.0;
cairo_clip_preserve(cr);
//cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
cairo_fill_extents(cr, &x1, &y1, &x2, &y2);
printf("Clip extents: %f, %f, %f, %f\n", x1, y1, x2, y2);
cairo_reset_clip(cr);
cairo_new_path(cr);
cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 0.5);
cairo_stroke_preserve (cr);
////////////
cairo_translate(cr, -480, 180);
cairo_reset_clip(cr);
cairo_new_path(cr);
create_triangle(cr, rec36, ARRAY_SIZE(rec36), 1);
cairo_set_source_rgba (cr, 1.0, 0.0, 0.5, 0.5);
//cairo_fill_preserve(cr);
cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.5);
cairo_set_line_width (cr, 2.0);
cairo_stroke_preserve (cr);
//cairo_clip(cr);
cairo_new_path(cr);
create_triangle(cr, rec915, ARRAY_SIZE(rec915), 1);
cairo_set_source_rgba (cr, 0.8, 0.8, 0.8, 0.5);
//cairo_fill_preserve(cr);
cairo_set_source_rgba (cr, 0.0, 1.0, 0, 0.5);
cairo_set_line_width (cr, 2.0);
cairo_stroke_preserve (cr);
////////////
cairo_translate(cr, 220, 00);
cairo_reset_clip(cr);
cairo_new_path(cr);
create_triangle(cr, rec36, ARRAY_SIZE(rec36), 1);
cairo_set_source_rgba (cr, 1.0, 0.0, 0.5, 0.5);
//cairo_fill_preserve(cr);
cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.5);
cairo_set_line_width (cr, 2.0);
cairo_stroke_preserve (cr);
cairo_clip(cr);
cairo_new_path(cr);
create_triangle(cr, rec915, ARRAY_SIZE(rec915), 1);
cairo_set_source_rgba (cr, 0.8, 0.8, 0.8, 0.5);
cairo_fill_preserve(cr);
cairo_set_source_rgba (cr, 0.0, 1.0, 0, 0.5);
cairo_set_line_width (cr, 2.0);
cairo_stroke_preserve (cr);
x1 = y1 = x2 = y2 = 0.0;
cairo_clip(cr);
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
printf("Clip extents: %f, %f, %f, %f\n", x1, y1, x2, y2);
cairo_reset_clip(cr);
cairo_new_path(cr);
cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 0.5);
cairo_stroke_preserve (cr);
////////////
cairo_translate(cr, 100, 00);
cairo_reset_clip(cr);
cairo_new_path(cr);
create_triangle(cr, rec36, ARRAY_SIZE(rec36), 1);
cairo_set_source_rgba (cr, 1.0, 0.0, 0.5, 0.5);
//cairo_fill_preserve(cr);
cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.5);
cairo_set_line_width (cr, 2.0);
cairo_stroke_preserve (cr);
cairo_clip(cr);
cairo_translate(cr, 0, 30);
cairo_new_path(cr);
create_triangle(cr, rec915, ARRAY_SIZE(rec915), 1);
cairo_set_source_rgba (cr, 0.8, 0.8, 0.8, 0.5);
cairo_fill_preserve(cr);
cairo_set_source_rgba (cr, 0.0, 1.0, 0, 0.5);
cairo_set_line_width (cr, 2.0);
cairo_stroke_preserve (cr);
x1 = y1 = x2 = y2 = 0.0;
cairo_clip(cr);
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
printf("Clip extents: %f, %f, %f, %f\n", x1, y1, x2, y2);
cairo_reset_clip(cr);
cairo_new_path(cr);
cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 0.5);
cairo_stroke_preserve (cr);
cairo_surface_write_to_png(pix, "image.png");
}
int main(int argc, char *argv[])
{
sandbox();
return 0;
}