【问题标题】:Why is there multiple collision calls Sprite Kit Swift为什么有多个碰撞调用 Sprite Kit Swift
【发布时间】:2015-12-04 21:17:10
【问题描述】:

我正在构建一个带有碰撞的 iOS 快速游戏。英雄正被屏幕右侧的小星星轰炸。每次星星击中英雄时,都会迭代得分并移除星星。但是,分数会增加一分以上。

节点设置:

var star = SKSpriteNode(imageNamed: "star")
star.size = CGSizeMake(30, 30)
star.zPosition = 10
var starPhysicsRect = CGRectMake(star.position.x - star.frame.size.width / 2, star.position.y - star.frame.size.width / 2, star.frame.size.width, star.frame.size.height)
star.physicsBody = SKPhysicsBody(edgeLoopFromRect: starPhysicsRect)
star.physicsBody?.restitution = 0
star.name = "star"
star.physicsBody?.mass = 0
return star

didBeginContact 函数:

func didBeginContact(contact: SKPhysicsContact) {
    //collision variables
    var firstBodyNode = contact.bodyA.node as! SKSpriteNode
    var secondBodyNode = contact.bodyB.node as! SKSpriteNode
    var firstNodeName = firstBodyNode.name
    var secondNodeName = secondBodyNode.name

    //other variables
    var scoreLabel: SKLabelNode = constantsInstance.scoreLabel(position: CGPointMake(self.frame.size.width * 0.86, self.frame.size.height * 0.928))


    //check if hero hit star
    if firstNodeName == "hero" && secondNodeName == "star" {
        println("star hit")
        secondBodyNode.removeFromParent()

        //iterate score
        childNodeWithName("scoreLabel")?.removeFromParent()
        scoreLabel.text = "\(counterForScore)"
        counterForScore++
        self.addChild(scoreLabel)
    }
}

我也多次将“star hit”打印到控制台。如果我在第一次调用函数时去掉星号,为什么会多次调用 didBeginContact 函数?

我运行了较小规模的模拟,发现如果没有移除命令,星星会相当深入地进入英雄(因为 SKAction)。会不会是在星星进入英雄的过程中,在被移除之前多次调用了didBeginContact函数?

非常感谢所有帮助。

【问题讨论】:

  • 您能告诉我们您设置 spriteNodes 的代码吗?
  • 刚刚添加了设置
  • 谢谢!这里似乎有什么不对劲? star.name = "bottomStar" 仍然在您检查 secondName == "star" 时触发?您是否正在共同寻找一种不同的互动方式?
  • 好收获。我在调整代码时错过了这一点。抱歉,草率的错误。刚改回来。
  • 好的,还有几个问题:在其他地方对精灵做了什么改变?你只是在创建一个 starSprite 的实例吗?

标签: swift sprite-kit collision-detection collision


【解决方案1】:

您可以在继续之前检查SKSpriteNode 的父级是否为零。

func didBeginContact(contact: SKPhysicsContact) {
    var firstBodyNode : SKSpriteNode!
    var secondBodyNode : SKSpriteNode!

    //  Assuming that the contact test bit mask of star is greater than hero. If it's not you should reverse the condition.

    if contact.bodyA.contactTestBitMask < contact.bodyB.contactTestBitMask {
        firstBodyNode = contact.bodyA.node as! SKSpriteNode
        secondBodyNode = contact.bodyB.node as! SKSpriteNode
    } else {
        firstBodyNode = contact.bodyB.node as! SKSpriteNode
        secondBodyNode = contact.bodyA.node as! SKSpriteNode
    }

    var firstNodeName = firstBodyNode.name
    var secondNodeName = secondBodyNode.name

    if firstNodeName == "hero" && secondNodeName == "star" {
        if secondBodyNode.parent != nil {
           // Your code.
        }
    }
}

【讨论】:

  • 刚刚试过了,还是有问题。你想通过检查 nil 来完成什么?
  • removeFromParent 将导致星的父级为nil
  • 你在改变'bottomStar'部分后检查父母是否是nil
  • 是的。我可以给你们更多有用的信息吗?再次感谢您的帮助。
【解决方案2】:

可能是由于physicsBody:

var star = SKSpriteNode(imageNamed: "star")
star.size = CGSizeMake(30, 30)
star.zPosition = 10
var starPhysicsRect = CGRectMake(star.position.x - star.frame.size.width / 2, star.position.y - star.frame.size.width / 2, star.frame.size.width, star.frame.size.height)
star.physicsBody = SKPhysicsBody(edgeLoopFromRect: starPhysicsRect)

看看创建starPhysicsRect的逻辑:

(star.position.x - star.frame.size.width / 2, star.position.y - star.frame.size.width / 2, star.frame.size.width, star.frame.size.height)

据我所知,这转化为以下值: (-15, -15, 30, 30) 那些负位置坐标看起来很奇怪。你确定你不只是想要:SKPhysicsBody(rectangleOfSize: star.size) 吗?

【讨论】:

  • 是的。我创建了一个框来勾勒出星星的轮廓。但是,根据这个解决方案,创建CGRect 与使用rectangleOfSize 的工作不同,即使它们具有相同的尺寸。非常感谢您的帮助!
猜你喜欢
  • 2013-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-09
  • 2014-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多