VgaGames 3 - Collision-detection man-pages

[.. upper level ..]

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.


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);