我正在尝试编写一段代码,使用计时器,每秒从三个位置中的一个位置从视图顶部“放下”一个球。当第一个球被释放时,它会工作,但是,在计时器再次调用该函数后,代码崩溃,因为它表示该节点无法再次添加到视图中。
有人可以向我解释一下这项工作的方法吗?
import SpriteKit
class GameScene: SKScene {
//Creates the three circles
let circleOne = SKSpriteNode(imageNamed: "Circle")
let circleTwo = SKSpriteNode(imageNamed: "Circle")
let circleThree = SKSpriteNode(imageNamed: "Circle")
//Creates dropping ball
let droppingBall = SKSpriteNode(imageNamed: "Circle")
//Creates variables to play game
var gameStarted = false
var gameOver = false
var timeInterval = 1.0
var droppingBallXPosition = 0
var livesLeft = 3
//Creates timer for the balls
var ballTimer = NSTimer()
override func didMoveToView(view: SKView) {
/* Setup your scene here */
//Set background colour
backgroundColor = UIColor.whiteColor()
//Assigns position to circles
circleOne.position = CGPoint(x: (self.frame.width / 2) - 80, y: self.frame.height / 2)
circleTwo.position = CGPoint(x: (self.frame.width / 2), y: self.frame.height / 2)
circleThree.position = CGPoint(x: (self.frame.width / 2) + 80, y: self.frame.height / 2)
//Assigns size to circles
circleOne.size = CGSize(width: 35, height: 35)
circleTwo.size = CGSize(width: 350, height: 350)
circleThree.size = CGSize(width: 35, height: 35)
//Set colour to circles
circleOne.color = UIColor.lightGrayColor()
circleOne.colorBlendFactor = 1.0
circleTwo.color = UIColor.lightGrayColor()
circleTwo.colorBlendFactor = 1.0
circleThree.color = UIColor.lightGrayColor()
circleThree.colorBlendFactor = 1.0
//Add circles to view
self.addChild(circleOne)
self.addChild(circleTwo)
self.addChild(circleThree)
//set properties for falling ball
droppingBall.position = CGPoint(x: CGFloat(droppingBallXPosition), y: 0)
droppingBall.size = CGSize(width: 25, height: 25)
droppingBall.color = UIColor.redColor()
droppingBall.colorBlendFactor = 1.0
droppingBall.physicsBody = SKPhysicsBody(circleOfRadius: 25)
droppingBall.physicsBody?.dynamic = false
droppingBall.physicsBody?.affectedByGravity = false
}
func releaseBall(){
var whichColumn = arc4random() % 3
switch whichColumn {
case 0:
droppingBall.position = CGPoint(x: (self.frame.width / 2) - 80, y: self.frame.height)
droppingBall.physicsBody?.dynamic = true
droppingBall.physicsBody?.affectedByGravity = true
droppingBall.physicsBody?.friction = 1.0
self.addChild(droppingBall)
break
case 1:
droppingBall.position = CGPoint(x: (self.frame.width / 2), y: self.frame.height)
droppingBall.physicsBody?.dynamic = true
droppingBall.physicsBody?.affectedByGravity = true
droppingBall.physicsBody?.friction = 1.0
self.addChild(droppingBall)
break
case 2:
droppingBall.position = CGPoint(x: (self.frame.width / 2) + 80, y: self.frame.height)
droppingBall.physicsBody?.dynamic = true
droppingBall.physicsBody?.affectedByGravity = true
droppingBall.physicsBody?.friction = 1.0
self.addChild(droppingBall)
break
default:
break
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
if gameStarted == false {
let zoomOut = SKAction.scaleTo(0.1, duration: 0.2)
circleTwo.runAction(zoomOut)
gameStarted = true
}
else if gameStarted == true && gameOver == false {
//check to see if the game is over
if livesLeft > 0 {
//Continue game
ballTimer = NSTimer.scheduledTimerWithTimeInterval(timeInterval, target: self, selector: #selector(GameScene.releaseBall), userInfo: nil, repeats: true)
}
else {
//The player has lost
gameOver = true
gameStarted = false
}
}
else if gameStarted == true && gameOver == true {
//The player has lost
gameOver = true
gameStarted = false
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
错误:
尝试添加已有父级的SKNode
答案 0 :(得分:0)
每次添加另一个球时,您都可以创建一个复制球来添加到场景中。这将是一个替代解决方案,而不是一个正确的答案,因为正确地做这将涉及为球创建一个类。这样,您需要做的就是在每个开关案例中创建一个新的sprite,如下所示:
let ballCopy = droppingBall.copy() as! SKSpritenode
然后,您只需更改其位置(因为使用copy
将有关正在复制的节点的所有内容复制到交换机案例所指的位置)。总而言之,它看起来应该是这样的:
func releaseBall(){
var whichColumn = arc4random() % 3
droppingBall.physicsBody?.dynamic = true
droppingBall.physicsBody?.affectedByGravity = true
droppingBall.physicsBody?.friction = 1.0
switch whichColumn {
case 0:
let ballCopy1 = droppingBall.copy() as! SKSpritenode
ballCopy1.position = CGPoint(x: (self.frame.width / 2) - 80, y: self.frame.height)
self.addChild(ballCopy1)
break
case 1:
let ballCopy2 = droppingBall.copy() as! SKSpritenode
ballCopy2.position = CGPoint(x: (self.frame.width / 2), y: self.frame.height)
self.addChild(ballCopy2)
break
case 2:
let ballCopy3 = droppingBall.copy() as! SKSpritenode
ballCopy3.position = CGPoint(x: (self.frame.width / 2) + 80, y: self.frame.height)
self.addChild(ballCopy3)
break
default:
break
}
}
答案 1 :(得分:0)
屏幕上只有一个球吗?如果是这样,你可以改变你的功能:
func releaseBall(){
self.droppingball.removefromparent()
var whichColumn = arc4random() % 3
switch whichColumn {
case 0:
droppingBall.position = CGPoint(x: (self.frame.width / 2) - 80, y: self.frame.height)
droppingBall.physicsBody?.dynamic = true
droppingBall.physicsBody?.affectedByGravity = true
droppingBall.physicsBody?.friction = 1.0
self.addChild(droppingBall)
break
case 1:
droppingBall.position = CGPoint(x: (self.frame.width / 2), y: self.frame.height)
droppingBall.physicsBody?.dynamic = true
droppingBall.physicsBody?.affectedByGravity = true
droppingBall.physicsBody?.friction = 1.0
self.addChild(droppingBall)
break
case 2:
droppingBall.position = CGPoint(x: (self.frame.width / 2) + 80, y: self.frame.height)
droppingBall.physicsBody?.dynamic = true
droppingBall.physicsBody?.affectedByGravity = true
droppingBall.physicsBody?.friction = 1.0
self.addChild(droppingBall)
break
default:
break
}
}
这应该允许您多次运行该功能。 如果系统需要多个球。您可以创建第二个精灵节点和第二个func来释放球并将计时器设置为在不同日期开始。
像这样:
var droppingball = SKSpriteNode(imageNamed: "Circle")
var droppingball0 = SKSpriteNode(imageNamed: "Circle")
func releaseBall(){
self.droppingball.removefromparent()
var whichColumn = arc4random() % 3
switch whichColumn {
case 0:
droppingBall.position = CGPoint(x: (self.frame.width / 2) - 80, y: self.frame.height)
droppingBall.physicsBody?.dynamic = true
droppingBall.physicsBody?.affectedByGravity = true
droppingBall.physicsBody?.friction = 1.0
self.addChild(droppingBall)
break
case 1:
droppingBall.position = CGPoint(x: (self.frame.width / 2), y: self.frame.height)
droppingBall.physicsBody?.dynamic = true
droppingBall.physicsBody?.affectedByGravity = true
droppingBall.physicsBody?.friction = 1.0
self.addChild(droppingBall)
break
case 2:
droppingBall.position = CGPoint(x: (self.frame.width / 2) + 80, y: self.frame.height)
droppingBall.physicsBody?.dynamic = true
droppingBall.physicsBody?.affectedByGravity = true
droppingBall.physicsBody?.friction = 1.0
self.addChild(droppingBall)
break
default:
break
}
}
func releaseBall0(){
self.droppingball.removefromparent()
var whichColumn = arc4random() % 3
switch whichColumn {
case 0:
droppingBall.position = CGPoint(x: (self.frame.width / 2) - 80, y: self.frame.height)
droppingBall0.physicsBody?.dynamic = true
droppingBall0.physicsBody?.affectedByGravity = true
droppingBall0.physicsBody?.friction = 1.0
self.addChild(droppingBall)
break
case 1:
droppingBall0.position = CGPoint(x: (self.frame.width / 2), y: self.frame.height)
droppingBall0.physicsBody?.dynamic = true
droppingBall0.physicsBody?.affectedByGravity = true
droppingBall0.physicsBody?.friction = 1.0
self.addChild(droppingBall0)
break
case 2:
droppingBall0.position = CGPoint(x: (self.frame.width / 2) + 80, y: self.frame.height)
droppingBall0.physicsBody?.dynamic = true
droppingBall0.physicsBody?.affectedByGravity = true
droppingBall0.physicsBody?.friction = 1.0
self.addChild(droppingBall0)
break
default:
break
}
} 然后,您需要做的就是找出您想要调用此函数的间隔,并将两个定时器添加到该间隔的两倍。例如,如果我想每秒发射一次,你会创建两个定时器间隔为2秒的定时器,并告诉一个定时器在第一个定时器之后开始1秒,然后将其装入:
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(1 * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(),
{
// your timer
})
答案 2 :(得分:0)
您收到错误的原因是因为Node已经添加到场景中,您只能添加一次。您需要创建一个新的SKSpriteNode实例,然后在每次想要另一个球时将其添加到场景中。您可能希望为球创建自定义类并将其存储在列表中,以便在需要时识别每个类。