以Sprite为中心的缩放图层

时间:2012-04-05 17:20:24

标签: objective-c cocos2d-iphone zoom

我正在开发一种小型游戏,其中太空船穿过一层(doh!),在某些情况下,宇宙飞船接近敌人,整个层在太空船上放大缩放级别取决于船与敌人之间的距离。所有这一切都很好。

然而,主要的问题是如何让变焦保持在太空船的中心?

目前我通过更新方法控制GameLayer对象的缩放,这里是代码:

-(void) prepareLayerZoomBetweenSpaceship{
    CGPoint mainSpaceShipPosition  = [mainSpaceShip position];
    CGPoint enemySpaceShipPosition = [enemySpaceShip position];

    float distance = powf(mainSpaceShipPosition.x - enemySpaceShipPosition.x, 2) + powf(mainSpaceShipPosition.y - enemySpaceShipPosition.y,2);
    distance = sqrtf(distance);

    /*
        Distance > 250 --> no zoom
        Distance < 100 --> maximum zoom
     */
    float myZoomLevel = 0.5f;
    if(distance < 100){ //maximum zoom in
        myZoomLevel = 1.0f;
    }else if(distance > 250){
        myZoomLevel = 0.5f;
    }else{
        myZoomLevel = 1.0f - (distance-100)*0.0033f;
    }

    [self zoomTo:myZoomLevel];
}

-(void) zoomTo:(float)zoom {
    if(zoom > 1){
        zoom = 1;
    }

    // Set the scale.
    if(self.scale != zoom){
        self.scale = zoom;
    }
}

基本上我的问题是:如何缩放图层并将其准确地放在两艘船之间?我猜这就像用两根手指捏缩放!

2 个答案:

答案 0 :(得分:1)

下面是一些应该让它适合您的代码。基本上你想要:

  1. 更新parentNode坐标系中的船位置
  2. 找出这些新位置将导致屏幕绑定的轴。
  3. 缩放并重新定位parentNode
  4. 我添加了一些稀疏的评论,但如果您有任何其他问题/问题请与我联系。首先将它转储到测试项目中可能最容易......

    将ivars放入您的CCLayer:

    CCNode *parentNode;
    CCSprite *shipA;
    CCSprite *shipB;
    CGPoint destA, deltaA;
    CGPoint destB, deltaB;
    CGPoint halfScreenSize;
    CGPoint fullScreenSize;
    

    初始化内容放入CCLayer:

    CGSize size = [[CCDirector sharedDirector] winSize];
    fullScreenSize = CGPointMake(size.width, size.height);
    halfScreenSize = ccpMult(fullScreenSize, .5f);
    parentNode = [CCNode node];
    [self addChild:parentNode];
    
    shipA = [CCSprite spriteWithFile:@"Icon-Small.png"]; //or whatever sprite
    [parentNode addChild:shipA];
    
    shipB = [CCSprite spriteWithFile:@"Icon-Small.png"];
    [parentNode addChild:shipB];
    
    //schedules update for every frame... might not run great.
    //[self schedule:@selector(updateShips:)]; 
    
    //schedules update for 25 times a second
    [self schedule:@selector(updateShips:) interval:0.04f]; 
    

    缩放/中心/发货更新方法:

    -(void)updateShips:(ccTime)timeDelta {
        //SHIP POSITION UPDATE STUFF GOES HERE
        ...
    
        //1st: calc aspect ratio formed by ship positions to determine bounding axis
        float shipDeltaX = fabs(shipA.position.x - shipB.position.x);
        float shipDeltaY = fabs(shipA.position.y - shipB.position.y);
        float newAspect = shipDeltaX / shipDeltaY;
    
        //Then: scale based off of bounding axis
    
        //if bound by x-axis OR deltaY is negligible
        if (newAspect > (fullScreenSize.x / fullScreenSize.y) || shipDeltaY < 1.0) { 
            parentNode.scale = fullScreenSize.x / (shipDeltaX + shipA.contentSize.width);
        } 
        else { //else: bound by y-axis or deltaX is negligible
            parentNode.scale = fullScreenSize.y / (shipDeltaY + shipA.contentSize.height);
        }
    
    
        //calculate new midpoint between ships AND apply new scale to it
        CGPoint scaledMidpoint = ccpMult(ccpMidpoint(shipA.position, shipB.position), parentNode.scale);
        //update parent node position (move it into view of screen) to scaledMidpoint
        parentNode.position = ccpSub(halfScreenSize, scaledMidpoint);
    }
    

    另外,我不确定它会对一堆东西的表现有多好 - 但这是一个单独的问题!

答案 1 :(得分:0)

为什么不移动整个视图,&amp;定位它,以便船在屏幕的中心?我没有尝试过你的例子,但它应该是直截了当的。也许是这样的 -

CGFloat x = (enemySpaceShipPosition.x - mainSpaceShipPosition.x) / 2.0 - screenCentreX;
CGFloat y = (enemySpaceShipPosition.y - mainSpaceShipPosition.y) / 2.0 - screenCentreY;


CGPoint midPointForContentOffset = CGPointMake(-x, -y);

[self setContentOffset:midPointForContentOffset];

...你已经设置了screenCentreX&amp;是的。我还没有使用过UISCrollView很长一段时间(在Unity中工作过,所以我忘记了所有的Obj-C),&amp;我不记得contentOffset如何受缩放级别的影响。尝试一下&amp;看到! (我假设你正在使用UIScrollView,如果不是你也可以尝试一下)