title: Bounding Box Issues with Cocos2d-X
body: <p>I am trying to get my bounding box to work properly, but keep failing when the Map gets scaled. I could really use some assistance here as this has been the bane of my existence.</p>
  
  <p>In a nutshell, I have 1 scene, 2 layers. One layer is a HUD and another is a map. The map is a layer that is rendered by tiling 100 images from a large sliced image. I scale these images to the given spacial scaling and they look great at all sizes. The problem occurs when I try to set a bounding box for the Width/Height of the Map while scaled. I am unable to get it to lock properly (Only right boundary and top boundary, left and bottom work fine). As an FYI, this will work beautifully when Scale is equal to 1, but as soon as I scale, everything gets awkward, most likely due to the changing X,Y of the Map Tiles when I scale the Sprite.</p>
  
  <p>Please help as I don't know what I am doing wrong and cannot wrap my head around the spaces... Here is some code to help:</p>
  
  
  
  <pre><code>bool MapLayer::init()
  {
      // Super init
      if ( !CCLayer::init() )
      {
          return false;
      }
  
      // We need to enable touches for this layer
      setTouchEnabled( true );
  
      // Set the Anchor Point
      setAnchorPoint(ccp(0,0));
  
      // We need to initialize the Map Textures for Rendering (Break up further for performance)
      for(int row = 0; row &lt; NUM_MAP_FRAME_ROWS; row++)
      {
          for(int col = 0; col &lt; NUM_MAP_FRAME_COLS; col++)
          {
              char imageFrameFile[25] = "";
              int imageFrame = ((row * 10) + col) + 1;
  
              // Create the String to load the image frame
              sprintf(imageFrameFile, "map_%02d.png", imageFrame);
  
              // Create the Sprite
              map[row][col] = CCSprite::create(imageFrameFile);
  
              // Add the Sprite to the Scene
              this-&gt;addChild(map[row][col], 0);
          }
      }
  
      // Render the Map at the default Scale (Show entire Map)
      renderMap();
  
      // Position the Viewport to the center of the map
      setPosition(ccp(0 - (((map[9][9]-&gt;getPosition().x + map[9][9]-&gt;getContentSize().width) / 2.0f) - ((map[9][9]-&gt;getContentSize().width / 2.0f))),
                      0 - ((map[0][0]-&gt;getPosition().y / 2.0f) - ((map[0][0]-&gt;getContentSize().height / 2.0f)))));
  
      return true;
  }
  
  
  
  void MapLayer::renderMap(void)
  {
      int overlapBuffer = 0;
      float spritePositionX = 0.0f;
      float spritePositionY = 0.0f;
  
      // Reset our Boundary variables
      rightBoundary = 0;
      topBoundary = 0;
  
      // Display the Tile-based Map
      for(int row = NUM_MAP_FRAME_ROWS - 1; row &gt;= 0; row--)
      {
          // Reset the starting position
          spritePositionX = 0.0f;
  
          for(int col = 0; col &lt; NUM_MAP_FRAME_COLS; col++)
          {
              CCSprite * pSprite = map[row][col];
              CCSize spriteContentSize = pSprite-&gt;getContentSize();
              float spriteWidth = spriteContentSize.width;
              float spriteHeight = spriteContentSize.height;
  
              // Position the Sprite by using the previous Sprite's location
              pSprite-&gt;setScale(getScale());
              pSprite-&gt;setAnchorPoint(ccp(0, 0));
              pSprite-&gt;setPosition(ccp(spritePositionX, spritePositionY));
  
              // Increment for the next Sprite Position
              spritePositionX += (float)(spriteWidth * pSprite-&gt;getScale()) - overlapBuffer;
  
              // Increment if this is the last column item
              if(col == (NUM_MAP_FRAME_COLS - 1))
              {
                  // Increment for the next Sprite Position
                  spritePositionY += (float)(spriteHeight * pSprite-&gt;getScale()) - overlapBuffer;
              }
          }
      }
  
  
  
  
  
      // TEST CODE
      CCPoint boundaries = convertToWorldSpace(ccp(spritePositionX, spritePositionY));
      rightBoundary = boundaries.x;
      topBoundary = boundaries.y;
      // TEST CODE
  }
  
  
  
  
  
  
  
  
  
  
  
  
  void MapLayer::scale(float newScale, CCPoint scaleCenter)
  {
      // scaleCenter is the point to zoom to..
      // If you are doing a pinch zoom, this should be the center of your pinch.
  
      // Get the original center point.
      CCPoint oldCenterPoint = ccp(scaleCenter.x * getScale(), scaleCenter.y * getScale());
  
      // Set the scale.
      setScale(newScale);
  
      // Get the new center point.
      CCPoint newCenterPoint = ccp(scaleCenter.x * getScale(), scaleCenter.y * getScale());
  
      // Then calculate the delta.
      CCPoint centerPointDelta  = ccpSub(oldCenterPoint, newCenterPoint);
  
      // Now adjust your layer by the delta.
      setPosition(ccpAdd(getPosition(), centerPointDelta));
  
      // Render the Map to the new Scale
      renderMap();
  }
  
  
  
  
  
  
  
  void MapLayer::checkBoundingBox(void)
  {
      // Grab the display size from the director
      CCSize winSize = CCDirector::sharedDirector()-&gt;getWinSize();
  
  
  
  
  
  
      cocos2d::CCLog("************************************");
      cocos2d::CCLog("WORLD Position-X: %f", convertToWorldSpace(getPosition()).x);
      cocos2d::CCLog("WORLD Position-Y: %f", convertToWorldSpace(getPosition()).y);
  
      cocos2d::CCLog("Position-X: %f", (getPosition()).x);
      cocos2d::CCLog("Position-Y: %f", (getPosition()).y);
  
  //    cocos2d::CCLog("Map[0][0]-X: %f", convertToWorldSpace(map[0][0]-&gt;getPosition()).x);
  //    cocos2d::CCLog("Map[0][0]-Y: %f", convertToWorldSpace(map[0][0]-&gt;getPosition()).y);
  //    cocos2d::CCLog("Map[9][9]-X: %f", convertToWorldSpace(map[9][9]-&gt;getPosition()).x);
  //    cocos2d::CCLog("Map[9][9]-Y: %f", convertToWorldSpace(map[9][9]-&gt;getPosition()).y);
      cocos2d::CCLog("WinSize Width: %f", winSize.width);
      cocos2d::CCLog("WinSize Height: %f", winSize.height);
  
  
      /*
       * Check if we have scaled beyond our limits
       */
      // Check the Width
      if(getPositionX() &gt;= 0)
      {        
          // Set the Position
          setPositionX(0);
      }
  
      // Check the Height
      if(getPositionY() &gt;= 0)
      {        
          // Set the Position
          setPositionY(0);
      }
  
  
  
  
      setPosition(ccpClamp(getPosition(),
                           ccp(-(rightBoundary - winSize.width),
                               -(topBoundary - winSize.height)),
                           ccp(0,0)));         
  }
  
  
  
  
  
  
  
  
  void MapLayer::ccTouchesMoved( CCSet *pTouches, CCEvent *pEvent )
  {
      // Verify that we are Panning the Map
      if(pTouches-&gt;count() == 1)
      {
          // Grab the touch to handle the pan
          CCTouch * panTouch = (CCTouch *)pTouches-&gt;anyObject();
  
          // Get the touch and previous touch
          CCPoint touchLocation = panTouch-&gt;getLocationInView();
          CCPoint previousLocation = panTouch-&gt;getPreviousLocationInView();
  
          // Get the distance for the current and previous touches.
          float currentDistanceX = touchLocation.x - previousLocation.x;
          float currentDistanceY = touchLocation.y - previousLocation.y;
  
          // Set new position of the layer
          setPosition(ccp(getPosition().x + currentDistanceX, getPosition().y - currentDistanceY));
      }
  
      // Verify that we are Zooming the Map
      else if (pTouches-&gt;count() == 2)
      {
          // Grab Touch One
          CCTouch * touchOne = (CCTouch *)pTouches-&gt;anyObject();
  
          // Don't grab the same Touch
          pTouches-&gt;removeObject(touchOne);
  
          // Grab Touch Two
          CCTouch * touchTwo = (CCTouch *)pTouches-&gt;anyObject();
  
          // Get the touches and previous touches.
          CCPoint touchLocationOne = touchOne-&gt;getLocationInView();
          CCPoint touchLocationTwo = touchTwo-&gt;getLocationInView();
  
          CCPoint previousLocationOne = touchOne-&gt;getPreviousLocationInView();
          CCPoint previousLocationTwo = touchTwo-&gt;getPreviousLocationInView();
  
          // Get the distance for the current and previous touches.
          float currentDistance = sqrt(pow(touchLocationOne.x - touchLocationTwo.x, 2.0f) +
                                       pow(touchLocationOne.y - touchLocationTwo.y, 2.0f));
  
          float previousDistance = sqrt(pow(previousLocationOne.x - previousLocationTwo.x, 2.0f) +
                                        pow(previousLocationOne.y - previousLocationTwo.y, 2.0f));
  
          // Get the delta of the distances.
          float distanceDelta = currentDistance - previousDistance;
  
          // Next, position the camera to the middle of the pinch.
          // Get the middle position of the pinch.
          CCPoint pinchCenter = ccpMidpoint(touchLocationOne, touchLocationTwo);
  
          // Then, convert the screen position to node space... use your game layer to do this.
          pinchCenter = convertToNodeSpace(pinchCenter);
  
          // Finally, call the scale method to scale by the distanceDelta, pass in the pinch center as well.
          // Also, multiply the delta by PINCH_ZOOM_MULTIPLIER to slow down the scale speed.
          scale(getScale() + (distanceDelta * PINCH_ZOOM_MULTIPLIER), pinchCenter);
      }
  
      /*
       * Verify that the new position is within our bounding box, otherwise lock it
       */
      checkBoundingBox();
  }
  </code></pre>