2014-06-01 13 views
23

Come posso creare un timer che scatta ogni due secondi che incrementerà il punteggio di uno su un HUD che ho sullo schermo? Questo è il codice che ho per l'HUD:SpriteKit - Creazione di un timer

@implementation MyScene 
{ 
    int counter; 
    BOOL updateLabel; 
    SKLabelNode *counterLabel; 
} 

-(id)initWithSize:(CGSize)size 
{ 
    if (self = [super initWithSize:size]) 
    { 
     counter = 0; 

     updateLabel = false; 

     counterLabel = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"]; 
     counterLabel.name = @"myCounterLabel"; 
     counterLabel.text = @"0"; 
     counterLabel.fontSize = 20; 
     counterLabel.fontColor = [SKColor yellowColor]; 
     counterLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter; 
     counterLabel.verticalAlignmentMode = SKLabelVerticalAlignmentModeBottom; 
     counterLabel.position = CGPointMake(50,50); // change x,y to location you want 
     counterLabel.zPosition = 900; 
     [self addChild: counterLabel]; 
    } 
} 
+0

Perché non eseguire l'override del metodo di aggiornamento (currentTime)? "è chiamato esattamente una volta per fotogramma, purché la scena sia presentata in una vista e non venga messa in pausa" – OhadM

risposta

56

In Sprite Kit non utilizzareNSTimer, performSelector:afterDelay: o Grand Central Dispatch (GCD, vale a dire qualsiasi metodo dispatch_...) perché thes I metodi di temporizzazione ignorano lo stato di un nodo, della scena o della vista paused. Inoltre, non si sa a che punto del ciclo di gioco sono stati eseguiti, il che può causare una serie di problemi a seconda di ciò che effettivamente fa il codice.

Gli unici due modi sanzionati per eseguire qualcosa basato sul tempo in Sprite Kit è usare sia per il metodo SKScene update: e utilizzando il parametro passato-in currentTime per tenere traccia del tempo.

o più comunemente si sarebbe solo utilizzare una sequenza d'azione che inizia con un'azione di attesa:

id wait = [SKAction waitForDuration:2.5]; 
id run = [SKAction runBlock:^{ 
    // your code here ... 
}]; 
[node runAction:[SKAction sequence:@[wait, run]]]; 

E per eseguire il codice più volte:

[node runAction:[SKAction repeatActionForever:[SKAction sequence:@[wait, run]]]]; 

In alternativa si può anche utilizzare performSelector:onTarget: invece di runBlock: o forse usare un customActionWithDuration:actionBlock: se è necessario imitare il metodo SKScene update: e non sapere come inoltrarlo al nodo o dove l'inoltro sarebbe inopportuno.

Vedere SKAction reference per dettagli.


UPDATE: Esempi di codice che utilizzano Swift

Swift 3

let wait = SKAction.wait(forDuration:2.5) 
let action = SKAction.run { 
    // your code here ... 
} 
run(SKAction.sequence([wait,action])) 

Swift 2

let wait = SKAction.waitForDuration(2.5) 
let run = SKAction.runBlock { 
    // your code here ... 
} 
runAction(SKAction.sequence([wait, run])) 

Aund per eseguire il codice più volte:

runAction(SKAction.repeatActionForever(SKAction.sequence([wait, run]))) 
+0

@ LearnCocos2D Funziona perfettamente! Solo per evitare errori da altri utenti, suggerisco di aggiungere una parentesi chiusa sulla terza riga per interrompere gli errori di sintassi. – user3578149

+2

errore di battitura fisso, aggiunto esempio ripetuto – LearnCocos2D

+0

Come tradurrei questo in Swift? –

-3

Il codice seguente crea un nuovo thread e attende 2 secondi prima di fare qualcosa sul thread principale:

BOOL continueIncrementingScore = YES; 

dispatch_async(dispatch_queue_create("timer", NULL);, ^{ 
    while(continueIncrementingScore) { 
     [NSThread sleepForTimeInterval:2]; 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      // this is performed on the main thread - increment score here 

     }); 
    } 
}); 

ogni volta che vuoi per fermarlo - basta impostare continueIncrementingScore-NO

+1

cattivo esempio perché c'è dispatch_after – LearnCocos2D

5

In Swift utilizzabile:

var timescore = Int() 
var actionwait = SKAction.waitForDuration(0.5) 
      var timesecond = Int() 
      var actionrun = SKAction.runBlock({ 
        timescore++ 
        timesecond++ 
        if timesecond == 60 {timesecond = 0} 
        scoreLabel.text = "Score Time: \(timescore/60):\(timesecond)" 
       }) 
      scoreLabel.runAction(SKAction.repeatActionForever(SKAction.sequence([actionwait,actionrun]))) 
5

ho preso l'esempio di cui sopra e rapida aggiunto in zeri per l'orologio.

func updateClock() { 
    var leadingZero = "" 
    var leadingZeroMin = "" 
    var timeMin = Int() 
    var actionwait = SKAction.waitForDuration(1.0) 
    var timesecond = Int() 
    var actionrun = SKAction.runBlock({ 
     timeMin++ 
     timesecond++ 
     if timesecond == 60 {timesecond = 0} 
     if timeMin/60 <= 9 { leadingZeroMin = "0" } else { leadingZeroMin = "" } 
     if timesecond <= 9 { leadingZero = "0" } else { leadingZero = "" } 

     self.flyTimeText.text = "Flight Time [ \(leadingZeroMin)\(timeMin/60) : \(leadingZero)\(timesecond) ]" 
    }) 
    self.flyTimeText.runAction(SKAction.repeatActionForever(SKAction.sequence([actionwait,actionrun]))) 
}