SpriteKit: как плавно анимировать SKCameraNode при отслеживании узла, но только после того, как узел переместит Y пикселей?

Этот вопрос и другие обсуждают, как отслеживать узел в SpriteKit с помощью SKCameraNode.

Однако наши потребности различаются.

Другие решения, такие как обновление положения камеры в update(_ currentTime: CFTimeInterval) SKScene, не работают, потому что мы хотим настроить положение камеры только после того, как узел переместил Y пикселей вниз по экрану.

Другими словами, если узел перемещается на 10 пикселей вверх, камера должна оставаться неподвижной. Если узел перемещается влево или вправо, камера должна оставаться неподвижной.

Мы пытались анимировать положение камеры во времени, а не мгновенно, но выполнение SKAction против камеры внутри update(_ currentTime: CFTimeInterval) ничего не дало.


person Crashalot    schedule 05.12.2016    source источник
comment
просто отслеживайте местоположение спрайта и ограничивайте движение узла камеры в зависимости от этого местоположения.   -  person GeneCode    schedule 05.12.2016
comment
@GeneCode да, но где? update(_ currentTime: CFTimeInterval) не работало, когда мы пытались анимировать движение SKCameraNode?   -  person Crashalot    schedule 05.12.2016
comment
Да, использование SKAction в методе обновления не является хорошей практикой, потому что обновление вызывается много раз в секунду.   -  person GeneCode    schedule 05.12.2016
comment
@GeneCode верно, так где вы предлагаете анимировать SKCameraNode?   -  person Crashalot    schedule 05.12.2016
comment
обновите позиционирование SKCameraNode. Но не анимировать. Просто примените положение сразу.   -  person GeneCode    schedule 05.12.2016
comment
это сработало для вас?   -  person GeneCode    schedule 05.12.2016


Ответы (2)


Я просто быстро сделал это. Я полагаю, это то, что вы ищете? (фактическая анимация плавная, просто мне пришлось сжать GIF)

введите описание изображения здесь

Это код обновления:

-(void)update:(CFTimeInterval)currentTime {
    /* Called before each frame is rendered */

    SKShapeNode *ball = (SKShapeNode*)[self childNodeWithName:@"ball"];
    if (ball.position.y>100) camera.position = ball.position;

    if (fabs(ball.position.x-newLoc.x)>10) {
        // move x
        ball.position = CGPointMake(ball.position.x+stepX, ball.position.y);
    }

    if (fabs(ball.position.y-newLoc.y)>10) {
        // move y
        ball.position = CGPointMake(ball.position.x, ball.position.y+stepY);
    }
}
person GeneCode    schedule 05.12.2016
comment
Спасибо за усилия, но это фактически то, что мы делали раньше. Это привело к очень рывковому движению, потому что узел движется быстро (падает под действием силы тяжести). - person Crashalot; 05.12.2016
comment
Если ваше движение дергается, скорее всего, это не из-за этого, а из-за того, как вы двигаете свой спрайт. Вы реализовали timeElapsed*speed для перемещения спрайта? - person GeneCode; 06.12.2016
comment
Или, может быть, раз уж вы используете физику, лучше вместо этого поместить все, что связано с движениями, в делегат didsimulatephysics? - person GeneCode; 06.12.2016
comment
Спасибо за быстрый ответ. Если мы не двигаем камеру, движение спрайта будет плавным, поэтому не похоже, что это проблема, связанная с перемещением спрайта. Дрожание возникает только при перемещении камеры в соответствии с новой позицией спрайта, что происходит только в том случае, если спрайт падает примерно на 50 пикселей. - person Crashalot; 06.12.2016
comment
У меня больше нет идей. Последнее предложение - попробовать сделать движение камеры в didsimulatephysics. Удачи. - person GeneCode; 06.12.2016

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

Вместо этого создайте подкласс для вашего узла персонажа и переопределите свойство position. По сути, мы говорим, что если ваша камера находится в 10 пикселях от вашего персонажа, двигайтесь к нему. Мы используем ключ в нашем действии, чтобы не накладывать несколько действий друг на друга, и режим синхронизации, позволяющий камере плавно перемещаться к вашей точке, а не мгновенно.

class MyCharacter : SKSpriteNode
{
    override var position : CGPoint
    {
        didSet
        {

            if let scene = self.scene, let camera = scene.camera,(abs(position.y - camera.position.y) > 10)
            {
                let move = SKAction.move(to: position, duration:0.1)
                move.timingMode = .easeInEaseOut
                camera.run(move,withKey:"moving")
            }
        }
    }
}

Редактировать: @Epsilon напомнил мне, что SKActions и SKPhysics обращаются к переменной напрямую, а не через сохраненное свойство, поэтому это не сработает. В этом случае сделайте это в методе didFinishUpdate:

override func didFinishUpdate()
{
    //character should be a known property to the class,  calling find everytime is too slow
    if let character = self.character, let camera = self.camera,(abs(character.position.y - camera.position.y) > 10)
    {
        let move = SKAction.move(to: character.position, duration:0.1)
        move.timingMode = .easeInEaseOut
        camera.run(move,withKey:"moving")
    }
}
person Knight0fDragon    schedule 05.12.2016
comment
если камера движется только вниз, то убери абс и сделай ‹=-10 - person Knight0fDragon; 05.12.2016
comment
Это будет работать только в том случае, если вы зададите положение персонажа напрямую. Если вы перемещаете персонажа с помощью действия или применяя силу/импульс к его physicsBody, didSet не будет вызываться, потому что свойство position не установлено напрямую. - person Epsilon; 05.12.2016
comment
Это правда, но вы можете обойти это, выполнив character.position = character.position в didFinishUpdate, что возвращает нас к ответу GeneCodes, просто используя другую функцию, или используйте customActions для перемещения вместо использования встроенного для перемещения вашего спрайт - person Knight0fDragon; 06.12.2016
comment
Спасибо за подробный ответ Найт. @Epsilon, у тебя есть другие предложения? - person Crashalot; 06.12.2016
comment
Запуск SKAction внутри didFinishUpdate не дает никакого эффекта. Делает ли это что-то для вас? - person Crashalot; 06.12.2016
comment
это должно повлиять на следующую фазу действия цикла - person Knight0fDragon; 06.12.2016
comment
как часто камера будет двигаться? это может быть легкость в том, что ничего не делает для вас - person Knight0fDragon; 06.12.2016
comment
вы можете поставить свои ходы в очередь, но это немного безумно, и я бы порекомендовал вместо этого переключиться на customAction - person Knight0fDragon; 06.12.2016