0

2 つのボディが衝突したときに表示する必要があるrestartButtonがあり、それが初めて発生したときに、すべてがうまくいきます。ボディが衝突します。それは「良い、正しい再起動」でしたそしてここから問題が始まります...

レベルが再起動された後、画面の中央 (restartButton が呼び出されたときに表示される必要がある場所) に触れると、次のように言ってゲームがクラッシュします。

「キャッチされない例外 'NSInvalidArgumentException' が原因でアプリを終了しています。理由: 'すでに親を持つ SKNode を追加しようとしました: 名前:'(null)' 粒子テクスチャ: 'enemyPart.png' (100 x 100) 位置:{721.33929, 175.39999 {{inf, inf}, {inf, inf}}' ** 最初のスロー コール スタック: (0x2a0fa137 など) libc++abi.dylib: タイプ NSException のキャッチされない例外で終了します"

しかし、restartButton は非表示であり、ボディが衝突していないため存在することさえできません。

その「良い再起動」の後、敵がプレイヤーに衝突すると、restartButton が一瞬表示され、プレイヤー、敵 1、敵 2、敵 3 がシーンからフェードアウトします。

誰かが助けてくれれば幸いです

これらすべてを確認できるコードは次のとおりです。

import SpriteKit
import UIKit



let player = SKEmitterNode(fileNamed: "playerPart.sks")
let enemy1 = SKEmitterNode(fileNamed: "ePart.sks")
let enemy2 = SKEmitterNode(fileNamed: "ePart.sks")
let enemy3 = SKEmitterNode(fileNamed: "ePart.sks")
let restartButton = SKSpriteNode(imageNamed: "restartButton")
let playerCat: UInt32 = 0x1 << 0
let enemyCat: UInt32 = 0x1 << 1


class Level2: SKScene, SKPhysicsContactDelegate {

    override func didMoveToView(view: SKView) {

        physicsWorld.contactDelegate = self


        initWorld()
        movements()

        player.physicsBody = SKPhysicsBody(circleOfRadius: 50)
        player.position = CGPointMake(819.2 , 693.8)
        player.zPosition = 1
        player.physicsBody?.categoryBitMask = playerCat
        player.physicsBody?.contactTestBitMask = enemyCat
        player.targetNode = self
        self.addChild(player)

        enemy1.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(102, 102))
        enemy1.position = CGPointMake(819.2, 175.4)
        enemy1.zPosition = 1
        enemy1.physicsBody?.affectedByGravity = false
        enemy1.physicsBody?.dynamic = true
        enemy1.physicsBody?.allowsRotation = false
        enemy1.physicsBody?.categoryBitMask = enemyCat
        enemy1.physicsBody?.contactTestBitMask = playerCat
        enemy1.physicsBody?.collisionBitMask = 0x0
        enemy1.targetNode = self
        enemy1.particleBirthRate = 150
        enemy1.particleLifetime = 10
        enemy1.particleLifetimeRange = 20
        enemy1.particlePositionRange = CGVectorMake(50, 60)
        enemy1.emissionAngle = 0
        enemy1.emissionAngleRange = 0
        enemy1.particleSpeed = 0
        enemy1.particleSpeedRange = 0


        enemy2.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(102, 102))
        enemy2.position = CGPointMake(614.4, 386.6)
        enemy2.zPosition = 1
        enemy2.physicsBody?.affectedByGravity = false
        enemy2.physicsBody?.dynamic = true
        enemy2.physicsBody?.allowsRotation = false
        enemy2.physicsBody?.categoryBitMask = enemyCat
        enemy2.physicsBody?.contactTestBitMask = playerCat
        enemy2.physicsBody?.collisionBitMask = 0x0
        enemy2.targetNode = self
        enemy2.particleBirthRate = 150
        enemy2.particleLifetime = 10
        enemy2.particleLifetimeRange = 20
        enemy2.particlePositionRange = CGVectorMake(50, 60)
        enemy2.emissionAngle = 0
        enemy2.emissionAngleRange = 0
        enemy2.particleSpeed = 0
        enemy2.particleSpeedRange = 0

        enemy3.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(102, 102))
        enemy3.position = CGPointMake(409.6, 181.8)
        enemy3.zPosition = 1
        enemy3.physicsBody?.affectedByGravity = false
        enemy3.physicsBody?.dynamic = true
        enemy3.physicsBody?.allowsRotation = false
        enemy3.physicsBody?.categoryBitMask = enemyCat
        enemy3.physicsBody?.contactTestBitMask = playerCat
        enemy3.physicsBody?.collisionBitMask = 0x0
        enemy3.targetNode = self
        enemy3.particleBirthRate = 150
        enemy3.particleLifetime = 10
        enemy3.particleLifetimeRange = 20
        enemy3.particlePositionRange = CGVectorMake(50, 60)
        enemy3.emissionAngle = 0
        enemy3.emissionAngleRange = 0
        enemy3.particleSpeed = 0
        enemy3.particleSpeedRange = 0


    func initWorld() {

        self.addChild(enemy1)
        self.addChild(enemy2)
        self.addChild(enemy3)

    }


    func movements() {

        let move11 = SKAction.moveTo(CGPointMake(819.2, 386.6), duration: 1.5)
        let move12 = SKAction.moveTo(CGPointMake(614.4, 386.6), duration: 1.5)
        let move13 = SKAction.moveTo(CGPointMake(614.4, 175.4), duration: 1.5)
        let move14 = SKAction.moveTo(CGPointMake(819.2, 175.4), duration: 1.5)
        let enemy1m = SKAction.sequence([move11, move12, move13, move14])
        let enemy1move = SKAction.repeatActionForever(enemy1m)

        let move21 = SKAction.moveTo(CGPointMake(614.4, 591.4), duration: 1.5)
        let move22 = SKAction.moveTo(CGPointMake(409.6, 591.4), duration: 1.5)
        let move23 = SKAction.moveTo(CGPointMake(409.6, 386.6), duration: 1.5)
        let move24 = SKAction.moveTo(CGPointMake(614.4, 386.6), duration: 1.5)
        let enemy2m = SKAction.sequence([move21, move22, move23, move24])
        let enemy2move = SKAction.repeatActionForever(enemy2m)

        let move31 = SKAction.moveTo(CGPointMake(409.6, 386.6), duration: 1.5)
        let move32 = SKAction.moveTo(CGPointMake(204.8, 386.6), duration: 1.5)
        let move33 = SKAction.moveTo(CGPointMake(204.8, 181.8), duration: 1.5)
        let move34 = SKAction.moveTo(CGPointMake(409.6, 181.8), duration: 1.5)
        let enemy3m = SKAction.sequence([move31, move32, move33, move34])
        let enemy3move = SKAction.repeatActionForever(enemy3m)

        enemy1.runAction(enemy1move)
        enemy2.runAction(enemy2move)
        enemy3.runAction(enemy3move)
    }


    func didBeginContact(contact: SKPhysicsContact) {
        let collision:UInt32 = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask)

        if collision == (playerCat | enemyCat) {
            self.removeAllActions()
            self.runAction(SKAction.waitForDuration(0.1), completion: {
                self.runAction(SKAction.waitForDuration(0.2), completion:
                    {self.removeAllActions()
                        self.removeChildrenInArray([enemy1, enemy2, enemy3, player])})

                restartButton.size = CGSizeMake(200, 200)
                restartButton.position = CGPointMake(512, 384)
                restartButton.zPosition = 1
                self.addChild(restartButton)
            })


        }
    }




    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {

        for touch: AnyObject in touches {
            let location = touch.locationInNode(self)

            if (restartButton .containsPoint(location)) {
                restartButton.runAction(fadeAway)
                restartButton.removeFromParent()
                println(1)
                self.runAction(SKAction.waitForDuration(1.5), completion: {
                let repeatLevel = SKTransition.fadeWithDuration(2)
                let level2 = Level2(fileNamed: "Level2")
                self.view?.presentScene(level2, transition:     repeatLevel)


                })
            }

        }
    }

    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */
    }
}
4

2 に答える 2

0

playerCat と energyCat が最初に衝突したときに、restartButton のサイズが初めて設定されますが、これは問題ありません。

restartButton にはサイズがあるためです。タッチが restartButton の境界内にあるかどうかを確認できます。

if (restartButton .containsPoint(location)) {

あなたが行ったように、しかし、restartButtonがシーンに追加されているかどうかを確認することはありません。簡単な修正はおそらく次のとおりです。

if (restartButton.parent != nil && restartButton .containsPoint(location)) {

ノードの境界であるかどうかを特に確認する必要がない場合。代わりにこれを使用して直接確認できます。これにより、親を確認する必要がなくなります。

if (self.nodeAtPoint(location) == restartButton) {

私が気付いたもう1つのことは、衝突検出で、すでに衝突しているかどうかを確認しないことです。そのため、すべてのアクションを削除してから新しいアクションを追加するだけで、同じコードを複数回実行する可能性があります。

冗長性を防ぐために単純な have 変数を追加できます

var detectionMade = false

でリセット

override func didMoveToView(view: SKView) {
    physicsWorld.contactDelegate = self

    initWorld()
    movements()

    detectionMade = false
    ...

最初に衝突してチェックするときに true に設定します

if collision == (playerCat | enemyCat) && !detectionMade {
    detectionMade = true
    ...
于 2015-04-12T00:50:31.183 に答える
0

@martinmeincke やりました!これを行うことによって:

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {

        for touch: AnyObject in touches {
            let location = touch.locationInNode(self)

            if (restartButton .containsPoint(location) && restartButton.parent == nil) {
                restartButton.runAction(fadeAway)

                println(1)



                }
            }

        }


    override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
        for touch: AnyObject in touches {
            let location = touch.locationInNode(self)

            if (restartButton .containsPoint(location)) {
                restartButton.removeFromParent()
                self.runAction(SKAction.waitForDuration(1.5), completion: {
                    let repeatLevel = SKTransition.fadeWithDuration(2)
                    let level2 = Level2(fileNamed: "Level2")
                    self.view?.presentScene(level2, transition: repeatLevel)
            })

        }
    }
    }
于 2015-04-12T13:37:31.530 に答える