2015-08-06 3 views
0

Я следую Рому Wenderlich на «IOS игр по Учебникам» & я получил все, что в моем мире установках & рабочие: Вся игра находится в ландшафтном режиме & есть один SKNode называется _worldNode & все, кроме _uiNode (в игре UI), добавляется к нему. Персонаж игрока подходит к тронутому месту & _worldNode движется под ним, как беговая дорожка. Однако, как и вся функциональность (или, как они ее называют: «сок»), я захотел добавить функции увеличения/уменьшения изображения через UIPinchGestureRecognizer путем масштабирования _worldNode, что я и сделал. Но теперь каждый раз, когда я увеличиваю масштаб, «камера» перемещается в левую нижнюю. Масштабирование перемещает вид в верхнем правом углу экрана. Это беспорядок. Мне нужно представление, чтобы сосредоточиться на персонаже игрока & Я пробовал все, что мог, найдя &, найти онлайн. Самое близкое, к чему я пришел, использовал технику от SKNode scale from the touched point, но я все еще получаю кровавый нижний правый/верхний беспорядок. Я понял, что этот беспорядок происходит только тогда, когда я обновляю камеру/просмотр (это действительно _worldNode.position). Поэтому методы «didSimulatePhysics» или «didFinishUpdate» не помогают. Фактически, даже кнопка времени, которая слегка перемещает/обновляет вид камеры (_worldNode.position), все еще дает мне нижнюю левую/верхнюю правую проблему. Вот мой код. Я надеюсь, что кто-то может посмотреть & скажите мне, что изменить, чтобы заставить все работать.Почему масштабирование/масштабирование в SKNode заставляет вид влево от экрана?

@interface GameScene() <SKPhysicsContactDelegate, UIGestureRecognizerDelegate> 
{ 
    UIPinchGestureRecognizer  *pinchGestureRecognizer; 
} 

// Свойства моей GameScene.

@property SKNode  *worldNode; 
@property etc. etc. 


//Called by -(id)initWithSize:(CGSize)size method & creates the in-game world. 
-(void)createWorld 
{ 
    [_worldNode addChild:_backgroundLayer]; 

    [self addChild:_worldNode]; 
    self.anchorPoint  = CGPointMake(0.5, 0.5); //RW tutorial did it this way. 
    _worldNode.position  = CGPointMake(-_backgroundLayer.layerSize.width/2, -_backgroundLayer.layerSize.height/2); //Center. 

    //Then I add every node to _worldNode from this point on. 
} 

//Neccessary for gesture recognizers. 
-(void)didMoveToView:(SKView *)view 
{ 
    pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handleZoomFrom:)]; 
    [view addGestureRecognizer:pinchGestureRecognizer]; 
} 

//"Camera" follows player character. 'didSimulatePhysics' doesn't help either. 
-(void)didFinishUpdate 
{ 
    //IF '_pinchingScreen' == YES then screen pinching is in progress. Thus, camera position update will seize for the duration of pinching. 
    if (!_pinchingScreen) 
    { 
     _worldNode.position = [self pointToCenterViewOn:_player.position]; 
    } 
} 

//Method that is called by my UIPinchGestureRecognizer. Answer from: https://stackoverflow.com/questions/21900614/sknode-scale-from-the-touched-point?lq=1 
-(void)handleZoomFrom:(UIPinchGestureRecognizer*)recognizer 
{ 
    CGPoint anchorPoint = [recognizer locationInView:recognizer.view]; 
    anchorPoint   = [self convertPointFromView:anchorPoint]; 

    if (recognizer.state == UIGestureRecognizerStateBegan) 
    { 
     // No code needed for zooming... 

     _player.movementMode = 2; //Stop character from moving from touches. 
     _pinchingScreen   = YES; //Notifies 'didFinishUpdate' method that pinching began & camera position update should stop for now. 
    } 
    else if (recognizer.state == UIGestureRecognizerStateChanged) 
    { 
     //Technique from the above Stack Overflow link - Commented out. 
//  CGPoint anchorPointInMySkNode = [_worldNode convertPoint:anchorPoint fromNode:self]; 
//   
//  [_worldNode setScale:(_worldNode.xScale * recognizer.scale)]; 
//   
//  CGPoint mySkNodeAnchorPointInScene = [self convertPoint:anchorPointInMySkNode fromNode:_worldNode]; 
//  CGPoint translationOfAnchorInScene = CGPointSubtract(anchorPoint, mySkNodeAnchorPointInScene); 
// 
//  _worldNode.position = CGPointAdd(_worldNode.position, translationOfAnchorInScene); 
//   
//  recognizer.scale = 1.0; 


     //Modified scale: 2.0 
     if(recognizer.scale > _previousWorldScale) 
     { 
      _previousWorldScale = recognizer.scale; 

      CGPoint anchorPointInMySkNode = [_worldNode convertPoint:anchorPoint fromNode:self]; 
      [_worldNode setScale:2.0]; 
      CGPoint worldNodeAnchorPointInScene = [self convertPoint:anchorPointInMySkNode fromNode:_worldNode]; 
      CGPoint translationOfAnchorInScene = CGPointSubtract(anchorPoint, worldNodeAnchorPointInScene); 
      _worldNode.position = CGPointAdd(_worldNode.position, translationOfAnchorInScene); 


      //[_worldNode runAction:[SKAction scaleTo:2.0 duration:0]]; //This works too. 
     } 
     //Original scale: 1.0 
     if(recognizer.scale < _previousWorldScale) 
     { 
      _previousWorldScale = recognizer.scale; 

      CGPoint anchorPointInMySkNode = [_worldNode convertPoint:anchorPoint fromNode:self]; 
      [_worldNode setScale:1.0]; 
      CGPoint worldNodeAnchorPointInScene = [self convertPoint:anchorPointInMySkNode fromNode:_worldNode]; 
      CGPoint translationOfAnchorInScene = CGPointSubtract(anchorPoint, worldNodeAnchorPointInScene); 
      _worldNode.position = CGPointAdd(_worldNode.position, translationOfAnchorInScene); 


      //[_worldNode runAction:[SKAction scaleTo:1.0 duration:0]]; //This works too. 
     } 
    } 
    else if (recognizer.state == UIGestureRecognizerStateEnded) 
    { 
     // No code needed here for zooming... 

     _pinchingScreen   = NO; //Notifies 'didFinishUpdate' method that pinching has stopped & camera position update should resume. 
     _player.movementMode = 0; //Resume character movement. 
    } 
} 

Так может кто-нибудь пожалуйста, скажите мне, посмотрев на приведенном выше коде, почему камера/вид смещается в левом нижнем углу на масштабирование? Я несколько дней пробовал эту проблему & Я все еще не могу понять.

+0

Итак, я попытался смягчить этот левый нижний эффект, добавив это в метод didFinishUpdate: CGPoint thePoint = [self pointToCenterViewOn: _player.position]; thePoint.x + = -self.size.width/2; thePoint.y + = -self.size.height/2; Итак, теперь, когда я увеличиваю масштаб с помощью этого: [_worldNode setXScale: 1.5]; [_worldNode setYScale: 1.5]; он работает, но персонаж игрока не остается строго внутри середины экрана. Он «свободен» и может через некоторое время выходить за пределы камеры ... Любые идеи о том, как стабилизировать положение персонажа в середине экрана? – Krekin

ответ

0

Благодаря JKallio, который написал подробный код в своем ответе Zoom and Scroll SKNode in SpriteKit, я смог найти фрагмент кода, который решает проблему. Существует метод под названием «centerOnNode», маленький, элегантный & решает мою проблему отлично. Здесь для тех, кто просто нуждается в том, что:

-(void) centerOnNode:(SKNode*)node 
{ 
    CGPoint posInScene = [node.scene convertPoint:node.position fromNode:node.parent]; 
    node.parent.position = CGPointMake(node.parent.position.x - posInScene.x, node.parent.position.y - posInScene.y); 
} 

Затем вызывается этот метод в ваших «didSimulatePhysics» или «внутри didFinishUpdate», как так:

//"Camera" follows player character. 
-(void)didFinishUpdate 
{ 
    //IF '_pinchingScreen' == YES then screen pinching is in progress. Thus, camera position update will seize for the duration of pinching. 
    if (!_pinchingScreen) 
    { 
     if (_previousWorldScale > 1.0) //If _worldNode scale is greater than 1.0 
     { 
      [self centerOnNode:_player]; //THIS IS THE METHOD THAT SOLVES THE PROBLEM! 
     } 
     else if (_previousWorldScale == 1.0) //Standard _worldNode scale: 1.0 
     { 
      _worldNode.position = [self pointToCenterViewOn:_player.position]; 
     } 
    } 
} 

P.S. Просто помните, что вопрос был не КАК увеличить масштаб. Но как решить проблему с камерой, когда мир УЖЕ увеличен.