【问题标题】:Applying Zoom Effect In cocos2D gaming environment?在 cocos2D 游戏环境中应用缩放效果?
【发布时间】:2011-08-20 14:57:06
【问题描述】:

我正在使用 cocos2D 游戏引擎开发一款游戏,并在加载关卡时加载所有 sprites,现在因为一些 sprites(障碍物)高于 320 像素,因此看起来很难检查出来。所以为了方便起见,我想应用ZOOM IN 和ZOOM out 效果,它可以一次最小化整个关卡的所有精灵,并且在缩小的情况下,这些精灵将驻留在旧位置。

我能做到吗?

如果是,那么如何?

也请说说捏缩放。

【问题讨论】:

    标签: iphone objective-c cocos2d-iphone game-engine


    【解决方案1】:

    如果所有精灵都具有相同的父级,您可以缩放它们的父级,它们将随之缩放,保持它们相对于父级的坐标。

    【讨论】:

    • 是的,但是在这种情况下,触摸的轨迹也会丢失,好像缩小了然后要触摸一个精灵,我需要在该精灵之后的 50 到 100 像素之后触摸它.. :(
    【解决方案2】:

    缩放,相当简单,只需设置主游戏层的 scale 属性...但有一些问题。

    当你缩放图层时,它会改变图层的位置。它不会自动缩放到您当前正在查看的内容的中心。如果您的游戏中有任何类型的滚动,您需要考虑这一点。

    为此,请将图层的anchorPoint 设置为ccp(0.0f, 0.0f),然后计算图层移动了多少,并相应地重新定位它。

    - (void) scale:(CGFloat) newScale scaleCenter:(CGPoint) 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.
        CGPoint oldCenterPoint = ccp(scaleCenter.x * yourLayer.scale, scaleCenter.y * yourLayer.scale); 
    
        // Set the scale.
        yourLayer.scale = newScale;
    
        // Get the new center point.
        CGPoint newCenterPoint = ccp(scaleCenter.x * yourLayer.scale, scaleCenter.y * yourLayer.scale); 
    
        // Then calculate the delta.
        CGPoint centerPointDelta  = ccpSub(oldCenterPoint, newCenterPoint);
    
        // Now adjust your layer by the delta.
        yourLayer.position = ccpAdd(yourLayer.position, centerPointDelta);
    }
    

    捏缩放更容易...只需检测 touchesMoved,然后调用您的缩放例程。

    - (void) ccTouchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
    
        // Examine allTouches instead of just touches.  Touches tracks only the touch that is currently moving...
        //   But stationary touches still trigger a multi-touch gesture.
        NSArray* allTouches = [[event allTouches] allObjects];
    
        if ([allTouches count] == 2) {            
            // Get two of the touches to handle the zoom
            UITouch* touchOne = [allTouches objectAtIndex:0];
            UITouch* touchTwo = [allTouches objectAtIndex:1];
    
            // Get the touches and previous touches.
            CGPoint touchLocationOne = [touchOne locationInView: [touchOne view]];
            CGPoint touchLocationTwo = [touchTwo locationInView: [touchTwo view]];  
    
            CGPoint previousLocationOne = [touchOne previousLocationInView: [touchOne view]];
            CGPoint previousLocationTwo = [touchTwo previousLocationInView: [touchTwo view]];
    
            // Get the distance for the current and previous touches.
            CGFloat currentDistance = sqrt(
                                           pow(touchLocationOne.x - touchLocationTwo.x, 2.0f) + 
                                           pow(touchLocationOne.y - touchLocationTwo.y, 2.0f));
    
            CGFloat previousDistance = sqrt(
                                            pow(previousLocationOne.x - previousLocationTwo.x, 2.0f) + 
                                            pow(previousLocationOne.y - previousLocationTwo.y, 2.0f));
    
            // Get the delta of the distances.
            CGFloat distanceDelta = currentDistance - previousDistance;
    
            // Next, position the camera to the middle of the pinch.
            // Get the middle position of the pinch.
            CGPoint pinchCenter = ccpMidpoint(touchLocationOne, touchLocationTwo);
    
            // Then, convert the screen position to node space... use your game layer to do this.
            pinchCenter = [yourLayer 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.      
            // A PINCH_ZOOM_MULTIPLIER of 0.005f works for me, but experiment to find one that you like.
            [self scale:yourlayer.scale - (distanceDelta * PINCH_ZOOM_MULTIPLIER)
                scaleCenter:pinchCenter];
        }    
    }
    

    【讨论】:

    • 可能听起来很傻,但我不知道如何计算 [glc_getModifiedScale],请详细说明。谢谢。
    • @rptwsthi 对不起,那是我的错误。那是我没有修复以匹配其余部分的一些代码。现在应该更有意义了。
    • 您能否进一步解释一下您是如何“将屏幕位置转换为节点空间”的?我尝试使用[self scale:(distanceDelta/PTM_RATIO) scaleCenter:pinchCenter]; 和[self scale:distanceDelta scaleCenter:[self convertToNodeSpace:pinchCenter]];,但只要我几乎不捏屏幕,它们(以及两者的组合)都会发疯。
    • @DavidT。请查看更新后的答案......可能应该包括一些细节;计算结果是对现有刻度值的增量,而不是全新的刻度值。如果这给您带来任何麻烦,请告诉我。
    • @MichaelFredrickson 明白了。谢谢!!!!顺便说一句,如果您不介意,我将修改您的答案以修复一些拼写错误?另外,我一直在使用YourLayer * yourLayer = (YourLayer *)[[self parent] findChildByTag:kTagYourLayer];我在哪里#define kTagYourLayer 789
    【解决方案3】:

    此代码将我的图层缩放 2 到特定位置

        [layer setScale:2];
        layer.position=ccp(240/2+40,160*1.5);
        double dx=(touchLocation.x*2-240);
        double dy=(touchLocation.y*2-160);
        layer.position=ccp(inGamePlay.position.x-dx,inGamePlay.position.y-dy);
    

    【讨论】:

      【解决方案4】:

      我的代码比其他代码运行得更好:

      - (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
      
          NSArray* allTouches = [[event allTouches] allObjects];
          CCLayer *gameField = (CCLayer *)[self getChildByTag:TAG_GAMEFIELD];
          if (allTouches.count == 2) {
      
              UIView *v = [[CCDirector sharedDirector] view];
              UITouch *tOne = [allTouches objectAtIndex:0];
              UITouch *tTwo = [allTouches objectAtIndex:1];
              CGPoint firstTouch = [tOne locationInView:v];
              CGPoint secondTouch = [tTwo locationInView:v];
              CGPoint oldFirstTouch = [tOne previousLocationInView:v];
              CGPoint oldSecondTouch = [tTwo previousLocationInView:v];
              float oldPinchDistance = ccpDistance(oldFirstTouch, oldSecondTouch);
              float newPinchDistance = ccpDistance(firstTouch, secondTouch);
      
              float distanceDelta = newPinchDistance - oldPinchDistance;
              NSLog(@"%f", distanceDelta);
              CGPoint pinchCenter = ccpMidpoint(firstTouch, secondTouch);
              pinchCenter = [gameField convertToNodeSpace:pinchCenter];
      
              gameField.scale = gameField.scale - distanceDelta / 100;
              if (gameField.scale < 0) {
      
                  gameField.scale = 0;
              }
          }
      }
      

      【讨论】:

      • 我的代码有什么问题?除了我的之外,此页面上没有可用的完整代码。
      • 效果很好,非常感谢。我一直在为这个 pinchZoom 苦苦挣扎一段时间! +1
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多