如何在精灵套件游戏中检测无碰撞



我正在做一个游戏,你必须使用挂在线程上的蜘蛛捕捉糖果,如我在此链接中所示:游戏截图(我是新来的,所以我还不能发布图像)。我已经有蜘蛛从左到右的移动,而且我能够使用 SKAction 通过"Y"来捕捉糖果,我唯一的问题是我还没有弄清楚如何知道蜘蛛是否没有捕获任何糖果,在他的移动过程中,我尝试在动作完成时使用 allContactedBody 函数,但返回的数组计数始终为零。有什么建议吗?

这是代码:

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"
                }
            }
        })
    }
}
首先,

你在这个问题中有很多代码......太多了,它很难专注于真正发生的事情。您还缺少 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
}

最新更新