So instead I came up with a method where you get the top right and the bottom left corners of the tiled map, finds their co-ordinates, then converts it to world space.
From here, the boundaries are drawn up where in the code below, I have taken into account a 40x320 UI bar running up the right side of the screen. My code is tried and tested on tiled maps of varying size, hope it will help someone.
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{if (hasPickedButton == NO) {// "allObjects" returns an NSArray of all the objects in the setNSArray *touchArray = [touches allObjects];// Only run the following code if there is more than one touch, wanting to resizeif ([touchArray count] > 1){// We're going to track the first two touches (i.e. first two fingers)// Create "UITouch" objects representing each touchUITouch *fingerOne = [touchArray objectAtIndex:0];UITouch *fingerTwo = [touchArray objectAtIndex:1];// Convert each UITouch object to a CGPoint, which has x/y coordinates we can actually useCGPoint pointOne = [fingerOne locationInView:[fingerOne view]];CGPoint pointTwo = [fingerTwo locationInView:[fingerTwo view]];CGPoint pointOnePrev = [fingerOne previousLocationInView:[fingerOne view]];CGPoint pointTwoPrev = [fingerTwo previousLocationInView:[fingerTwo view]];// The touch points are always in "portrait" coordinates// You will need to convert them if in landscape (which we are)pointOne = [[CCDirector sharedDirector] convertToGL:pointOne];pointTwo = [[CCDirector sharedDirector] convertToGL:pointTwo];pointOnePrev = [[CCDirector sharedDirector] convertToGL:pointOnePrev];pointTwoPrev = [[CCDirector sharedDirector] convertToGL:pointTwoPrev];CGPoint point1Map = [mapLayer convertToNodeSpace:pointOne];CGPoint point2Map = [mapLayer convertToNodeSpace:pointTwo];CGPoint midPoint = ccpMidpoint(point1Map, point2Map);mapLayer.anchorPoint = ccp(midPoint.x/mapWidth, midPoint.y/mapWidth);//this statement finds the difference in the pinches that the player is doing now, and the pinch the player was doing//if they were pinching in, subtract the distance of the pinch from the distance of the previous pinchif ((sqrt(pow(pointOnePrev.x - pointTwoPrev.x, 2.0) + pow(pointOne.y - pointTwo.y, 2.0))) > sqrt(pow(pointOne.x - pointTwo.x, 2.0) + pow(pointOne.y - pointTwo.y, 2.0))) {distance -= sqrt(pow(pointOne.x - pointTwo.x, 2.0) + pow(pointOne.y - pointTwo.y, 2.0))/100;distance = fabsf(distance);}//otherwise they are pinching out and so add on more to the distanceelse if ((sqrt(pow(pointOnePrev.x - pointTwoPrev.x, 2.0) + pow(pointOne.y - pointTwo.y, 2.0))) < sqrt(pow(pointOne.x - pointTwo.x, 2.0) + pow(pointOne.y - pointTwo.y, 2.0))) {distance += sqrt(pow(pointOne.x - pointTwo.x, 2.0) + pow(pointOne.y - pointTwo.y, 2.0))/100;distance = fabsf(distance);}// Get the distance between the touch points// Scale the distance based on the overall width of the screen (multiplied by a constant, just for effect)mapScale = distance / [CCDirector sharedDirector].winSize.width * 3;//we don't want the player to be able to zoom out to the point where the map is smaller than the screenfloat minFactor = MAX(440.0/mapWidth, 320.0/mapHeight);if (mapScale <= minFactor) {//set this here, so if the player keeps zooming out out out, even though it doesn't change the scale factor, the distance is always decremented. this line keeps it to the last distance that had any effect, stops jumping cameradistance = lastGoodDistance;}//we don't want him zooming in larger than the original imageif (mapScale>1.0) {distance = lastGoodDistance;}if ((mapScale< 1.0) && (mapScale > minFactor)){//set the last distance which had any affect to be the current onelastGoodDistance= distance;
//get the co-ordinates of the BL and TR tiles for this scale in wordspace, then put scale back to normal for now//allow the zoom to take place, but don't permentatly apply it just yet, we want to make sure the final scaled map is within the bounds of the view before moving it (otherwise it appears shakey)float oldscale = mapLayer.scale;[mapLayer setScale:mapScale];
//restore the old mapscale until we sort out the positionCGSize mapTiles = [levelMap mapSize];float y = mapTiles.height;float x = mapTiles.width;CCSprite * grid = [mapBgLayer tileAt:ccp(0, y-1)];CGPoint bottomLeftGrid = grid.position;bottomLeftGrid = [levelMap convertToWorldSpace:bottomLeftGrid];grid = [mapBgLayer tileAt:ccp(x-1, 0)];CGPoint topRightGrid = grid.position;topRightGrid = [levelMap convertToWorldSpace:topRightGrid];
mapLayer.scale = oldscale;//check to see if the layer is drifting off the screen while the zoom is taking placeCGPoint difference = ccp(0, 0);float degreeOfAwkard = (1- mapScale)*10;float awkardOffsetX = degreeOfAwkard *3.51;float awkardOffsetY = degreeOfAwkard *3.5;if (bottomLeftGrid.x > 0) {float offBy = 0 - bottomLeftGrid.x;difference.x += offBy;}if (bottomLeftGrid.y > 0) {float offBy = 0 - bottomLeftGrid.y;difference.y += offBy;}if (topRightGrid.x < 400 + awkardOffsetX) {float offBy = 400 - topRightGrid.x + awkardOffsetX;difference.x += offBy;}if (topRightGrid.y < 280 + awkardOffsetY) {float offBy = 280 - topRightGrid.y + awkardOffsetY;difference.y += offBy;}mapLayer.position = ccpAdd(mapLayer.position, difference);// [mapLayer runAction:[CCMoveBy actionWithDuration:0.05 position:difference]];mapLayer.scale = mapScale;}}if ([touchArray count] ==1){CGSize mapTiles = [levelMap mapSize];float y = mapTiles.height;float x = mapTiles.width;CCSprite * grid = [mapBgLayer tileAt:ccp(0, y-1)];CGPoint bottomLeftGrid = grid.position;bottomLeftGrid = [levelMap convertToWorldSpace:bottomLeftGrid];grid = [mapBgLayer tileAt:ccp(x-1, 0)];CGPoint topRightGrid = grid.position;topRightGrid = [levelMap convertToWorldSpace:topRightGrid];UITouch * fingerOne = [touchArray objectAtIndex:0];CGPoint newTouchLocation = [fingerOne locationInView:[fingerOne view]];newTouchLocation = [[CCDirector sharedDirector] convertToGL:newTouchLocation];CGPoint oldTouchLocation = [fingerOne previousLocationInView:fingerOne.view];oldTouchLocation = [[CCDirector sharedDirector] convertToGL:oldTouchLocation];//get the difference in the finger touches when the player was draggingCGPoint difference = ccpSub(newTouchLocation, oldTouchLocation);//adds this on to the layers current position, effectively moving itCGPoint bottomLeft = ccpAdd(mapLayer.position, difference);//check to see if the map edges of the map are showing in the screen, if so bringing them back on the view so no black space can be seenbottomLeft = ccpAdd(mapLayer.position, difference);bottomLeftGrid = ccpAdd(bottomLeftGrid, difference);topRightGrid = ccpAdd(topRightGrid, difference);//don't ask why, but the boundary changes by about 3pxls per 0.1 scalefloat degreeOfAwkard = (1- mapScale)*10;float awkardOffsetX = degreeOfAwkard *3.51;float awkardOffsetY = degreeOfAwkard *3.5;if (bottomLeftGrid.x > 0) {//finds how much the map is off the boundaryfloat offBy = 0 - bottomLeftGrid.x;difference.x += offBy;}if (bottomLeftGrid.y > 0) {float offBy = 0 - bottomLeftGrid.y;difference.y += offBy;}if (topRightGrid.x < 400 + awkardOffsetX) {float offBy = 400 - topRightGrid.x + awkardOffsetX;difference.x += offBy;}if (topRightGrid.y < 280 + awkardOffsetY) {float offBy = 280 - topRightGrid.y + awkardOffsetY;difference.y += offBy;}//adjusts the map so it is within the boundary justmapLayer.position = ccpAdd(mapLayer.position, difference);}}}
What is on "tileAt:" ?
ReplyDelete