@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];
}
}
#1 楼
在Sprite Kit中不要使用NSTimer
,performSelector:afterDelay:
或Grand Central Dispatch(GCD,即任何dispatch_...
方法),因为这些计时方法会忽略节点,场景或视图的paused
状态。而且,您不知道它们在游戏循环中的哪一点执行,这可能会导致各种问题,具体取决于您的代码实际执行的操作。仅有的两种批准的方式可以在基于时间的情况下执行某些操作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]]]];
或者,您也可以使用
performSelector:onTarget:
代替runBlock:
或如果需要模仿SKScene customActionWithDuration:actionBlock:
方法并且不知道如何将其转发到节点或转发不便的地方,则可以使用update:
。有关详细信息,请参阅SKAction参考。
更新:使用Swift的代码示例
Swift 5
run(SKAction.repeatForever(SKAction.sequence([
SKAction.run( /*code block or a func name to call*/ ),
SKAction.wait(forDuration: 2.5)
])))
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]))
并重复运行代码:
runAction(SKAction.repeatActionForever(SKAction.sequence([wait, run])))
评论
@ LearnCocos2D完美运行!为了防止其他用户出错,我建议在第三行添加一个封闭的括号以停止语法错误。
–user3578149
2014年6月1日上午10:56
固定错字,添加重复示例
–LearnCocos2D
2014年6月1日,11:03
我如何将其翻译成Swift?
–何塞·玛丽亚(JoséMaría)
2014年7月7日14:04
我添加了Swift代码片段。尚未测试它是否可以编译。让我知道是否可以。
–LearnCocos2D
2014年12月17日的15:00
重复执行该操作无济于事,因为这会造成很大的性能损失。我需要每秒进行一次动作,也许动作太激烈了。因此,我建议使用更新方法。编辑:由于某种原因,Product> Clean解决了该问题,我将其收回。
– 3366784
15-10-16在3:40
#2 楼
在Swift中可用: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])))
#3 楼
我以上面的示例为例,并为时钟添加了前导零。 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])))
}
#4 楼
这是使用Xcode 9.3和Swift 4.1为SpriteKit构建计时器的完整代码。在我们的示例中,分数标签将每2递增1秒。
这是最终结果
好,我们开始吧!
1)得分标签
首先我们需要一个标签
class GameScene: SKScene {
private let label = SKLabelNode(text: "Score: 0")
}
2)得分标签进入场景
class GameScene: SKScene {
private let label = SKLabelNode(text: "Score: 0")
override func didMove(to view: SKView) {
self.label.fontSize = 60
self.addChild(label)
}
}
现在标签位于屏幕的中心。让我们运行项目来查看它。
请注意,此时标签尚未更新!
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)
}
}
#5 楼
以下代码创建一个新线程,并等待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
});
}
});
无论何时要停止它,只需将
continueIncrementingScore
设置为NO
评论
错误的例子,因为有dispatch_after
–LearnCocos2D
2014年6月1日10:28
评论
为什么不重写update(currentTime)方法? “只要场景在视图中呈现且不暂停,则每帧恰好调用一次”