2015-05-07 6 views
22

Voglio aggiungere uno spartito alla parte superiore della mia scena nel gioco su cui sto lavorando. Il punteggio si baserà su quanto durerà e aumenterà ogni secondo. Grazie per l'aiuto in anticipo!Come posso far eseguire una funzione ogni secondo in swift?

import SpriteKit 

class easyScene: SKScene { 
let scrollBarEasyBottom = SKSpriteNode(imageNamed: "scrollBarEasyBottom") 
let scrollBarEasyTop = SKSpriteNode(imageNamed: "scrollBarEasyTop") 
let ball = SKSpriteNode(imageNamed: "ball") 
var origSBEBpositionX = CGFloat(0) 
var origSBETpositionX = CGFloat(0) 
var maxSBEBX = CGFloat(0) 
var SBEBSpeed = 5 
var maxSBETX = CGFloat(0) 
var SBETSpeed = 5 
var score = 0 
var timer: NSTimer? 

var scoreText = SKLabelNode(fontNamed: "Kailasa") 

override func didMoveToView(view: SKView) { 
    println("Easy Scene is the location") 
    self.backgroundColor = UIColor.blackColor() 
    self.scrollBarEasyBottom.position = CGPoint(x:0, y:270) 
    self.addChild(self.scrollBarEasyBottom) 
    self.scrollBarEasyBottom.yScale = 0.2 
    self.origSBEBpositionX = self.scrollBarEasyBottom.position.x 
    // end scrollBarEasyBottom 
    self.scrollBarEasyTop.position = CGPoint(x:20, y:400) 
    self.addChild(self.scrollBarEasyTop) 
    self.scrollBarEasyTop.yScale = 0.2 
    self.origSBETpositionX = self.scrollBarEasyTop.position.x 
    // end scrollBarEasyTop 
    self.ball.position = CGPoint(x:40, y:293) 
    self.addChild(self.ball) 
    self.ball.yScale = 0.17 
    self.ball.xScale = 0.17 
    // end ball 
    self.maxSBEBX = self.scrollBarEasyBottom.size.width - self.frame.size.width 
    self.maxSBEBX *= -1 
    self.maxSBETX = self.scrollBarEasyTop.size.width - self.frame.size.width 
    self.maxSBETX *= -1 
    // 
    self.scoreText.text = "0" 
    self.scoreText.fontSize = 60 
    self.scoreText.position = CGPoint(x: CGRectGetMidX(self.frame), y: 500) 
    self.scoreText.text = String(self.score) 
    self.addChild(self.scoreText) 
    timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("scoreIncrease") , userInfo: nil, repeats: true) 
    func scoreIncrease(){ 
     score++ 
     println(score) 
    } 


} 
override func update(currentTime: NSTimeInterval){ 
    if self.scrollBarEasyBottom.position.x <= maxSBEBX + 1200 { 
     self.scrollBarEasyBottom.position.x = self.origSBEBpositionX 
    } 
    if self.scrollBarEasyTop.position.x <= maxSBETX + 1200 { 
     self.scrollBarEasyTop.position.x = self.origSBETpositionX 
    } 

    scrollBarEasyBottom.position.x -= CGFloat(self.SBEBSpeed) 
    scrollBarEasyTop.position.x -= CGFloat(self.SBETSpeed) 
    // moving bars 
    var degreeRotation = CDouble(self.SBEBSpeed) * M_PI/180 
    self.ball.zRotation -= CGFloat(degreeRotation) 
    //rotate ball 


    } 


    } 

Dopo l'esecuzione di questo codice, ho sempre arrivare un "selettore non riconosciuto inviato ad errori istanza".

+0

Potresti valido un risponderti per favore! – Zl3n

+3

Tutte queste risposte non sono così utili in realtà. In SpriteKit dovresti prendere in considerazione l'utilizzo di SKactions per cose legate al tempo. Cerca su questo su SO. In generale, un Timer (NSTimer) non rispetta lo stato di pausa del nodo, della scena o della vista, quindi può portare a determinati problemi. D'altro canto, le SKActions vengono messe automaticamente in pausa se il nodo, la scena o una vista vengono messe in pausa durante una partita o ad alcune interruzioni come una telefonata ecc. – Whirlwind

risposta

22

C'è qualcosa chiamato NSTimer in rapido che potrebbe risolvere il tuo problema. Ho dato un esempio come puoi usarlo. Personalizzalo per il tuo scopo.

var timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("yourMethodToCall"), userInfo: nil, repeats: true) 

Aggiungere questa riga al punto in cui è necessario chiamare ripetutamente la funzione.

  1. Il 1.0 si riferisce a 1 secondo.
  2. Modificare il selector chiamare yourMethodName
  3. repeats è impostato su true chiamare quella funzione ogni secondo.

Provalo e fammi sapere se sei bloccato da qualche parte. Grazie.

+0

A proposito del mio codice, penso di aver provato a farlo. Probabilmente sto usando male in qualche modo perché sono ancora un principiante, ma sarebbe bello se potessi dare un'occhiata a questo. Potresti averlo perso quando l'hai guardato per la prima volta. Grazie! –

+2

Prova a mettere il metodo 'scoreIncrease' al di fuori del metodo' didMoveToView'. –

+0

Questo ha risolto il mio problema grazie mille! Ora il mio problema è che anche se il mio output stampa "score" ogni secondo, il numero sullo schermo di gioco rimane a 0. –

35

È possibile utilizzare uno come questo:

var timer = NSTimer() 

override func viewDidLoad() { 
     scheduledTimerWithTimeInterval() 
} 

func scheduledTimerWithTimeInterval(){ 
     // Scheduling timer to Call the function "updateCounting" with the interval of 1 seconds 
     timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("updateCounting"), userInfo: nil, repeats: true) 
    } 


    func updateCounting(){ 
     NSLog("counting..") 
    } 

Swift 3:

var timer = Timer() 

override func viewDidLoad() {    // Use for the app's interface 
     scheduledTimerWithTimeInterval() 
} 

override func didMove(to view: SKView) { // As part of a game 
     scheduledTimerWithTimeInterval() 
} 

func scheduledTimerWithTimeInterval(){ 
    // Scheduling timer to Call the function "updateCounting" with the interval of 1 seconds 
    timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.updateCounting), userInfo: nil, repeats: true) 
} 

func updateCounting(){ 
    NSLog("counting..") 
} 
+2

Grazie mille! Ho una domanda, come posso interrompere il timer? – senty

+8

timer.invalidate() – palme

5

Swift 3

trovare questa soluzione ha funzionato per me

weak var timer: Timer? 
var timerDispatchSourceTimer : DispatchSourceTimer? 

func startTimer() { 
    if #available(iOS 10.0, *) { 
     timer = Timer.scheduledTimer(withTimeInterval: 3, repeats: true) { [weak self] _ in 
      // do something here 

     } 

    } else { 
     // Fallback on earlier versions 
     timerDispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main) 
     timerDispatchSourceTimer?.scheduleRepeating(deadline: .now(), interval: .seconds(60)) 
     timerDispatchSourceTimer?.setEventHandler{ 
       // do something here 

     } 
     timerDispatchSourceTimer?.resume() 
    } 
} 

func stopTimer() { 
    timer?.invalidate() 
    //timerDispatchSourceTimer?.suspend() // if you want to suspend timer 
    timerDispatchSourceTimer?.cancel() 
} 

// if appropriate, make sure to stop your timer in `deinit` 
deinit { 
    stopTimer() 
} 
+1

L'utilizzo di NSTimer in SpriteKit non è un metodo preferito per le azioni basate sul tempo. Non rispetta lo stato di pausa del nodo, della scena o della vista e può portare a determinati problemi in alcune situazioni. Usare SKActions o aggiornare: il metodo è un'alternativa migliore. – Whirlwind

+0

@Whirlwind non ho mai usato SpirteKit, ma è ora di informarlo :) grazie per l'ispirazione –

0

// Per l'esecuzione di un pezzo di codice ogni secondo

///Runs every second, to cancel use: timer.invalidate() 
@discardableResult public static func runThisEvery(
    seconds: TimeInterval, 
    startAfterSeconds: TimeInterval, 
    handler: @escaping (CFRunLoopTimer?) -> Void) -> Timer { 
    let fireDate = startAfterSeconds + CFAbsoluteTimeGetCurrent() 
    let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, seconds, 0, 0, handler) 
    CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.commonModes) 
    return timer! 
}