如何使用 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 更改运动的持续时间?的主要内容,如果未能解决你的问题,请参考以下文章