如何检测精灵套件游戏中没有碰撞

时间:2017-11-06 04:23:50

标签: ios sprite-kit game-physics skphysicsbody

我正在做一个游戏,你必须使用一个线程悬挂的蜘蛛捕捉糖果,正如我在这个链接中所示:Game screenshot(我是新来的,所以我还不能发布图像) 。我已经从左到右进行了蜘蛛的运动,并且我能够使用SKAction通过'Y'来捕捉糖果,我唯一的问题是我没弄明白但是如何知道蜘蛛是不是' t捕获任何糖果,在他的运动过程中,我尝试在动作完成时使用allContactedBodies函数,但返回的数组的计数始终为零。有什么建议吗?

以下是代码:

class GameScene: SKScene, SKPhysicsContactDelegate {

    private var rope = SKSpriteNode(imageNamed: "rope")
    private var anchor = SKSpriteNode(imageNamed: "anchor")
    private var currentCharacter: SKSpriteNode!
    private var candy: SKSpriteNode!
    var direction : String = "backward"

    var lastCandyAdded: TimeInterval = 0
    let candyVelocity: CGFloat = 4.0

    let characterBitMask  : UInt32 = 0x1 << 1
    let candyBitMask: UInt32 = 0x1 << 2

    let characterVelocity: CGFloat = 18.0
    var direction : String = "backward"

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

        self.addAnchor()
        self.addRope()
        self.addCharacter()

        let jointOneFixed = SKPhysicsJointFixed.joint(withBodyA: anchor.physicsBody!, bodyB: rope.physicsBody!, anchor: anchor.position)
        self.physicsWorld.add(jointOneFixed);

        let jointTwoFixed = SKPhysicsJointFixed.joint(withBodyA: rope.physicsBody!, bodyB: currentCharacter.physicsBody!, anchor: currentCharacter.position)
        self.physicsWorld.add(jointTwoFixed);
    }

    func addAnchor(){
        anchor.position = CGPoint(x: self.size.width / 2, y: self.size.height + 1)
        anchor.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        anchor.setScale(1)
        anchor.zPosition = 2
        anchor.name = "anchor"
        anchor.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: anchor.size.width, height: anchor.size.height))
        anchor.physicsBody?.affectedByGravity = false
        anchor.physicsBody?.friction = 0;
        anchor.physicsBody?.linearDamping = 0;
        anchor.physicsBody?.mass = 10;
        self.addChild(anchor)
    }

    func addCharacter() {
        let characterName: String = UserDefaults.standard.string(forKey: "current_character")!
        currentCharacter = SKSpriteNode(imageNamed: characterName);
        currentCharacter.position = CGPoint(x: self.size.width / 2, y: self.size.height - 400)
        currentCharacter.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        currentCharacter.setScale(0.43)
        currentCharacter.zPosition = 2
        currentCharacter.name = "character"
        currentCharacter.physicsBody = SKPhysicsBody(rectangleOf: currentCharacter.size)
        currentCharacter.physicsBody?.categoryBitMask = characterBitMask
        currentCharacter.physicsBody?.contactTestBitMask = candyBitMask
        currentCharacter.physicsBody?.collisionBitMask = candyBitMask;
        currentCharacter.physicsBody?.affectedByGravity = false;
        currentCharacter.physicsBody?.friction = 0;
        currentCharacter.physicsBody?.linearDamping = 0;
        currentCharacter.physicsBody?.mass = 20;
        self.addChild(currentCharacter)
    }

    func addRope() {
        rope.position = CGPoint(x: anchor.position.x, y: anchor.position.y - 70)
        rope.setScale(0.65)
        rope.zPosition = 1
        rope.name = "rope"
        rope.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: rope.size.width, height: rope.size.height))
        rope.physicsBody?.affectedByGravity = false;
        rope.physicsBody?.friction = 0;
        rope.physicsBody?.linearDamping = 0;
        rope.physicsBody?.mass = 5;
        rope.physicsBody?.allowsRotation = false
        self.addChild(rope)
    }

    func addCandy() {
        let number = Int.random(min: 1, max: 24)
        let candyWord = "candie"
        let candyTexture = SKTexture(imageNamed: "\(candyWord)\(number)")
        candy = SKSpriteNode(texture: candyTexture)
        candy.zPosition = 3
        candy.setScale(0.40)
        candy.physicsBody = SKPhysicsBody(circleOfRadius: max(candy.size.width / 2, candy.size.height / 2))
        candy.physicsBody?.isDynamic = true
        candy.name = "candy"
        candy.physicsBody?.categoryBitMask = candyBitMask
        candy.physicsBody?.contactTestBitMask = characterBitMask
        candy.physicsBody?.collisionBitMask = characterBitMask
        candy.physicsBody?.affectedByGravity = false
        candy.position = CGPoint(x: self.frame.size.width + 20, y: self.frame.size.height / 2 + 150)
        self.addChild(candy)
    }

    func moveCandy() {
        self.enumerateChildNodes(withName: "candy", using: {(node, stop) -> Void in
            if let candy = node as? SKSpriteNode {
                candy.position = CGPoint(x: candy.position.x - self.candyVelocity, y: candy.position.y)
                if candy.position.x < 0 {
                    candy.removeFromParent()
                }
            }
        })
    }

    override func update(_ currentTime: TimeInterval) {
        self.moveCandy()
        self.moveCharacter()
        if currentTime - self.lastCandyAdded >  0.75 {
            self.lastCandyAdded = currentTime + Double.random(min: 0.00, max: 0.60)
            self.addCandy()
        }
    }

    func collisionBetween(candy: SKNode, object: SKNode) {
        let moveUp = SKAction.moveBy(x: 0, y: 100, duration:0.0)
        let shrinkRope = SKAction.animate(with: [SKTexture(imageNamed: "rope")], timePerFrame: 0)

        let moveUpBlock = SKAction.run({
            self.anchor.run(moveUp)
        })
        let shrinkRopeBlock = SKAction.run({
            self.rope.run(shrinkRope)
        })

        let sequence = SKAction.sequence([SKAction.wait(forDuration: 0.07), shrinkRopeBlock, moveUpBlock])
        self.run(sequence)

        candy.removeFromParent()
    }

    func didBegin(_ contact: SKPhysicsContact) {
        guard let nodeA = contact.bodyA.node else { return }
        guard let nodeB = contact.bodyB.node else { return }

        if nodeA.name == "candy" && nodeB.name == "character" {
            collisionBetween(candy: nodeA, object: nodeB)
        } else if nodeA.name == "character" && nodeB.name == "candy" {
            collisionBetween(candy: nodeB, object: nodeA)
        }
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?){
        let moveDown = SKAction.moveBy(x: 0, y: -100, duration:0.0)
        let stretchRope = SKAction.animate(with: [SKTexture(imageNamed: "rope_stretch")], timePerFrame: 0)

        let moveDownBlock = SKAction.run({
            self.anchor.run(moveDown, completion: {
               var physicBodies = self.currentCharacter.physicsBody?.allContactedBodies();

                // This count is always zero
                print(physicBodies?.count)

            })
        })
        let stretchRopeBlock = SKAction.run({
            self.rope.run(stretchRope)
        })

        let sequence = SKAction.sequence([moveDownBlock, stretchRopeBlock])
        self.run(sequence)
    }

    func moveCharacter(){
        self.enumerateChildNodes(withName: "anchor", using: {(node, stop) -> Void in
            if let anchorNode = node as? SKSpriteNode {
                if anchorNode.position.x < 120 {
                    anchorNode.position = CGPoint(x: anchorNode.position.x + self.characterVelocity, y: anchorNode.position.y)
                    self.direction = "forward"
                } else if anchorNode.position.x > self.size.width - 120 {
                    anchorNode.position = CGPoint(x: anchorNode.position.x - self.characterVelocity, y: anchorNode.position.y)
                    self.direction = "backward"
                } else if self.direction == "forward" {
                    anchorNode.position = CGPoint(x: anchorNode.position.x + self.characterVelocity, y: anchorNode.position.y)
                    self.direction = "forward"
                } else {
                    anchorNode.position = CGPoint(x: anchorNode.position.x - self.characterVelocity, y: anchorNode.position.y)
                    self.direction = "backward"
                }
            }
        })
    }
}

1 个答案:

答案 0 :(得分:0)

首先,你在这个问题上有很多代码......太多了,这使得很难专注于真正发生的事情。您还缺少moveCharacter()的代码块。

你应该强烈考虑为你的玩家,绳子和(大多数)糖果创建子类。我还会考虑最初创建一个糖果数组,这样你就不会在运行时动态创建物理对象。

至于你的问题,不如在你的班级中创建几个变量那么简单

private var isMoving = false
private var didGetCandy = false

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    //prevent the user from firing the move while in the middle of a move
    guard !isMoving else { return }
    isMoving = true

    let moveDownBlock = SKAction.run({
        self.anchor.run(moveDown) {
           //this is an appreviated form of a 'completion' block
           self.isMoving = false
           print("did I get a candy \(didGetCandy)")
        }
    })
}

func collisionBetween(candy: SKNode, object: SKNode) {
    didGetCandy = true
}