如何改变一个运动的持续时间计数- Swift SpriteKit



在我的游戏中,有一个类用于向左移动的"墙"。我想根据添加到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),它说开始产生墙每秒钟与一秒钟的持续时间(这影响节点的速度)。

接下来,我将场景的touchesBegan修改为:
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,这样每面墙都可以访问它,但你仍然需要处理场景中的触摸,因为现在当用户直接点击墙壁时,触摸会被处理。

最新更新