在我的游戏中,有一个类用于向左移动的"墙"。我想根据添加到touchesBegan
方法中的i
计数来改变它的速度:
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent {
count++
}
func startMoving() {
let moveLeft = SKAction.moveByX(-kDefaultXToMovePerSecond, y: 0, duration: 1 )
let move = SKAction.moveByX(-kDefaultXToMovePerSecond, y: 0, duration: 0.5)
if(count <= 10)
{
runAction(SKAction.repeatActionForever(moveLeft))
}
else
{
runAction(SKAction.repeatActionForever(move))
}
}
但它不起作用。你能帮忙吗?
就像我说的,有很多改动需要做:
首先让我们改变MLWall类并添加一个持续时间属性,它将在startMoving方法中使用:
var duration:NSTimeInterval = 0.5
然后仍然在MLWall类中更改初始化方法:
init(duration: NSTimeInterval) {
self.duration = duration
//...
}
并更改startMoving方法以使用传递的参数:
func startMoving() {
let moveLeft = SKAction.moveByX(-kDefaultXToMovePerSecond, y: 0, duration: self.duration)
runAction(SKAction.repeatActionForever(moveLeft))
}
这些是Wall类内部的变化。现在让我们在WallGenerator类中做一些更改:
第一个WallGenerator类应该知道墙应该走多快。所以我们添加属性来存储信息:
var currentDuration: NSTimeInterval = 1 // I named it duration, because SKAction takes duration as a parameter, but this actually affects on speed of a wall.
之后,第一个必须更改的方法是startGeneratingWallsEvery(second:)到startGeneratingWallsEvery(second: duration:
//duration parameter added
func startGeneratingWallsEvery(seconds: NSTimeInterval, duration : NSTimeInterval) {
self.currentDuration = duration
generationTimer = NSTimer.scheduledTimerWithTimeInterval(seconds, target: self, selector: "generateWall", userInfo: nil, repeats: true)
}
在这里,我们正在使WallGenerator意识到所需的墙的速度。下一个需要修改的方法是
//duration parameter added
func generateWall() {
//...
//Duration parameter added
let wall = MLWall(duration: self.currentDuration)
//...
}
还有一个GameScene。在这里,我添加了一个tapCounter属性:
let debugLabel = SKLabelNode(fontNamed: "Arial") //I've also added a debug label to track taps count visually
var tapCounter = 0
如果你想看到tap计数的数目,可以这样初始化label:
//Setup debug label
debugLabel.text = "Tap counter : (tapCounter)"
debugLabel.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMaxY(frame)-50.0)
debugLabel.fontColor = SKColor.purpleColor()
self.addChild(debugLabel)
首先我改变了start方法:
func start() {
//...
// adding duration parameter in method call
wallGenerator.startGeneratingWallsEvery(1,duration: 1)
}
重要的部分是:wallGenerator.startGeneratingWallsEvery(1,duration: 1)
,它说开始产生墙每秒钟与一秒钟的持续时间(这影响节点的速度)。
if isGameOver {
restart()
} else if !isStarted {
start()
} else {
tapCounter++
debugLabel.text = "Tap counter : (tapCounter)"
if(tapCounter > 10){
wallGenerator.stopGenerating()
wallGenerator.startGeneratingWallsEvery(0.5, duration:0.5)
}
hero.flip()
}
然后,更改restart()方法,以便在游戏结束时重新启动计数器:
func restart() {
tapCounter = 0
//...
}
差不多就是这样了。我想我没有忘记什么,但在我身边,它就像它应该的那样工作。此外,请注意,使用NSTimer从这个GitHub项目不是你想在SpriteKit。那是因为NSTimer不尊重场景,视图或节点的暂停状态。这意味着即使你认为游戏暂停了,它也会继续刷墙。对于这种情况,SKAction将是首选的替代品。
希望这对你有帮助,如果你有进一步的问题,请随时提问,但我想你可以从上面的代码中理解发生了什么。基本上所做的是,WallGenerator已经意识到他们的wall节点应该有多快,而wall node也意识到它应该有多快…
编辑:还有另一种改变墙壁速度的方法,那就是用键运行移动动作。然后,在刷出的那一刻,基于tapCounter的值,你可以通过键访问移动的动作,并直接改变动作的速度属性…这可能是一个更短的方法,但仍然需要一些改变(在Wall类中传递一个duration参数,并在场景中实现tapCounter)。
试着这样做:
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent {
count++
startMoving()
}
func startMoving() {
removeAllActions()
let moveLeft = SKAction.moveByX(-kDefaultXToMovePerSecond, y: 0, duration: count <= 10 ? 1.0 : 0.5)
runAction(SKAction.repeatActionForever(moveLeft))
}
当我看到你的问题下面的评论时,你提出了一个非常不清楚的问题,但是你的代码中存在意识形态问题。
如果我没理解错的话,你的touchesBegan
方法是在墙上实现的,所以它对新生成的墙没有影响。你必须将逻辑移动到场景中,然后以速度作为参数生成新墙,或者至少将count
作为类var,这样每面墙都可以访问它,但你仍然需要处理场景中的触摸,因为现在当用户直接点击墙壁时,触摸会被处理。