如何使用 count-Swift SpriteKit 更改运动的持续时间?

Posted

技术标签:

【中文标题】如何使用 count-Swift SpriteKit 更改运动的持续时间?【英文标题】:How to change the duration of a movement with count- Swift SpriteKit? 【发布时间】:2015-08-03 10:19:36 【问题描述】:

在我的游戏中,有一个向左移动的“墙”类。我想根据我添加到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))
    

但它不起作用。你能帮忙吗?

【问题讨论】:

看起来你正在场景中运行一个动作。尝试在墙节点上运行一个操作。 我正在墙上类上运行这个 从您发布的代码中看起来不像。 startMoving() 方法是 Wall 类还是 GameScene 类的成员?如果它是 GameScene 类的成员,那么你应该这样做:wallNode.runAction(...) 而不是 runAction(...) 所有这些代码都在 Wall 类中,我添加了 touchesBegun:tinypic.com/r/1058576/8 所以你在节点的 init 方法中调用 startMoving() 方法,对吧?在这种情况下,计数器始终等于 0,因此 startMoving() 方法中的 else 块永远不会执行。实际上,我不确定这里的主要问题是什么?墙节点是否移动?墙节点接收触摸有问题吗? 【参考方案1】:

正如我所说,有很多改变需要做:

首先让我们更改 MLWall 类并添加一个将在 startMoving 方法中使用的持续时间属性:

var duration:NSTimeInterval = 0.5

然后还是在MLWall类里面修改init方法:

 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

如果您想查看点击次数,可以通过以下方式初始化标签:

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

首先我改变了启动方法:

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
       //...
 

差不多就是这样。我想我没有忘记什么,但在我身边,它应该可以正常工作。另外,请注意,像 GitHub project 这样使用 NSTimer 并不是您在 SpriteKit 中想要的。那是因为 NSTimer 不尊重场景、视图或节点的暂停状态。这意味着即使您认为游戏已暂停,它也会继续生成墙。 SKAction 将是这种情况的首选替代品。

希望这会有所帮助,如果您还有其他问题,请随时提出,但我想您可以从上面的代码中理解发生了什么。基本上所做的是,WallGenerator 已经意识到他们的墙节点应该走多快,而 Wall 节点已经意识到它应该走多快......

编辑:

还有另一种改变墙壁速度的方法,即使用键运行移动动作。然后,在生成的那一刻,根据 tapCounter 的值,你可以通过按键访问一个移动的动作,并直接改变动作的速度属性......这可能是一种更短的方式,但仍然需要一些改变(在里面传递一个持续时间参数Wall 类和在场景中实现 tapCounter)。

【讨论】:

【参考方案2】:

尝试这样做:

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


截至我在您的问题下方阅读 cmets 时,您提出了一个非常不清楚的问题,但是您的代码中存在思想上的问题。

如果我理解一切正确,您的touchesBegan 方法已在墙上实现,因此它对新生成的墙没有影响。您必须将该逻辑移动到场景中,然后以速度作为参数生成新墙,或者至少将count 设为类变量,这样每面墙都可以访问它,但您仍然必须处理场景中的触摸,因为现在触摸是在用户直接点击墙壁时处理的。

【讨论】:

这行不通...所有动作都在协同工作。我需要它首先每 1 秒运行一次,然后每 0.5 秒运行一次 我提供的代码允许您的实例每秒移动一次kDefaultXToMovePerSecond,直到计数等于或大于10,然后它将每半秒移动一次kDefaultXToMovePerSecond。这是一种期望的行为吗? @s1ddok 她正在尝试改变移动墙壁的速度,但是有一个 WallGenerator 类可以生成预定大小的墙壁。并且由于 Wall 节点不知道屏幕上的触摸次数,它应该以所需的速度进行初始化。 GitHub上有一个项目叫Nimble Ninja……你可以下载下来自己看看我在说什么…… 我的意思是:“WallGenerator 类以预定速度生成墙”(不是大小:) 好吧,我不是在研究别人的项目,我只是想帮助 OP 理解,他的设计是错误的。

以上是关于如何使用 count-Swift SpriteKit 更改运动的持续时间?的主要内容,如果未能解决你的问题,请参考以下文章

带有 Skview 的 ViewController - SpriteKit SKScene

在 SpriteKit 项目中包含一个 UIKit 小游戏

[精选] Mysql分表与分库如何拆分,如何设计,如何使用

如果加入条件,我该如何解决。如果使用字符串连接,我如何使用

如何使用本机反应创建登录以及如何验证会话

如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]