【问题标题】:Swift Spritekit - Only collide sprites when they are in certain positions?Swift Spritekit - 只有在特定位置时才会碰撞精灵?
【发布时间】:2019-06-17 04:41:10
【问题描述】:

您好,请放轻松,因为我对 Swift 还是很陌生。我正在创建一个游戏,您的角色(在屏幕左侧)必须向上或向下滑动以改变车道(4 车道)或通过点击屏幕右侧跳跃,以躲避来自右侧的障碍物屏幕的一侧。这带来了一个问题,当角色精灵在一个车道上时,它的一些像素在上面的车道上,所以在不同的车道上并不能保护角色免受碰撞。 (角色跳跃时也会出现这个问题)有没有办法编程让角色和障碍物只有在同一条车道上才会发生碰撞?

我已尝试使 .collisionBitMask 和 .categoryBitMask 根据障碍物或角色的位置而变化,但我不知道如何正确编码。老实说,我很迷茫。这是一些代码:

runningDoggo.physicsBody = SKPhysicsBody(texture: doggoTexture, size: runningDoggo.size)
runningDoggo.physicsBody?.affectedByGravity = false
runningDoggo.physicsBody?.isDynamic = true
runningDoggo.physicsBody?.collisionBitMask = 0x1 << 2
bush.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "8-bit bush"), size: bush.size)
bush.physicsBody?.isDynamic = true
bush.physicsBody?.affectedByGravity = false
bush.physicsBody?.categoryBitMask = 0x1 << 1

然后我在一个函数中有一组开关盒,用于随机选择灌木进入的车道

    switch randomLane{
    case 1:
        bush.position = CGPoint(x: 0.4*UIScreen.main.bounds.width, y:-0.07*UIScreen.main.bounds.height)
        if(bush.position.y < runningDoggo.position.y) {
            bush.zPosition = 6
        }
        self.addChild(bush)
    case 2:
        bush.position = CGPoint(x: 0.4*UIScreen.main.bounds.width, y:-0.18*UIScreen.main.bounds.height)
        if(bush.position.y < runningDoggo.position.y)  {
            bush.zPosition = 6
        }
        self.addChild(bush)
    case 3:
        bush.position = CGPoint(x: 0.4*UIScreen.main.bounds.width, y:-0.29*UIScreen.main.bounds.height)
        if(bush.position.y < runningDoggo.position.y) {
            bush.zPosition = 6
        }
        self.addChild(bush)
    case 4:
        bush.position = CGPoint(x: 0.4*UIScreen.main.bounds.width, y:-0.4*UIScreen.main.bounds.height)
        if(bush.position.y < runningDoggo.position.y) {
            bush.zPosition = 6
        }
        self.addChild(bush)
    default:
        print("How is this not 1,2,3, or 4?")
    }
    bush.run(moveAndRemoveBush)

我希望它只碰撞(编辑:不要碰撞而是接触)runningDoggo 精灵与灌木精灵如果它们在同一条车道上,并且如果角色不在障碍物的车道上则通过而不发生碰撞。

【问题讨论】:

    标签: ios swift xcode sprite-kit collision-detection


    【解决方案1】:

    首先,那个复杂的开关可以简化成这样(任何时候你多次编写相同的代码,想想你是否可以简化它):

    bush.position.x = 0.40 * UIScreen.main.bounds.width
    bush.position.y = 0.07 * randomLane * UIScreen.main.bounds.height) // 0.07, 0.14, 0.21 or 0.28 for lanes 1-4 
    if (bush.position.y < runningDoggo.position.y) bush.zPosition = 6
    self.addChild(bush)
    bush.run(moveAndRemoveBush)
    

    好的 - 我知道 0.07、0.14、0.21 和 0.28 的 y 值与 0.07、0.18、0.29 和 0.40 的值不匹配,但也许这是你可以调整的东西,或者将偏移数组定义为一个属性:

    let bushYOffset = [0.07, 0.18, 0.29, 0.40]
    

    然后只需选择车道对应的偏移量

    bush.position.x = 0.40 * UIScreen.main.bounds.width
    bush.position.y = bushYOffset[randonLane-1] * UIScreen.main.bounds.height)
    if (bush.position.y < runningDoggo.position.y) bush.zPosition = 6
    self.addChild(bush)
    bush.run(moveAndRemoveBush)
    

    要解决您的主要问题,您可以为数组中的每个通道创建一个位掩码:

    let laneMask: [UInt32] = [1<<1, 1<<2, 1<<3, 1<<4]
    

    当 Doggo 移动到一个新的车道时,给 Doggo 对应的 collisonBitmask 的物理体它刚刚移动到的车道:

    runningDoggo.physicsBody?.collisionBitMask = laneMask[doggoLane - 1] // Arrays start at 0
    

    当你生成一个障碍物时,也给它它所在车道的碰撞位掩码:

    bush.physicsBody?.collisionBitMask = laneMask[randomLane - 1] // Arrays start at 0
    

    现在 Doggo 和灌木丛只有在同一车道上才会发生碰撞。如果它们在不同的车道上,它们就不会,即使它们的某些像素重叠。

    如果屏幕上还有狗狗和灌木需要与之交互的其他精灵,您可能需要对此进行调整。

    注意:

    您确定要让它们发生碰撞而不是接触吗?当精灵相互碰撞和反弹并在屏幕上飞来飞去时,就会发生碰撞;联系人是两个精灵接触的地方,你的代码被调用,你可以让一个精灵爆炸,或者失去生命,或者增加分数等。

    编辑:我的碰撞和接触分步指南: https://stackoverflow.com/a/51041474/1430420

    以及碰撞和接触测试位掩码指南: https://stackoverflow.com/a/40596890/1430420

    操作位掩码以关闭和打开单独的碰撞和接触。 https://stackoverflow.com/a/46495864/1430420

    【讨论】:

    • 非常感谢史蒂夫的精彩提示。是的,你是对的,我的意思是我希望他们接触而不是碰撞,因为接触正确车道上的灌木应该会结束游戏并触发我的重启屏幕。用contactBitMask替换collisionBitMask是否是相同的解决方案?
    • 它是“contactTestBitMask”,但您还需要将您的场景设置为联系人代理并设置“didBegib(contact:)”功能。 “collisikns 和联系人的分步指南”应该会有所帮助。
    • 我确实有 didBegin(contact:) 似乎工作的功能。问题在于它适用于所有车道,而不仅仅是我需要的特定车道。至于联系人代表,我一直在使用“self.physicsWorld.contactDelegate = self”对吗? (*每次我输入contactTestBitMask时,我都忘记了“测试”部分,我的错)
    • @IMathSometimes 如果你;re 'didBegin' 在应该触发的时候触发,那么你已经完成了 90% 的工作:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多