Ios SpriteKit-创建计时器

Ios SpriteKit-创建计时器,ios,objective-c,timer,sprite-kit,Ios,Objective C,Timer,Sprite Kit,我如何创建一个每两秒钟启动一次的计时器,使屏幕上的HUD上的分数增加一分?这是我的HUD代码: @implementation MyScene { int counter; BOOL updateLabel; SKLabelNode *counterLabel; } -(id)initWithSize:(CGSize)size { if (self = [super initWithSize:size]) { counter =

我如何创建一个每两秒钟启动一次的计时器,使屏幕上的HUD上的分数增加一分?这是我的HUD代码:

    @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];
    }
}

以下代码创建一个新线程并等待2秒钟,然后在主线程上执行操作:

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

        });
    }
});

无论何时,只要在Sprite Kit中将
continueIncrementingScore
设置为
NO

,不要使用
NSTimer
性能选择器:afterDelay:
或Grand Central Dispatch(GCD,即任何
Dispatch.
方法),因为这些计时方法忽略了节点的,场景或视图的
暂停
状态。此外,您不知道它们在游戏循环中的哪一点执行,这可能会导致各种问题,具体取决于您的代码实际执行了什么

在Sprite Kit中执行基于时间的操作的唯一两种方法是使用SKScene
update:
方法和使用传入的currentTime参数跟踪时间

或者更常见的情况是,您只需使用以等待操作开始的操作序列:

id wait = [SKAction waitForDuration:2.5];
id run = [SKAction runBlock:^{
    // your code here ...
}];
[node runAction:[SKAction sequence:@[wait, run]]];
要重复运行代码,请执行以下操作:

[node runAction:[SKAction repeatActionForever:[SKAction sequence:@[wait, run]]]];
runAction(SKAction.repeatActionForever(SKAction.sequence([wait, run])))
或者,您也可以使用
性能选择器:onTarget:
而不是
运行块:
,或者如果您需要模拟SKScene
更新:
方法,并且不知道如何将其转发到节点或转发不方便的地方,也可以使用
customActionWithDuration:actionBlock:

有关详细信息,请参阅


更新:使用Swift编写示例代码

斯威夫特5

 run(SKAction.repeatForever(SKAction.sequence([
     SKAction.run( /*code block or a func name to call*/ ),
     SKAction.wait(forDuration: 2.5)
     ])))
斯威夫特3

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

let wait = SKAction.waitForDuration(2.5)
let run = SKAction.runBlock {
    // your code here ...
}
runAction(SKAction.sequence([wait, run]))
要重复运行代码,请执行以下操作:

[node runAction:[SKAction repeatActionForever:[SKAction sequence:@[wait, run]]]];
runAction(SKAction.repeatActionForever(SKAction.sequence([wait, run])))
在下列情况下:

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])))

我以上面的swift示例为例,为时钟添加了前导零

    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])))
}
func updatelock(){
var leadingZero=“”
var leadingZeroMin=“”
var timeMin=Int()
var actionwait=SKAction.waitForDuration(1.0)
var timesecond=Int()
var actionrun=SKAction.runBlock({
timeMin++
秒++
如果timesecond==60{timesecond=0}

如果timeMin/60以下是使用Xcode 9.3和Swift 4.1为SpriteKit构建计时器的完整代码

在我们的示例中,分数标签将每2秒递增1。 这是最后的结果

好,我们开始吧

1) 分数标签 首先,我们需要一个标签

class GameScene: SKScene {
    private let label = SKLabelNode(text: "Score: 0")
}
2) 乐谱标签进入场景 现在标签位于屏幕中央。让我们运行项目来查看它

请注意,此时标签未更新

3) 柜台 我们还希望构建一个计数器属性,该属性将保存标签显示的当前值。我们还希望在更改计数器属性后立即更新标签,以便

class GameScene: SKScene {

    private let label = SKLabelNode(text: "Score: 0")
    private var counter = 0 {
        didSet {
            self.label.text = "Score: \(self.counter)"
        }
    }

    override func didMove(to view: SKView) {
        self.label.fontSize = 60
        self.addChild(label)

        // let's test it!
        self.counter = 123
    }
}

4) 行动 最后,我们要构建一个每2秒将递增计数器的操作

class GameScene: SKScene {

    private let label = SKLabelNode(text: "Score: 0")
    private var counter = 0 {
        didSet {
            self.label.text = "Score: \(self.counter)"
        }
    }

    override func didMove(to view: SKView) {
        self.label.fontSize = 60
        self.addChild(label)
        // 1 wait action
        let wait2Seconds = SKAction.wait(forDuration: 2)
        // 2 increment action
        let incrementCounter = SKAction.run { [weak self] in
            self?.counter += 1
        }
        // 3. wait + increment
        let sequence = SKAction.sequence([wait2Seconds, incrementCounter])
        // 4. (wait + increment) forever
        let repeatForever = SKAction.repeatForever(sequence)

        // run it!
        self.run(repeatForever)
    }
}

坏例子,因为有调度_after@LearnCocos2D非常好用!为了防止其他用户出错,我建议在第三行添加一个闭括号以阻止语法错误。修复了打字错误,添加了重复示例如何将其转换为Swift?我添加了Swift代码片段。尚未测试它是否编译。如果不编译,请告诉我。重复该操作没有帮助,因为它会造成很大的性能损失。我需要每秒运行一次该操作,可能太激烈了。出于这个原因,我建议使用更新方法。编辑:我收回它,因为某些原因产品>清理解决了问题。为什么不重写更新(currentTime)方法?只要场景显示在视图中且未暂停,则每帧仅调用一次