Collision-detection functions
Functions for quadtree collision detection.
When checking an object for a collision with any other object, only relevant objects are checked to save runtime.
Quadtree collision detection is designed to be used with VgaGames3-objects.
- Structures and Enumerations
- Creating and destroying a quadtree
- VG3_coll_q_new()
Create a new quadtree. - VG3_coll_q_free()
Destroy the quadtree. - VG3_coll_q_tag()
Tag the quadtree. - Using the quadtree
- VG3_coll_q_insert()
Insert an object into the quadtree. - VG3_coll_q_remove()
Remove an object from the quadtree. - VG3_coll_q_getobj()
Search an object in the quadtree. - VG3_coll_q_getobjs()
Search all occurrences of an object in the quadtree. - VG3_coll_check()
Check whether a moving object collides with another object. - VG3_coll_q_find()
Return a sorted list of objects which collide with an moving object. - VG3_coll_q_mark()
Mark all objects in the quadtree onto the window with a rectangle. Only for debug purposes.
Example
/* move two created rectangle images until they collide */
struct vg3_window *wstruct;
int winw, winh;
/* open window */
wstruct = VG3_window_new(argv[0], VGAG3_VGAVERSION_LOW, VGAG3_WINSCALE_BESTSCALE);
if (wstruct == NULL) { fprintf(stderr, "%s\n", VG3_error()); exit(1); }
/* get the size of the window */
VG3_window_getsize(wstruct, &winw, &winh);
/* create two images of rectangles,
* move them until they collide
*/
{ const int rtwidth = 10, rtheight = 10; /* size of images */
struct vg3_rect rect0, rect1, rect2;
struct vg3_image *img1, *img2;
struct vg3_quadtree *qdtr;
struct vg3_coll coll, *pcoll;
int maxno;
/* create quadtree with the size of the window */
rect0.x = 0;
rect0.y = 0;
rect0.w = winw;
rect0.h = winh;
qdtr = VG3_coll_q_new(&rect0, 0, 0);
if (qdtr == NULL) { fprintf(stderr, "%s\n", VG3_error()); goto byebye; }
/* create first image (yellow rectangle) and put it to the left of the window */
rect1.x = 0;
rect1.y = (winh - rtwidth) / 2;
rect1.w = rtwidth;
rect1.h = rtheight;
img1 = VG3_image_create(wstruct, rect1.w, rect1.h);
if (img1 == NULL) { fprintf(stderr, "%s\n", VG3_error()); goto byebye; }
VG3_draw_clear(wstruct, img1, VGAG3_COLOR_YELLOW);
/* put yellow rectangle into the quadtree */
memset(&coll, 0, sizeof(coll));
coll.rect = rect1;
coll.optr = img1;
snprintf(coll.oid, sizeof(coll.oid), "YELLOW RECTANGLE");
if (VG3_coll_q_insert(qdtr, &coll) < 0) { fprintf(stderr, "%s\n", VG3_error()); goto byebye; }
/* create second image (blue rectangle) and put it to the right of the window */
rect2.x = winw - rtwidth;
rect2.y = (winh - rtwidth) / 2;
rect2.w = rtwidth;
rect2.h = rtheight;
img2 = VG3_image_create(wstruct, rect2.w, rect2.h);
if (img2 == NULL) { fprintf(stderr, "%s\n", VG3_error()); goto byebye; }
VG3_draw_clear(wstruct, img2, VGAG3_COLOR_BLUE);
/* put blue rectangle into the quadtree */
memset(&coll, 0, sizeof(coll));
coll.rect = rect2;
coll.optr = img2;
snprintf(coll.oid, sizeof(coll.oid), "BLUE RECTANGLE");
if (VG3_coll_q_insert(qdtr, &coll) < 0) { fprintf(stderr, "%s\n", VG3_error()); goto byebye; }
/* game-loop */
printf("\n");
VG3_discard_input(wstruct);
for (;;) {
/* clear window */
VG3_draw_clear(wstruct, NULL, VGAG3_COLOR_BLACK);
/* +++ move yellow rectangle +++ */
/* remove it from the quadtree */
VG3_coll_q_remove(qdtr, img1);
/* check for collision when moving it 2 pixels to the right */
rect0 = rect1;
rect0.x += 2;
maxno = VG3_coll_q_find(qdtr, &rect1, &rect0, &pcoll);
if (maxno < 0) { fprintf(stderr, "%s\n", VG3_error()); goto byebye; }
/* collision found? */
if (maxno > 0) {
printf("It took %d from %d steps to collide with %s\n",
pcoll[0].ret.steps, pcoll[0].ret.maxsteps, pcoll[0].oid);
free(pcoll);
break;
}
free(pcoll);
/* now move it and put it back into the quadtree */
rect1 = rect0;
memset(&coll, 0, sizeof(coll));
coll.rect = rect1;
coll.optr = img1;
snprintf(coll.oid, sizeof(coll.oid), "YELLOW RECTANGLE");
if (VG3_coll_q_insert(qdtr, &coll) < 0) { fprintf(stderr, "%s\n", VG3_error()); goto byebye; }
/* draw it to the window */
VG3_image_copy(wstruct, NULL, img1, rect1.x + (rect1.w / 2), rect1.y + (rect1.h / 2), NULL, 0);
/* +++ move blue rectangle +++ */
/* remove it from the quadtree */
VG3_coll_q_remove(qdtr, img2);
/* check for collision when moving it 3 pixels to the left */
rect0 = rect2;
rect0.x -= 3;
maxno = VG3_coll_q_find(qdtr, &rect2, &rect0, &pcoll);
if (maxno < 0) { fprintf(stderr, "%s\n", VG3_error()); goto byebye; }
/* collision found? */
if (maxno > 0) {
printf("It took %d from %d steps to collide with %s\n",
pcoll[0].ret.steps, pcoll[0].ret.maxsteps, pcoll[0].oid);
free(pcoll);
break;
}
free(pcoll);
/* now move it and put it back into the quadtree */
rect2 = rect0;
memset(&coll, 0, sizeof(coll));
coll.rect = rect2;
coll.optr = img2;
snprintf(coll.oid, sizeof(coll.oid), "BLUE RECTANGLE");
if (VG3_coll_q_insert(qdtr, &coll) < 0) { fprintf(stderr, "%s\n", VG3_error()); goto byebye; }
/* draw it to the window */
VG3_image_copy(wstruct, NULL, img2, rect2.x + (rect2.w / 2), rect2.y + (rect2.h / 2), NULL, 0);
/* +++ remainder +++ */
/* update window and get key-strokes */
VG3_window_update(wstruct, 0, 0);
if (VG3_inputevent_update(wstruct) > 0) { break; }
VG3_wait_time(40);
}
VG3_discard_input(wstruct);
/* free all images */
VG3_image_unload(wstruct, NULL);
/* free quadtree */
VG3_coll_q_free(qdtr);
}
/* if an error occurred after creating the window, close it before exiting */
byebye:
/* close window */
VG3_window_free(wstruct);