text: /*----------------------------------------------------------------------------
  * Filename:         ball.c
  * Description:      Ball object used in pong on Keil MCB1700 board
  * Author(s):        George Cowan, Alexander Rathke
  * Date Modified:    Nov. 13, 2017
  *----------------------------------------------------------------------------*/
  #include <lpc17xx.h>
  #include <stdbool.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include "GLCD.h"
  #include "point.h"
  #include "utils.h"
  #include "ball.h"
  
  /*----------------------------------------------------------------------------
   *      Ball Constants
   *---------------------------------------------------------------------------*/
  
  const uint16_t BALL_RADIUS = 6;
  const uint32_t BITMAP_DIM  = ((BALL_RADIUS)*2) + 1;
  
  /*----------------------------------------------------------------------------
   *      Function Definitions
   *---------------------------------------------------------------------------*/
  
  /*******************************************************************************
  *   Function Name:      new_ball
  *   Author(s):          Alexander Rathke
  *   Definition:         ball generator, does not init bitmap
  *   Parameters:         ball center point, color
  *   Returns:            created ball
  *******************************************************************************/
  Ball new_ball(Point p, unsigned short color) {
      Ball b;
      b.center = p;
      b.radius = BALL_RADIUS;
      b.color = color;
      b.b_map = NULL;
      b.velocity[0] = 0;
      b.velocity[1] = 0;
      return b;
  }
  
  /*******************************************************************************
  *   Function Name:      move_ball
  *   Author(s):          Alexander Rathke
  *   Definition:         move ball center position to new point
  *   Parameters:         ball, new center point
  *******************************************************************************/
  void move_ball(Ball *b, Point p) {
      b->center = p;
  }
  
  /*******************************************************************************
  *   Function Name:      fill_line
  *   Author(s):          Alexander Rathke
  *   Definition:         fills vertical line from lower to upper y value, in
                          column x of bitmap with ball color
  *   Parameters:         ball, x val, lower y val, upper y val
  *******************************************************************************/
  void fill_line(Ball *b, uint32_t x_pos, uint32_t y_lower, uint32_t y_upper) {
      uint32_t i;
  
      for (i = y_lower; i <= y_upper; ++i) {
          b->b_map[(i*BITMAP_DIM) + x_pos] = b->color;
      }
  }
  
  /*******************************************************************************
  *   Function Name:      generate_bitmap
  *   Author(s):          Alexander Rathke
  *   Definition:         fills ball bitmap with filled circle generated by
                          Bresenham's circle algorithm, represents ball
  *   Parameters:         ball (uses ball radius, color, modified bitmap)
  *******************************************************************************/
  void generate_bitmap(Ball *b) {
      uint32_t i;
      int16_t xc = (b->radius),
              yc = (b->radius),
              x = 0,
              y = b->radius,
              D = 3 - (2*(b->radius));
  
      if (b->b_map != NULL) {
          free_bitmap(b);
      }
  
      b->b_map = malloc((BITMAP_DIM * BITMAP_DIM) * sizeof(unsigned short));
  
      // Fill as black (background color)
      for(i = 0; i < (BITMAP_DIM * BITMAP_DIM); ++i) {
          b->b_map[i] = Black;
      }
  
  
      while(x <= y) {
          fill_line(b, xc+x, yc-y, yc+y);
          fill_line(b, xc-x, yc-y, yc+y);
          fill_line(b, xc+y, yc-x, yc+x);
          fill_line(b, xc-y, yc-x, yc+x);
  
          ++x;
  
          if (D < 0) {
              D = D + (4*x) + 6;
          }
          else {
              D = D + (4*(x-y)) + 10;
              --y;
          }
      }
  }
  
  /*******************************************************************************
  *   Function Name:      copy_bitmap
  *   Author(s):          Alexander Rathke
  *   Definition:         deep copies bitmap from one ball to another
  *   Parameters:         ball to copy from, ball to copy to
  *******************************************************************************/
  void copy_bitmap(Ball *from, Ball*to) {
      if (to->b_map != NULL) {
          free_bitmap(to);
      }
  
      to->b_map = malloc((BITMAP_DIM * BITMAP_DIM) * sizeof(unsigned short));
  
      memcpy(to->b_map, from->b_map, (BITMAP_DIM * BITMAP_DIM)* sizeof(unsigned short));
  }
  
  /*******************************************************************************
  *   Function Name:      shift_ball
  *   Author(s):          Alexander Rathke
  *   Definition:         shift ball center point (relative shift)
  *   Parameters:         ball, x shift, y shift
  *******************************************************************************/
  void shift_ball(Ball *b, int16_t x_shift, int16_t y_shift) {
      shift_point(&(b->center), x_shift, y_shift);
  }
  
  /*******************************************************************************
  *   Function Name:      set_ball_velocity
  *   Author(s):          Alexander Rathke
  *   Definition:         sets ball velocity (x and y direction speeds)
  *   Parameters:         ball, new x speed, new y speed
  *******************************************************************************/
  void set_ball_velocity(Ball *b, int8_t x_speed, int8_t y_speed) {
      b->velocity[0] = x_speed;
      b->velocity[1] = y_speed;
  }
  
  /*******************************************************************************
  *   Function Name:      print_bitmap
  *   Author(s):          Alexander Rathke
  *   Definition:         prints ball bitmap to serial port
  *   Parameters:         ball
  *******************************************************************************/
  void print_bitmap(Ball *b) {
      uint32_t i;
  
      for(i = 0; i < (BITMAP_DIM*BITMAP_DIM); ++i) {
          printf("%d ", b->b_map[i]);
          if ((i+1) % BITMAP_DIM == 0) {
              printf("\r\n");
          }
      }
  }
  
  /*******************************************************************************
  *   Function Name:      draw_ball
  *   Author(s):          Alexander Rathke
  *   Definition:         draws ball on LCD, uses bitmap and ball position, must
                          generate bitmap before calling
  *   Parameters:         ball to draw
  *******************************************************************************/
  void draw_ball(Ball *b) {
  
      if (b->b_map != NULL) {
          uint32_t i = 0,
                   lower_left_x = (b->center.x - b->radius),
                   lower_left_y = (b->center.y - b->radius);
          uint16_t x, y;
  
          for(i = 0; i < (BITMAP_DIM*BITMAP_DIM); ++i) {
              GLCD_SetTextColor(b->b_map[i]);
              x = lower_left_x + (i % BITMAP_DIM);
              y = lower_left_y + (i / BITMAP_DIM);
              GLCD_PutPixel(x,y);
          }
      }
  }
  
  /*******************************************************************************
  *   Function Name:      ball_is_pos_equal
  *   Author(s):          Alexander Rathke
  *   Definition:         check if balls have same center position and radius
  *   Parameters:         ball a, ball b
  *   Returns:            true if ball center points and radii are same, false
                          otherwise
  *******************************************************************************/
  bool ball_is_pos_equal (Ball *a, Ball *b) {
      return (a->center.x == b->center.x &&
              a->center.y == b->center.y &&
              a->radius == b->radius);
  }
  
  /*******************************************************************************
  *   Function Name:      subtract_ball
  *   Author(s):          Alexander Rathke
  *   Definition:         return ball filled with bitmap to clear portion of
                          old ball not being overlapped by new ball
                          does not return exact overlap, approximates with
                          rectangles
  *   Parameters:         old ball, next ball (current position), clear color
  *   Returns:            ball filled with bitmap to clear portion of
                          old ball not being overlapped by new ball
  *******************************************************************************/
  Ball subtract_ball (Ball *old, Ball *next, unsigned short clear_color) {
      uint32_t i,
               cur_row,
               cur_col;
      int32_t col_overlap,
              row_overlap;
  
      uint8_t case_flag = 0;
  
      Ball return_ball = deep_copy_ball(old);
      return_ball.color = clear_color;
  
      if (next->center.x < old->center.x) {
          col_overlap = (next->center.x + next->radius) - (old->center.x - old->radius);
          case_flag |= 1;
      }
      else {
          col_overlap = (old->center.x + old->radius) - (next->center.x - next->radius);
      }
  
      if (col_overlap < 0) {
          // No intersection
          case_flag |= (1 << 2);
      }
  
      if (next->center.y < old->center.y) {
          row_overlap = (next->center.y + next->radius) - (old->center.y - old->radius);
          case_flag |= (1 << 1);
      }
      else {
          row_overlap = (old->center.y + old->radius) - (next->center.y - next->radius);
      }
  
      if (row_overlap < 0) {
          // No intersection
          case_flag |= (1 << 2);
      }
  
      for(i = 0; i < (BITMAP_DIM * BITMAP_DIM); ++i) {
          cur_col = (i % BITMAP_DIM);
          cur_row = (i / BITMAP_DIM);
  
          if (is_bit_on(case_flag, 2)) {
              // No intersection
              return_ball.b_map[i] = clear_color;
          }
          else {
              if (case_flag == 0) {
                  // next left (or aligned) and above (or aligned) old
                  if (!( (cur_row >= (BITMAP_DIM - row_overlap - 1)) && (cur_col >= (BITMAP_DIM - col_overlap - 1)) )) {
                      return_ball.b_map[i] = clear_color;
                  }
              }
              else if (case_flag == 1) {
                  // next right and above (or aligned) old
                  if (!( (cur_row >= (BITMAP_DIM - row_overlap - 1)) && (cur_col <= col_overlap) )) {
                      return_ball.b_map[i] = clear_color;
                  }
              }
              else if (case_flag == 2) {
                  // next left (or aligned) and below old
                  if (!( (cur_row <= row_overlap) && (cur_col >= (BITMAP_DIM - col_overlap - 1)) )) {
                      return_ball.b_map[i] = clear_color;
                  }
              }
              else if (case_flag == 3) {
                  // next right and below old
                  if (!( (cur_row <= row_overlap) && (cur_col <= col_overlap) )) {
                      return_ball.b_map[i] = clear_color;
                  }
              }
          }
      }
  
      return return_ball;
  }
  
  /*******************************************************************************
  *   Function Name:      deep_copy_ball
  *   Author(s):          Alexander Rathke
  *   Definition:         create a deep copy (needed for bitmap) of ball
  *   Parameters:         ball to copy
  *   Returns:            deep copy of ball passed as parameter
  *******************************************************************************/
  Ball deep_copy_ball (Ball *b) {
      Ball copy;
      copy.center = b->center;
      copy.radius = b->radius;
      copy.color = b->color;
      copy.velocity[0] = 0;
      copy.velocity[1] = 0;
      copy.b_map = NULL;
  
      copy_bitmap(b, &copy);
      return copy;
  }
  
  /*******************************************************************************
  *   Function Name:      free_bitmap
  *   Author(s):          Alexander Rathke
  *   Definition:         free ball bitmap, set to null
  *   Parameters:         ball
  *******************************************************************************/
  void free_bitmap (Ball *b) {
      free(b->b_map);
      b->b_map = NULL;
  }
  
  /*******************************************************************************
  *   Function Name:      erase_ball
  *   Author(s):          Alexander Rathke
  *   Definition:         erases ball using clear color
  *   Parameters:         ball to erase, clear color to cover ball with
  *******************************************************************************/
  void erase_ball (Ball *b, unsigned short clear_color) {
      uint32_t i;
      Ball copy = deep_copy_ball(b);
  
      if (copy.b_map == NULL) {
          copy.b_map = malloc((BITMAP_DIM * BITMAP_DIM) * sizeof(unsigned short));
      }
  
      // fill with clear color
      for(i = 0; i < (BITMAP_DIM * BITMAP_DIM); ++i) {
          copy.b_map[i] = clear_color;
      }
  
      draw_ball(&copy);
      free_bitmap(&copy);
  }
  
  /******************************************************************************
  **                            End Of File
  ******************************************************************************/
  
  