class AppDelegate: UIResponder, UIApplicationDelegate {
Ошибка в предыдущей строке кода. Я думаю, что ошибка связана со следующим кодом в моем GameScene.swift. Я набрал следующий код для своей игровой логики c.
В игре четыре треугольника составляют квадрат. Один из четырех узлов падает с верхней части экрана, и, если он попадает на правильную сторону квадрата (вы можете повернуть квадрат, щелкнув по экрану), другой узел вновь появляется. Следующий код не работает правильно, и я получаю сообщение об ошибке Thread 1: сигнал SIGABRT.
import SpriteKit
class GameScene: SKScene {
let basicTop = SKSpriteNode(imageNamed: "basic top");
let basicBottom = SKSpriteNode(imageNamed: "basic bottom");
let basicLeft = SKSpriteNode(imageNamed: "basic left");
let basicRight = SKSpriteNode(imageNamed: "basic right");
let brickTop = SKSpriteNode(imageNamed: "Top Side");
let brickBottom = SKSpriteNode(imageNamed: "Bottom Side");
let brickLeft = SKSpriteNode(imageNamed: "Left Side");
let brickRight = SKSpriteNode(imageNamed: "Right Side copy 2");
override func didMove(to view: SKView) {
isUserInteractionEnabled = true
layoutScene()
}
func layoutScene() {
backgroundColor = UIColor(red: 10/255, green: 75/255, blue: 150/255, alpha: 1.0)
spawnBrick()
spawnBasicTop()
spawnBasicBottom()
spawnBasicLeft()
spawnBasicRight()
backgroundScene()
setupPhysics()
}
func setupPhysics() {
physicsWorld.gravity = CGVector(dx: 0.0, dy: -0.1)
physicsWorld.contactDelegate = self
}
func spawnBrick() {
let randomFunc = [self.spawnbrickTop, self.spawnbrickBottom, self.spawnbrickLeft, self.spawnbrickRight]
let randomResult = Int(arc4random_uniform(UInt32(randomFunc.count)))
randomFunc[randomResult]()
}
func spawnbrickTop() {
brickTop.size = CGSize(width: 224, height: 93)
brickTop.name = "BrickTop"
brickTop.position = CGPoint(x: frame.midX, y: frame.maxY)
brickTop.zPosition = 0
//physics stuff begins here
brickTop.physicsBody = SKPhysicsBody(rectangleOf: brickTop.size)
brickTop.physicsBody?.categoryBitMask = PhysicsCategories.brickTopCategory
brickTop.physicsBody?.contactTestBitMask = PhysicsCategories.basicTopCategory
brickTop.physicsBody?.contactTestBitMask = PhysicsCategories.basicBottomCategory
brickTop.physicsBody?.contactTestBitMask = PhysicsCategories.basicLeftCategory
brickTop.physicsBody?.contactTestBitMask = PhysicsCategories.basicRightCategory
brickTop.physicsBody?.collisionBitMask = PhysicsCategories.none
//bye bye physics
self.addChild(brickTop)
}
func spawnbrickBottom() {
brickBottom.size = CGSize(width: 230, height: 101)
brickBottom.name = "BrickBottom"
brickBottom.position = CGPoint(x: frame.midX, y: frame.maxY)
brickBottom.zPosition = 0
//physics stuff begins here
brickBottom.physicsBody = SKPhysicsBody(rectangleOf: brickBottom.size)
brickBottom.physicsBody?.categoryBitMask = PhysicsCategories.brickBottomCategory
brickBottom.physicsBody?.contactTestBitMask = PhysicsCategories.basicTopCategory
brickBottom.physicsBody?.contactTestBitMask = PhysicsCategories.basicBottomCategory
brickBottom.physicsBody?.contactTestBitMask = PhysicsCategories.basicLeftCategory
brickBottom.physicsBody?.contactTestBitMask = PhysicsCategories.basicRightCategory
brickBottom.physicsBody?.collisionBitMask = PhysicsCategories.none
//bye bye physics
self.addChild(brickBottom)
}
func spawnbrickLeft() {
brickLeft.size = CGSize(width: 210, height: 70)
brickLeft.name = "BrickLeft"
brickLeft.position = CGPoint(x: frame.midX, y: frame.maxY)
brickLeft.zPosition = 0
//physics stuff begins here
brickLeft.physicsBody = SKPhysicsBody(rectangleOf: brickLeft.size)
brickLeft.physicsBody?.categoryBitMask = PhysicsCategories.brickLeftCategory
brickLeft.physicsBody?.contactTestBitMask = PhysicsCategories.basicTopCategory
brickLeft.physicsBody?.contactTestBitMask = PhysicsCategories.basicBottomCategory
brickLeft.physicsBody?.contactTestBitMask = PhysicsCategories.basicLeftCategory
brickLeft.physicsBody?.contactTestBitMask = PhysicsCategories.basicRightCategory
brickLeft.physicsBody?.collisionBitMask = PhysicsCategories.none
//bye bye physics
self.addChild(brickLeft)
}
func spawnbrickRight() {
brickRight.size = CGSize(width: 190, height: 84)
brickRight.name = "BrickRight"
brickRight.position = CGPoint(x: frame.midX, y: frame.maxY)
brickRight.zPosition = 0
//physics stuff begins here
brickRight.physicsBody = SKPhysicsBody(rectangleOf: brickRight.size)
brickRight.physicsBody?.categoryBitMask = PhysicsCategories.brickRightCategory
brickRight.physicsBody?.contactTestBitMask = PhysicsCategories.basicTopCategory
brickRight.physicsBody?.contactTestBitMask = PhysicsCategories.basicBottomCategory
brickRight.physicsBody?.contactTestBitMask = PhysicsCategories.basicLeftCategory
brickRight.physicsBody?.contactTestBitMask = PhysicsCategories.basicRightCategory
brickRight.physicsBody?.collisionBitMask = PhysicsCategories.none
//bye bye physics
self.addChild(brickRight)
}
func turnBasicTop() {
basicTop.run(SKAction.rotate(byAngle: .pi/2, duration: 0.25))
}
func turnBasicBottom() {
basicBottom.run(SKAction.rotate(byAngle: .pi/2, duration: 0.25))
}
func turnBasicLeft() {
basicLeft.run(SKAction.rotate(byAngle: .pi/2, duration: 0.25))
}
func turnBasicRight() {
basicRight.run(SKAction.rotate(byAngle: .pi/2, duration: 0.25))
}
func gameOver() {
print("Game Over!")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
turnBasicTop()
turnBasicBottom()
turnBasicLeft()
turnBasicRight()
}
func spawnBasicTop() {
basicTop.size = CGSize(width: 400, height: 400)
basicTop.position = CGPoint(x: 230, y: 200)
basicTop.zPosition = 1
//physics stuff begins here
basicTop.physicsBody = SKPhysicsBody(rectangleOf: basicTop.size)
basicTop.physicsBody?.categoryBitMask = PhysicsCategories.basicTopCategory
basicTop.physicsBody?.isDynamic = false
basicTop.physicsBody?.allowsRotation = true
//bye bye physics
addChild(basicTop)
}
func spawnBasicBottom() {
basicBottom.size = CGSize(width: 400, height: 400)
basicBottom.position = CGPoint(x: 230, y: 200)
basicBottom.zPosition = 1
//physics stuff begins here
basicBottom.physicsBody = SKPhysicsBody(rectangleOf: basicBottom.size)
basicBottom.physicsBody?.categoryBitMask = PhysicsCategories.basicBottomCategory
basicBottom.physicsBody?.isDynamic = false
//bye bye physics
addChild(basicBottom)
}
func spawnBasicLeft() {
basicLeft.size = CGSize(width: 400, height: 400)
basicLeft.position = CGPoint(x: 230, y: 200)
basicLeft.zPosition = 1
//physics stuff begins here
basicLeft.physicsBody = SKPhysicsBody(rectangleOf: basicLeft.size)
basicLeft.physicsBody?.categoryBitMask = PhysicsCategories.basicLeftCategory
basicLeft.physicsBody?.isDynamic = false
//bye bye physics
addChild(basicLeft)
}
func spawnBasicRight() {
basicRight.size = CGSize(width: 400, height: 400)
basicRight.position = CGPoint(x: 230, y: 200)
basicRight.zPosition = 1
//physics stuff begins here
basicRight.physicsBody = SKPhysicsBody(rectangleOf: basicRight.size)
basicRight.physicsBody?.categoryBitMask = PhysicsCategories.basicRightCategory
basicRight.physicsBody?.isDynamic = false
//bye bye physics
addChild(basicRight)
}
func backgroundScene() {
let constructionSite = SKSpriteNode(imageNamed: "Background Image")
constructionSite.size = frame.size
constructionSite.position = CGPoint(x: frame.midX, y: frame.midY)
constructionSite.zPosition = -1
addChild(constructionSite)
}
}
extension GameScene: SKPhysicsContactDelegate {
func didBegin(_ contact: SKPhysicsContact) {
//01
//10
//11
let contactMask = contact.bodyA.categoryBitMask |
contact.bodyB.categoryBitMask
if contactMask == PhysicsCategories.brickTopCategory |
(PhysicsCategories.basicTopCategory) {
if let brickTop = contact.bodyA.node?.name == "BrickTop" ?
contact.bodyA.node as? SKSpriteNode : contact.bodyB.node as?
SKSpriteNode {
if brickTop == basicTop {
print("Correct!")
brickTop.run(SKAction.fadeOut(withDuration: 0.15), completion: {
brickTop.removeFromParent()
self.spawnBrick()
})
}
else if contactMask == PhysicsCategories.brickBottomCategory |
(PhysicsCategories.basicBottomCategory) {
if let brickBottom = contact.bodyA.node?.name == "BrickBottom" ?
contact.bodyA.node as? SKSpriteNode : contact.bodyB.node as?
SKSpriteNode {
if brickBottom == basicBottom {
print("Correct!")
brickBottom.run(SKAction.fadeOut(withDuration: 0.15), completion: {
brickBottom.removeFromParent()
self.spawnBrick()
})
}
else if contactMask == PhysicsCategories.brickLeftCategory |
(PhysicsCategories.basicBottomCategory) {
if let brickLeft = contact.bodyA.node?.name == "BrickLeft" ?
contact.bodyA.node as? SKSpriteNode : contact.bodyB.node as?
SKSpriteNode {
if brickLeft == basicLeft {
print("Correct!")
brickLeft.run(SKAction.fadeOut(withDuration: 0.15), completion: {
brickLeft.removeFromParent()
self.spawnBrick()
})
}
else if contactMask == PhysicsCategories.brickRightCategory |
(PhysicsCategories.basicRightCategory) {
if let brickRight = contact.bodyA.node?.name == "BrickRight" ?
contact.bodyA.node as? SKSpriteNode : contact.bodyB.node as?
SKSpriteNode {
if brickRight == basicRight {
print("Correct!")
brickRight.run(SKAction.fadeOut(withDuration: 0.15), completion: {
brickRight.removeFromParent()
self.spawnBrick()
})
}
else {
gameOver()
}
}
}
}
}
}
}
}
}
}
}
В случае ошибки выводится следующее сообщение:
*** Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: 'Attemped to add a SKNode which already
has a parent: <SKSpriteNode> name:'BrickLeft' texture:[<SKTexture> 'Left
Side' (254 x 165)] position:{207, 896} scale:{1.00, 1.00} size:{210, 70}
anchor:{0.5, 0.5} rotation:0.00'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff23c7127e __exceptionPreprocess + 350
1 libobjc.A.dylib 0x00007fff513fbb20 objc_exception_throw + 48
2 CoreFoundation 0x00007fff23c710bc +[NSException raise:format:] + 188
3 SpriteKit 0x00007fff2be8cba1 -[SKNode insertChild:atIndex:] + 157
4 SpriteKit 0x00007fff2be8cae1 -[SKNode addChild:] + 68
5 Brick Switch 0x000000010ee913b0 $s12Brick_Switch9GameSceneC14spawnbrickLeftyyF + 2816
6 Brick Switch 0x000000010ee97e7c $sTA.40 + 28
7 Brick Switch 0x000000010ee8ebcc $sIeg_ytIegr_TR + 12
8 Brick Switch 0x000000010ee8edc1 $sIeg_ytIegr_TRTA.8 + 17
9 Brick Switch 0x000000010ee8eaad $s12Brick_Switch9GameSceneC05spawnA0yyF + 781
10 Brick Switch 0x000000010ee96ba5 $s12Brick_Switch9GameSceneC8didBeginyySo16SKPhysicsContactCFyycfU2_ + 85
11 Brick Switch 0x000000010ee96a7d $sIeg_IeyB_TR + 45
12 SpriteKit 0x00007fff2be2483e _ZN9SKCAction25didFinishWithTargetAtTimeEP7SKCNoded + 44
13 SpriteKit 0x00007fff2be26090 _ZN7SKCFade27cpp_updateWithTargetForTimeEP7SKCNoded + 184
14 SpriteKit 0x00007fff2be3a49b _ZN7SKCNode6updateEdf + 221
15 SpriteKit 0x00007fff2be3a560 _ZN7SKCNode6updateEdf + 418
16 SpriteKit 0x00007fff2be51e2b -[SKScene _update:] + 613
17 SpriteKit 0x00007fff2be726c9 -[SKView _update:] + 953
18 SpriteKit 0x00007fff2be6ed91 __51-[SKView _vsyncRenderForTime:preRender:postRender:]_block_invoke.323 + 281
19 SpriteKit 0x00007fff2be6e180 -[SKView _vsyncRenderForTime:preRender:postRender:] + 527
20 SpriteKit 0x00007fff2be6fdb8 __29-[SKView setUpRenderCallback]_block_invoke + 203
21 SpriteKit 0x00007fff2beb3992 -[SKDisplayLink _callbackForNextFrame:] + 301
22 QuartzCore 0x00007fff2afeb266 _ZN2CA7Display11DisplayLink14dispatch_itemsEyyy + 640
23 QuartzCore 0x00007fff2b0c3e03 _ZL22display_timer_callbackP12__CFMachPortPvlS1_ + 299
24 CoreFoundation 0x00007fff23b9503d __CFMachPortPerform + 157
25 CoreFoundation 0x00007fff23bd4bc9 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
26 CoreFoundation 0x00007fff23bd4228 __CFRunLoopDoSource1 + 472
27 CoreFoundation 0x00007fff23bced64 __CFRunLoopRun + 2516
28 CoreFoundation 0x00007fff23bce066 CFRunLoopRunSpecific + 438
29 GraphicsServices 0x00007fff384c0bb0 GSEventRunModal + 65
30 UIKitCore 0x00007fff48092d4d UIApplicationMain + 1621
31 Brick Switch 0x000000010ee99e2b main + 75
32 libdyld.dylib 0x00007fff5227ec25 start + 1
33 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
Это файл настроек:
enum PhysicsCategories {
static let none: UInt32 = 0
static let brickCategory: UInt32 = 0x1 << 1//01
static let brickTopCategory: UInt32 = 0x1 << 2//01
static let brickBottomCategory: UInt32 = 0x1 << 3//01
static let brickLeftCategory: UInt32 = 0x1 << 4//01
static let brickRightCategory: UInt32 = 0x1 << 5//01
static let basicTopCategory: UInt32 = 0x1 << 6 //10; shifts all bits to the left
static let basicBottomCategory: UInt32 = 0x1 << 7 //10; shifts all bits to the left
static let basicLeftCategory: UInt32 = 0x1 << 8 //10; shifts all bits to the left
static let basicRightCategory: UInt32 = 0x1 << 9 //10; shifts all bits to the left
}