我正在制作一个游戏,其中随机物体落入随机位置,并且有一个固定y轴的球并且沿着x轴保持移动,并且它必须移动投掷物体,我试图计算分数和我这样做的方式是我创建了一个物理对象,它与球在同一个y轴上,当对象碰撞时,应该调用分数函数并将分数增加1,但由于某种原因该应用程序不断崩溃,它给了我这个错误。
2015-07-13 01:23:17.242 WalkRun[26792:3773366] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attemped to add a SKNode which already has a parent: <SKSpriteNode> name:'(null)' texture:[<SKTexture> 'shortwall' (60 x 60)] position:{30, 768} size:{60, 60} rotation:0.00'
*** First throw call stack:
(
0 CoreFoundation 0x00000001073c33f5 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x00000001092eabb7 objc_exception_throw + 45
2 CoreFoundation 0x00000001073c332d +[NSException raise:format:] + 205
3 SpriteKit 0x0000000107ebfaf6 -[SKNode addChild:] + 111
4 WalkRun 0x00000001071c8c44 _TFC7WalkRun9PlayScene10leftObjectfS0_FT_T_ + 2868
5 WalkRun 0x00000001071c7ddc _TFC7WalkRun9PlayScene10randObjectfS0_FT_T_ + 236
6 WalkRun 0x00000001071c8102 _TToFC7WalkRun9PlayScene10randObjectfS0_FT_T_ + 34
7 Foundation 0x0000000107a39fd4 __NSFireTimer + 83
8 CoreFoundation 0x000000010732b4e4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
9 CoreFoundation 0x000000010732b0a5 __CFRunLoopDoTimer + 1045
10 CoreFoundation 0x00000001072ee3dd __CFRunLoopRun + 1901
11 CoreFoundation 0x00000001072eda06 CFRunLoopRunSpecific + 470
12 GraphicsServices 0x000000010e7569f0 GSEventRunModal + 161
13 UIKit 0x0000000108046550 UIApplicationMain + 1282
14 WalkRun 0x00000001071d54ce top_level_code + 78
15 WalkRun 0x00000001071d550a main + 42
16 libdyld.dylib 0x0000000109ad9145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
这是我的代码:
//
// PlayScene.swift
// WalkRun
//
// Created by naeim on 7/10/15.
// Copyright (c) 2015 naeim. All rights reserved.
//
import Foundation
import SpriteKit
class PlayScene: SKScene, SKPhysicsContactDelegate{
var ball = SKSpriteNode(imageNamed: "ball")
var wall = SKNode()
var wallRight = SKNode()
var wallMiddle = SKNode()
var ballSpeed = CGFloat()
var bigWall = SKSpriteNode(imageNamed: "shortwall")
var tallWall = SKSpriteNode(imageNamed: "tallwall")
var ballGroup:UInt32 = 1
var objectGroup:UInt32 = 2
var gapGroup:UInt32 = 3
var gameOver = 0
var movingObjects = SKNode()
var score = 0
var scoreLabel = SKLabelNode()
override func didMoveToView(view: SKView) {
self.physicsWorld.contactDelegate = self
backgroundColor = UIColor(hex: 0x80d9ff)
self.physicsWorld.gravity = CGVectorMake(-9,0)
self.addChild(movingObjects)
//creating the ball
ball.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMinY(self.frame) + self.ball.size.height * 2)
ball.physicsBody = SKPhysicsBody(circleOfRadius: self.ball.size.width / 2)
ball.zPosition = 10
//let the ball rotate forever
ballSpeed = 3
let rotateAction = SKAction.rotateByAngle(ballSpeed, duration: 1)
let repeatAction = SKAction.repeatActionForever(rotateAction)
ball.runAction(repeatAction)
ball.physicsBody?.categoryBitMask = ballGroup
ball.physicsBody?.collisionBitMask = objectGroup
ball.physicsBody?.contactTestBitMask = objectGroup
self.addChild(ball)
//creating the wall of the left
wall.position = CGPointMake(CGRectGetMinX(self.frame),CGRectGetMinY(self.frame))
wall.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(2, self.frame.size.height * 2.0))
wall.physicsBody?.dynamic = false
wall.physicsBody?.categoryBitMask = objectGroup
self.addChild(wall)
//creating the wall of the right
wallRight.position = CGPointMake(CGRectGetMaxX(self.frame), CGRectGetMinY(self.frame))
wallRight.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(2, self.frame.size.height * 2.0))
wallRight.physicsBody?.dynamic = false
wallRight.physicsBody?.categoryBitMask = objectGroup
self.addChild(wallRight)
//creating the middle wall that objects pass by
wallMiddle.position = CGPointMake(CGRectGetMinX(self.frame), CGRectGetMinY(self.frame))
wallMiddle.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.frame.size.width, 1))
wallMiddle.physicsBody?.dynamic = false
wallMiddle.physicsBody?.categoryBitMask = gapGroup
wallMiddle.physicsBody?.collisionBitMask = gapGroup
wallMiddle.physicsBody?.contactTestBitMask = objectGroup
self.addChild(wallMiddle)
//creating the label
scoreLabel.fontName = "Helvetica"
scoreLabel.fontSize = 60
scoreLabel.text = "0"
scoreLabel.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) + 70 )
self.addChild(scoreLabel)
var timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("randObject"), userInfo: nil, repeats: true)
var timerObjects = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("checkObjectPlace"), userInfo: nil, repeats: true)
}
func checkObjectPlace(){
}
//function to randomly choose which object
func randObject(){
if gameOver == 0{
var rand = arc4random_uniform(6)+1
switch(rand){
case 1:
leftObject()
case 2:
middleObject()
case 3:
rightObject()
case 4:
LeftAndMiddleObject()
case 5:
rightAndLeftObject()
case 6:
rightAndMiddleObject()
default:
println("error !! non a number other than 0, 1, 2 has been choosen .")
}
}
}
//function to create the left objects
func leftObject(){
var rand = arc4random_uniform(2) + 1
if rand == 1
{
bigWall.position = CGPointMake(CGRectGetMinX(self.frame) + bigWall.size.width / 2, CGRectGetMaxY(self.frame))
var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
var removeObjects = SKAction.removeFromParent()
var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
bigWall.runAction(moveAndRemoveObjects)
bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
bigWall.physicsBody?.dynamic = false
bigWall.physicsBody?.categoryBitMask = objectGroup
movingObjects.addChild(bigWall)
}
else
{
tallWall.position = CGPointMake(CGRectGetMinX(self.frame) + tallWall.size.width / 2, CGRectGetMaxY(self.frame))
var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
var removeObjects = SKAction.removeFromParent()
var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
tallWall.runAction(moveAndRemoveObjects)
tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
tallWall.physicsBody?.dynamic = false
tallWall.physicsBody?.categoryBitMask = objectGroup
movingObjects.addChild(tallWall)
}
}
//function to create the middle objects
func middleObject(){
var rand = arc4random_uniform(2) + 1
if rand == 1
{
var bigWall = SKSpriteNode(imageNamed: "shortwall")
bigWall.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame))
var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
var removeObjects = SKAction.removeFromParent()
var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
bigWall.runAction(moveAndRemoveObjects)
bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
bigWall.physicsBody?.dynamic = false
bigWall.physicsBody?.categoryBitMask = objectGroup
movingObjects.addChild(bigWall)
}
else
{
var tallWall = SKSpriteNode(imageNamed: "tallwall")
tallWall.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame))
var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
var removeObjects = SKAction.removeFromParent()
var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
tallWall.runAction(moveAndRemoveObjects)
tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
tallWall.physicsBody?.dynamic = false
tallWall.physicsBody?.categoryBitMask = objectGroup
movingObjects.addChild(tallWall)
}
}
//function to create the right objects
func rightObject(){
var rand = arc4random_uniform(2) + 1
if rand == 1
{
var bigWall = SKSpriteNode(imageNamed: "shortwall")
bigWall.position = CGPointMake(CGRectGetMaxX(self.frame) - bigWall.size.width / 2, CGRectGetMaxY(self.frame))
var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
var removeObjects = SKAction.removeFromParent()
var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
bigWall.runAction(moveAndRemoveObjects)
bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
bigWall.physicsBody?.dynamic = false
bigWall.physicsBody?.categoryBitMask = objectGroup
movingObjects.addChild(bigWall)
}
else
{
var tallWall = SKSpriteNode(imageNamed: "tallwall")
tallWall.position = CGPointMake(CGRectGetMaxX(self.frame) - tallWall.size.width / 2, CGRectGetMaxY(self.frame))
var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
var removeObjects = SKAction.removeFromParent()
var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
tallWall.runAction(moveAndRemoveObjects)
tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
tallWall.physicsBody?.dynamic = false
tallWall.physicsBody?.categoryBitMask = objectGroup
movingObjects.addChild(tallWall)
if ball.position.x == tallWall.position.x{
scoreIncrement()
}
}
}
//function to create a right and left object
func rightAndLeftObject(){
var rand = arc4random_uniform(2) + 1
if rand == 1
{
var bigWall = SKSpriteNode(imageNamed: "shortwall")
var tallWall = SKSpriteNode(imageNamed: "tallwall")
tallWall.position = CGPointMake(CGRectGetMinX(self.frame) + tallWall.size.width / 2, CGRectGetMaxY(self.frame))
bigWall.position = CGPointMake(CGRectGetMaxX(self.frame) - bigWall.size.width / 2, CGRectGetMaxY(self.frame))
var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
var removeObjects = SKAction.removeFromParent()
var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
bigWall.runAction(moveAndRemoveObjects)
tallWall.runAction(moveAndRemoveObjects)
tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
tallWall.physicsBody?.dynamic = false
bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
bigWall.physicsBody?.dynamic = false
bigWall.physicsBody?.categoryBitMask = objectGroup
tallWall.physicsBody?.categoryBitMask = objectGroup
movingObjects.addChild(tallWall)
movingObjects.addChild(bigWall)
bigWall.position = CGPointMake(CGRectGetMaxX(self.frame) - bigWall.size.width / 2, CGRectGetMaxY(self.frame))
}
else
{
var bigWall = SKSpriteNode(imageNamed: "shortwall")
var tallWall = SKSpriteNode(imageNamed: "tallwall")
bigWall.position = CGPointMake(CGRectGetMaxX(self.frame) - bigWall.size.width / 2, CGRectGetMaxY(self.frame))
tallWall.position = CGPointMake(CGRectGetMaxX(self.frame) - tallWall.size.width / 2, CGRectGetMaxY(self.frame))
var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
var removeObjects = SKAction.removeFromParent()
var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
tallWall.physicsBody?.dynamic = false
bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
bigWall.physicsBody?.dynamic = false
tallWall.runAction(moveAndRemoveObjects)
bigWall.runAction(moveAndRemoveObjects)
bigWall.physicsBody?.categoryBitMask = objectGroup
tallWall.physicsBody?.categoryBitMask = objectGroup
movingObjects.addChild(tallWall)
movingObjects.addChild(bigWall)
}
}
func rightAndMiddleObject(){
var rand = arc4random_uniform(2) + 1
if rand == 1
{
var bigWall = SKSpriteNode(imageNamed: "shortwall")
var tallWall = SKSpriteNode(imageNamed: "tallwall")
tallWall.position = CGPointMake(CGRectGetMaxX(self.frame) - tallWall.size.width / 2, CGRectGetMaxY(self.frame))
bigWall.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame))
var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
var removeObjects = SKAction.removeFromParent()
var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
tallWall.runAction(moveAndRemoveObjects)
bigWall.runAction(moveAndRemoveObjects)
tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
tallWall.physicsBody?.dynamic = false
bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
bigWall.physicsBody?.dynamic = false
bigWall.physicsBody?.categoryBitMask = objectGroup
tallWall.physicsBody?.categoryBitMask = objectGroup
movingObjects.addChild(tallWall)
movingObjects.addChild(bigWall)
}
else
{
var bigWall = SKSpriteNode(imageNamed: "shortwall")
var tallWall = SKSpriteNode(imageNamed: "tallwall")
bigWall.position = CGPointMake(CGRectGetMidX(self.frame) , CGRectGetMaxY(self.frame))
tallWall.position = CGPointMake(CGRectGetMaxX(self.frame) - tallWall.size.width / 2, CGRectGetMaxY(self.frame))
var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
var removeObjects = SKAction.removeFromParent()
var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
tallWall.runAction(moveAndRemoveObjects)
bigWall.runAction(moveAndRemoveObjects)
tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
tallWall.physicsBody?.dynamic = false
bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
bigWall.physicsBody?.dynamic = false
bigWall.physicsBody?.categoryBitMask = objectGroup
tallWall.physicsBody?.categoryBitMask = objectGroup
movingObjects.addChild(tallWall)
movingObjects.addChild(bigWall)
}
}
func LeftAndMiddleObject(){
var rand = arc4random_uniform(2) + 1
if rand == 1
{
var bigWall = SKSpriteNode(imageNamed: "shortwall")
var tallWall = SKSpriteNode(imageNamed: "tallwall")
tallWall.position = CGPointMake(CGRectGetMinX(self.frame) + tallWall.size.width / 2, CGRectGetMaxY(self.frame))
bigWall.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame))
var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
var removeObjects = SKAction.removeFromParent()
var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
tallWall.runAction(moveAndRemoveObjects)
bigWall.runAction(moveAndRemoveObjects)
tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
tallWall.physicsBody?.dynamic = false
bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
bigWall.physicsBody?.dynamic = false
bigWall.physicsBody?.categoryBitMask = objectGroup
tallWall.physicsBody?.categoryBitMask = objectGroup
movingObjects.addChild(tallWall)
movingObjects.addChild(bigWall)
}
else
{
var bigWall = SKSpriteNode(imageNamed: "shortwall")
var tallWall = SKSpriteNode(imageNamed: "tallwall")
bigWall.position = CGPointMake(CGRectGetMidX(self.frame) , CGRectGetMaxY(self.frame))
tallWall.position = CGPointMake(CGRectGetMinX(self.frame) + tallWall.size.width / 2, CGRectGetMaxY(self.frame))
var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
var removeObjects = SKAction.removeFromParent()
var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
tallWall.runAction(moveAndRemoveObjects)
bigWall.runAction(moveAndRemoveObjects)
tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: tallWall.size)
tallWall.physicsBody?.dynamic = false
bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: bigWall.size)
bigWall.physicsBody?.dynamic = false
bigWall.physicsBody?.categoryBitMask = objectGroup
tallWall.physicsBody?.categoryBitMask = objectGroup
movingObjects.addChild(tallWall)
movingObjects.addChild(bigWall)
}
}
func scoreIncrement(){
score = score + 1
scoreLabel.text = "\(score)"
}
func didBeginContact(contact: SKPhysicsContact) {
println("contact")
if contact.bodyA.categoryBitMask == gapGroup || contact.bodyB.categoryBitMask == gapGroup {
println("gap contact")
} else {
gameOver = 1
movingObjects.speed = 0
}
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
if gameOver == 0 {
ball.physicsBody?.velocity = CGVectorMake(0, 0)
ball.physicsBody?.applyImpulse(CGVectorMake(70,0))
}
}
override func update(currentTime: NSTimeInterval) {
}
}
答案 0 :(得分:0)
该错误表明您正在尝试将子节点添加到已有父节点的节点。堆栈跟踪指向leftObject方法。在这里,您有一个SKAction设置,可以在一段时间内移动,然后从父项中删除。
var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
var removeObjects = SKAction.removeFromParent()
var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
bigWall.runAction(moveAndRemoveObjects)
这会将操作添加到节点并运行,但您的代码路径将继续下去
movingObjects.addChild(bigWall)
几乎立刻。看起来像竞争条件,您认为代码将等到操作完成后再继续运行。
答案 1 :(得分:0)
您有一个名为bigWall的实例属性,在大多数方法中,您创建一个名为bigWall的本地对象并将其添加到场景中。因为每次调用方法时它都是一个新对象,所以它工作正常。但是在方法leftObject中,您没有本地对象bigWall,因此它引用了实例属性。第一次调用leftObject时,可以将实例属性bigWall添加到场景中。第二次调用方法时,它会尝试将bigWall实例属性添加到场景中,当场景已经存在于场景中时,您将获得错误。