/**
  * Wall Collision
  *
  * @param x X Position
  * @param y Y Position
  * @param M Map
  * @return if character is about to collide with the wall
  */
 public boolean WallCollision(double x, double y, GridMap M) {
   // If invalid coordinate
   try {
     if (M.getBlockNum(x, y) == -1) {
       // Collision check
       if (isValidSurface(M.Fill[M.getBlockNum(x + 3, y + 3)])) {
         return false;
       }
       return true;
     }
     // Collision check
     if (isValidSurface(M.Fill[M.getBlockNum(x, y)])) {
       return false;
     }
   } catch (Exception e) {
     return WallCollision(x + M.Size / 2, y + M.Size / 2, M);
   }
   return true;
 }
 /** Method to remove cells that are no longer needed to be displayed. */
 public void removeUnneededCells() {
   Map<Point2D.Double, Cell> cells = mapLink.getCells();
   // remove and clear un-needed cells
   Iterator<Point2D.Double> i = cellDrawings.keySet().iterator();
   while (i.hasNext()) // iterate through all available drawings
   {
     Point2D.Double currKey = i.next();
     if (!cells.containsKey(currKey)) // if the drawing no longer corresponds to an actual cell
     {
       i.remove();
     }
   }
 }
  /**
   * Method to update cells according to the changes that have been applied. Cells are drawn in
   * respect to the centre point.
   */
  public void updateDrawings() {
    // re-create graphical display, as a dynamic display
    display = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
    graphicsDisplay = (Graphics2D) display.createGraphics();
    graphicsDisplay.setPaint(Color.white);
    graphicsDisplay.fillRect(0, 0, display.getWidth(), display.getHeight());

    Point2D.Double robotDrawPos =
        getVisualLoc(
            new Point2D.Double(
                robotPos.getX(),
                robotPos.getY())); // get robot's position to determine origin or draw later
    if (followRobot
        == true) // if the display is following the robot, draw the robot in the centre of the
                 // display
    {
      shiftX = (int) (Math.round((displayCentre.getX() - robotDrawPos.getX()) / 10) * 10);
      shiftY = (int) (Math.round((displayCentre.getY() - robotDrawPos.getY()) / 10) * 10);
      robotDrawPos =
          displayCentre; // change robot drawing position to the centre point of the display
    } else {
      // otherwise no shifts
      shiftX = 0;
      shiftY = 0;
    }
    // update cell graphics
    Map<Point2D.Double, Cell> cells = mapLink.getCells();
    Iterator<Point2D.Double> i = cells.keySet().iterator();
    if (enabledSelection) {
      selectedCellKeys.clear();
    }
    while (i.hasNext()) {
      Point2D.Double key = i.next(); // obtain the next cell key
      Cell cell = cells.get(key); // obtain the cell
      boolean hasChanged = false;
      boolean newCell = false;
      CellGraphic cellWob;
      try {
        cellWob = cellDrawings.get(key); // try to obtain the current drawing
      } catch (
          NullPointerException
              e) // if no drawing has been assigned, ensure the graphic is set to null
      {
        cellWob = null;
        newCell = true; // set flag to indicate that this is a  new cell
      }

      if (cellWob == null) {
        newCell = true;
      }
      switch (cell
          .getState()) // compare the actual cell state with what cell state is being displayed
      {
        case CLEAN: // if the actual cell is clean and either the cell is incorrectly displayed or
                    // has no graphic
          {
            if (newCell == true || !(cellWob instanceof CleanCellGfx)) {
              cellWob = new CleanCellGfx(this);
              hasChanged = true;
            }
            break;
          }
        case UNCLEAN: // if the actual cell is unclean and either the cell is incorrectly displayed
                      // or has no graphic
          {
            if (newCell == true || !(cellWob instanceof UncleanCellGfx)) {
              cellWob = new UncleanCellGfx(this);
              hasChanged = true;
            }
            break;
          }
        case HALFCLEAN: // if the actual cell is half-clean and either the cell is incorrectly
                        // displayed or has no graphic
          {
            if (newCell == true || !(cellWob instanceof HalfCleanCellGfx)) {
              cellWob = new HalfCleanCellGfx(this);
              hasChanged = true;
            }
            break;
          }
        case CLOSED: // if the actual cell is closed and either the cell is incorrectly displayed or
                     // has no graphic
          {
            if (newCell == true || !(cellWob instanceof ClosedCellGfx)) {
              cellWob = new ClosedCellGfx(this);
              hasChanged = true;
            }
            break;
          }
      }

      // if the cell is new or it has changed state
      if (newCell == true || hasChanged == true) {
        cellDrawings.put(key, cellWob); // place or update the graphic in the hashmap
      }

      if (enabledSelection
          && cell.getState() != CellState.CLOSED
          && cellWob.getX() >= selectedRegion.getMinX()
          && cellWob.getX() <= selectedRegion.getMaxX()
          && cellWob.getY() >= selectedRegion.getMinY()
          && cellWob.getY() <= selectedRegion.getMaxY()) {
        cellWob.toggleSelected(true);
        selectedCellKeys.add(key);
      } else {
        cellWob.toggleSelected(false);
      }
      Point2D.Double graphPos = getVisualLoc(new Point2D.Double(cell.getXVal(), cell.getYVal()));
      // set x and y values, already tested casting to int in getPixelLoc
      int x = (int) graphPos.getX();
      int y = (int) graphPos.getY();
      cellWob.setLocation(x + shiftX, y + shiftY); // assign location of the graphic
      cellWob.paint(graphicsDisplay);
    }
    // update robot drawing, on top of cells
    graphicsDisplay.drawImage(
        robotWob,
        (int) robotDrawPos.getX(),
        (int) robotDrawPos.getY(),
        (int) cellUnitWidth,
        (int) cellUnitHeight,
        this);

    graphicsDisplay.dispose();
  }