запустить SKAction на основе количества символов текста узла SKLabel

У меня есть игровая сцена, состоящая из анимаций, происходящих синхронно с содержанием песни. Одно из действий, которое я пытаюсь настроить, относится к тексту песни, который отображается с помощью SKLabelNode. Что я хочу сделать, так это переключаться между двумя анимациями в зависимости от того, есть ли символы в LabelNode (певец перестает «петь» и ждет). У меня есть это в методе обновления:

var singerActive = false
var lyricsLabel = SKLabelNode()

override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */
        if lyricsLabel.text?.characters.count == 0{
            singerActive = false
        }else{
            singerActive = true
        }

        let sings = SKAction.runBlock { () -> Void in
            self.singer.runAction(SKAction.fadeAlphaTo(1, duration: 0.1))
            self.singerIdle.runAction(SKAction.fadeAlphaTo(0, duration: 0.1))
        }
        let singerInactive = SKAction.runBlock { () -> Void in
            self.singer.runAction(SKAction.fadeAlphaTo(0, duration: 0.1))
            self.singerIdle.runAction(SKAction.fadeAlphaTo(1, duration: 0.1))
        }

        var stopper = true
        if singerActive && stopper{
            stopper = false
            singer.runAction(sings)
        }

        if singerActive == false && stopper == false{

            stopper = true
            singer.runAction(singerInactive)
        }

    }

К сожалению, похоже, это не работает. Активное состояние певца работает, но неактивное состояние не срабатывает, когда количество символов == 0. Я поместил туда логическое значение «stopper», чтобы гарантировать, что SKAction не будет вызываться постоянно, как в методе обновления. Я новичок в Swift и SpriteKit, поэтому любая помощь будет очень признательна.


person derekFairholm    schedule 18.02.2016    source источник
comment
вот что я вижу. в неактивном состоянии ваше первое условие не выполняется, поэтому стопор никогда не меняется, поэтому ваше второе условие не выполняется, потому что стопор всегда истинен   -  person Knight0fDragon    schedule 19.02.2016


Ответы (1)


Ваш стопорный код все ломает, вы хотите сделать что-то вроде этого:

    override func update(currentTime: CFTimeInterval) {
    /* Called before each frame is rendered */
    if lyricsLabel.text?.characters.count == 0{
        singerActive = false
    }else{
        singerActive = true
    }

    let sings = SKAction.runBlock { () -> Void in
        self.singer.runAction(SKAction.fadeAlphaTo(1, duration: 0.1))
        self.singerIdle.runAction(SKAction.fadeAlphaTo(0, duration: 0.1))
    }
    let singerInactive = SKAction.runBlock { () -> Void in
        self.singer.runAction(SKAction.fadeAlphaTo(0, duration: 0.1))
        self.singerIdle.runAction(SKAction.fadeAlphaTo(1, duration: 0.1))
    }

    if singerActive{
        singer.removeAllActions()
        singer.runAction(sings)
    }
    else{
        singer.removeAllActions()
        singer.runAction(singerInactive)
    }

}

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

Итак, вам нужно сделать что-то вроде этого:

    override func update(currentTime: CFTimeInterval) {
    /* Called before each frame is rendered */
    if lyricsLabel.text?.characters.count == 0{
        singerActive = false
    }else{
        singerActive = true
    }

    let sings = SKAction.runBlock { () -> Void in
        self.singer.runAction(SKAction.fadeAlphaTo(1, duration: 0.1))
        self.singerIdle.runAction(SKAction.fadeAlphaTo(0, duration: 0.1))
    }
    let singerInactive = SKAction.runBlock { () -> Void in
        self.singer.runAction(SKAction.fadeAlphaTo(0, duration: 0.1))
        self.singerIdle.runAction(SKAction.fadeAlphaTo(1, duration: 0.1))
    }

    if singerActive && singerIdle.alpha = 1{
        singer.removeAllActions()
        singerIdle.alpha = 0.99;
        singer.runAction(sings)
    }
    else if !singerActive && singer.alpha = 1{
        singer.removeAllActions()
        singer.alpha = 0.99;
        singer.runAction(singerInactive)
    }

}

Теперь мы вызываем его только тогда, когда наши альфа-состояния равны 1.

person Knight0fDragon    schedule 18.02.2016
comment
Большое спасибо! Это работает хорошо, за исключением того, что мне нужно было удалить метод removeAllActions()... каждая анимация выполняется непрерывно, и я просто меняю альфа-состояния, чтобы сделать желаемую анимацию видимой. - person derekFairholm; 19.02.2016
comment
если вы не удалите AllActions, то они будут накапливаться на вас, я предполагаю, что этот код работает так быстро, что removeAllActions удаляет действия, прежде чем что-либо сделать - person Knight0fDragon; 19.02.2016
comment
Есть ли какой-то способ сделать хотя бы скейшн вне апдейта? Кажется, должен быть более чистый способ справиться с этим... - person derekFairholm; 20.02.2016
comment
не уверен, что вы собираетесь здесь делать, но есть несколько способов сделать это вне вашего обновления, я просто не собирался переписывать ваш код. Вы можете добавить прослушиватель при изменении текста метки или создать строковое свойство и использовать didSet для запуска действий при появлении/исчезновении нового слова, а затем назначить это строковое свойство тексту. - person Knight0fDragon; 20.02.2016
comment
Не могли бы вы объяснить добавление слушателя? Довольно новичок в этом, очень ценится. - person derekFairholm; 20.02.2016
comment
raywenderlich.com/90773/ посмотрите на наблюдение за ключом-значением - person Knight0fDragon; 20.02.2016