Использование жестов с SpriteKit для одновременного перетаскивания, вращения и масштабирования нескольких спрайтов по отдельности.

Я создал приложение для iOS, в котором мне нужно одновременно перемещать, вращать и масштабировать спрайт (я использую Sprite Kit от Apple). По большей части у меня это работает. В настоящее время я могу касаться одним пальцем и перемещать спрайт, а если я использую два пальца, я могу масштабировать и вращать спрайт. Для этого я использую UIPanGestureRecognizer, UIPinchGestureRecognizer и UIRotateGestureRecognizer. Это прекрасно работает. Я бы хотел, чтобы, когда я перетаскиваю, вращаю и масштабирую один спрайт правой рукой, я мог взять левую руку и перетаскивать, вращать и масштабировать другой спрайт независимо от другого спрайта.

В настоящее время я использую жесты iOS для перемещения, вращения и масштабирования спрайтов. Я использовал код, очень похожий на тот, что нашел на веб-сайте Рэя Вендерлиха в его руководстве по перетаскиванию спрайтов для Sprite Kit. http://www.raywenderlich.com/44270/sprite-kit-tutorial-how-to-drag-and-drop-sprites. Часть, которую я использую, находится внизу, когда он начинает использовать UIPanGestureRecognizers вместо простого метода касания.

Как я уже сказал, жесты отлично работают с одним спрайтом за раз. Как заставить его работать более чем с одним спрайтом?

Например, для UIPanGesturRecognizer я добавляю следующий код:

- (void)didMoveToView:(SKView *)view {
      UIPanGestureRecognizer *gestureRecognizer = [[UIPanGestureRecognizer alloc]         initWithTarget:self action:@selector(handlePanFrom:)];
      [[self view] addGestureRecognizer:gestureRecognizer];

}

Затем у меня есть метод для этого, который называетсяgestRecognizer ниже:

- (void)handlePanFrom:(UIPanGestureRecognizer *)recognizer {
if (recognizer.state == UIGestureRecognizerStateBegan) {

    CGPoint touchLocation = [recognizer locationInView:recognizer.view];

    touchLocation = [self convertPointFromView:touchLocation];

    [self selectNodeForTouch:touchLocation]; // This just returns the node that has been touched


} else if (recognizer.state == UIGestureRecognizerStateChanged) {

    CGPoint translation = [recognizer translationInView:recognizer.view];
    translation = CGPointMake(translation.x, -translation.y);
    [self panForTranslation:translation];
    [recognizer setTranslation:CGPointZero inView:recognizer.view];

} else if (recognizer.state == UIGestureRecognizerStateEnded) {

   [_selectedNode removeAllActions];

}

}

Наконец, есть метод, который перемещает спрайт:

- (void)panForTranslation:(CGPoint)translation {

if([[_selectedNode name] isEqualToString:kAnimalNodeName]) {

    CGPoint position = [_selectedNode position];
    // Set variable for the point to move selected node
    CGPoint movePoint = CGPointMake(position.x + translation.x, position.y + translation.y);
    [_selectedNode setPosition:newPos];

}

}

Теперь в примере кода показаны только методы для UIPanGestureRecognizer, но у меня также есть аналогичные методы для жестов поворота и сжатия. Весь этот код находится в моем классе сцены.

Спасибо вам за помощь.


person user3491793    schedule 03.04.2014    source источник


Ответы (2)


Ну, учебник, который вы разместили, в значительной степени показывает, как это сделать...

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint positionInScene = [touch locationInNode:self];
    [self selectNodeForTouch:positionInScene];
}

- (void)selectNodeForTouch:(CGPoint)touchLocation {
    //The below statement assigns touchedNode from a sprite that contains touchLocation
    SKSpriteNode *touchedNode = (SKSpriteNode *)[self nodeAtPoint:touchLocation];

  //2
if(![_selectedNode isEqual:touchedNode]) {
    [_selectedNode removeAllActions];
    [_selectedNode runAction:[SKAction rotateToAngle:0.0f duration:0.1]];

    _selectedNode = touchedNode;

        //the below if statement determines what SKNode is to be given a SKAction
    if([[touchedNode name] isEqualToString:kAnimalNodeName]) {
    SKAction *sequence = [SKAction sequence:@[[SKAction rotateByAngle:degToRad(-4.0f) duration:0.1],
                                                  [SKAction rotateByAngle:0.0 duration:0.1],
                                                  [SKAction rotateByAngle:degToRad(4.0f) duration:0.1]]];
        [_selectedNode runAction:[SKAction repeatActionForever:sequence]];
        }
    }
}

Поэтому, если вы хотите применить действие к нескольким узлам, просто дайте им одно и то же имя. Я предлагаю назвать ваши узлы, поместить их в массив, а затем выполнить итерацию по ним, проверяя, имеют ли они одно и то же имя. Если у вас есть дополнительные вопросы, пожалуйста, прокомментируйте.

ОБНОВЛЕНИЕ: 1

- (void)panForTranslation:(CGPoint)translation {

    //Once again you would do the same thing. Just give the nodes the same name. 
    if([[_selectedNode name] isEqualToString:kAnimalNodeName]) {

        CGPoint position = [_selectedNode position];
        // Set variable for the point to move selected nodes
        CGPoint movePoint = CGPointMake(position.x + translation.x, position.y + translation.y);
        [_selectedNode setPosition:newPos];

     }
person Roecrew    schedule 03.04.2014
comment
Спасибо за помощь. Я отредактировал свой вопрос, чтобы попытаться уточнить мой вопрос и добавить код, который я использую. В этом уроке я упоминал, что он на самом деле сделал прикосновение двумя разными способами. Первый, код которого вы указали, использует касания, а второй использует UIPanGestureRecognizer, который я использую, а также UIRotateGestureRecognizer и UIPinchRecognizer. Я был бы очень признателен, если бы вы могли взглянуть на мой отредактированный вопрос и сообщить мне, если у вас есть какие-либо идеи. Еще раз спасибо за ваше время. Это так ценится. - person user3491793; 03.04.2014
comment
Итак, вы хотите применить вращение и сжатие к нескольким узлам? - person Roecrew; 03.04.2014
comment
да. Они должны быть независимыми друг от друга, чтобы каждым можно было управлять разными пальцами. - person user3491793; 03.04.2014
comment
Оооо, хорошо, вы хотите использовать UITouch. Прочтите следующую ссылку. zcentric.com/2008/09/22/multiple-objects-and -utouch - person Roecrew; 03.04.2014

Я также использую этот учебник, чтобы сделать что-то подобное. В примере кода используется переменная экземпляра selectedNode, представляющая один выбранный узел.

Чтобы это работало для нескольких узлов, я бы рекомендовал использовать NSMutableArray из selectedNodes или создать подкласс SKSpriteNode для хранения того, является ли он в данный момент «выбранным». Удачи!

person MattDevOhYeah    schedule 20.06.2014