首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >简单的SpriteKit接触检测(太空射击游戏)

简单的SpriteKit接触检测(太空射击游戏)
EN

Stack Overflow用户
提问于 2016-04-15 20:36:49
回答 3查看 132关注 0票数 1

我想做一个简单的太空射击游戏。接触应该发生在鱼雷和外星人之间,或者航天飞机和外星人之间。问题是,第二次接触(航天飞机对外星人)只有在第一种接触发生后才发生(鱼雷对外星人),而且它们并不总是精确的。这是在类之外创建的结构。

代码语言:javascript
复制
struct PhysicsCategory {
static let alien : UInt32 = 1
static let torpedo : UInt32 = 2
static let shuttle : UInt32 = 3 }

穿梭机:

代码语言:javascript
复制
shuttle.physicsBody = SKPhysicsBody(rectangleOfSize: shuttle.size)
shuttle.physicsBody?.categoryBitMask = PhysicsCategory.shuttle
shuttle.physicsBody?.contactTestBitMask = PhysicsCategory.alien 
shuttle.physicsBody?.dynamic = false 
shuttle.physicsBody?.affectedByGravity = false

鱼雷:

代码语言:javascript
复制
torpedo.physicsBody = SKPhysicsBody(rectangleOfSize: torpedo.size)
torpedo.physicsBody?.categoryBitMask = PhysicsCategory.torpedo
torpedo.physicsBody?.contactTestBitMask = PhysicsCategory.alien
torpedo.physicsBody?.affectedByGravity = false
torpedo.physicsBody?.dynamic = false

外侨:

代码语言:javascript
复制
alien.physicsBody = SKPhysicsBody(rectangleOfSize: torpedo.size)
alien.physicsBody?.categoryBitMask = PhysicsCategory.alien
alien.physicsBody?.contactTestBitMask = PhysicsCategory.torpedo
alien.physicsBody?.affectedByGravity = false
alien.physicsBody?.dynamic = true

最后,这是我的联系人代码:

代码语言:javascript
复制
    func didBeginContact(contact: SKPhysicsContact) {
    var firstBody : SKPhysicsBody = contact.bodyA
    var secondBody : SKPhysicsBody = contact.bodyB

    if ((firstBody.categoryBitMask == PhysicsCategory.alien) && (secondBody.categoryBitMask == PhysicsCategory.torpedo)) ||
    ((firstBody.categoryBitMask == PhysicsCategory.torpedo) && (secondBody.categoryBitMask == PhysicsCategory.alien)) {
        self.contactWithTorpedo(firstBody.node as! SKSpriteNode, torpedo: secondBody.node as! SKSpriteNode)
    } else if ((firstBody.categoryBitMask == PhysicsCategory.shuttle) && (secondBody.categoryBitMask == PhysicsCategory.alien)) {
            self.contactWithShuttle(firstBody.node as! SKSpriteNode, shuttle: secondBody.node as! SKSpriteNode)
    }
}


func contactWithTorpedo (alien: SKSpriteNode, torpedo : SKSpriteNode) {
    alien.removeFromParent()
    torpedo.removeFromParent()
    score++
    scoreLabel.text = "score: " + "\(score)"
}

func contactWithShuttle (alien:SKSpriteNode, shuttle:SKSpriteNode) {
    alien.removeFromParent()
    shuttle.removeFromParent()

    self.view?.presentScene(EndScene())

}

我不太清楚问题出在哪里,而且我还看过一些教程也是这样做的。我不知道这是否相关,但这不是一个iOS游戏,而是一个OSX。提前谢谢你!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-04-19 11:48:49

您可能会发现对didBeginContact进行如下重构并不那么令人费解,因为这样可以避免使用firstBody/secondbody的内容和复杂的if...then条件来查看与什么有联系的内容:

代码语言:javascript
复制
func didBeginContact(contact: SKPhysicsContact) {
    let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

    switch contactMask {
    case PhysicsCategory.alien | PhysicsCategory.torpedo:
       // alien and torpedo have contacted
       contact.bodyA.removeFromParent()
       contact.bodyB.removeFromParent()
       score += 1
       scoreLabel.text = "score: " + "\(score)"

    case PhysicsCategory.alien | PhysicsCategory.shuttle:
       // alien and shuttle have contacted
       contact.bodyA.removeFromParent()
       contact.bodyB.removeFromParent()

       self.view?.presentScene(EndScene())

    default :
        //Some other contact has occurred
        print("Some other contact")
    }
}

您只需为游戏中的所有联系人添加尽可能多的PhysicsCategory.enemy | PhysicsCategory.player案例即可。对每个潜在的联系人进行单独编码,这样您就不会在if...then...else中失去自我。

如果您确实只需要引用联系人中涉及的一个节点(例如,在敌人击中该节点后将其移除),您可以这样做:

代码语言:javascript
复制
let playerNode = contact.bodyA.categoryBitMask == PhysicsCategory.player ? contact.bodyA.node! : contact.bodyB.node!
playernode.removefromParent
票数 1
EN

Stack Overflow用户

发布于 2016-04-15 21:32:26

我建议您阅读有关SKPhysicsBody的文档。

场景中的每个物理体可以被分配到多达32个不同的类别,每一个都对应于位掩码中的一个位。定义游戏中使用的掩码值。结合collisionBitMask和contactTestBitMask属性,定义哪些物理体相互作用,以及游戏何时收到这些相互作用的通知。

首先,我会将PhysicsCategory更改为

代码语言:javascript
复制
struct PhysicsCategory {
static let alien : UInt32 = 0x1 << 1
static let torpedo : UInt32 = 0x1 << 2
static let shuttle : UInt32 = 0x1 << 3 
}

然后

代码语言:javascript
复制
alien.physicsBody?.contactTestBitMask = PhysicsCategory.torpedo | PhysicsCategory.shuttle

希望这能有所帮助。

票数 0
EN

Stack Overflow用户

发布于 2016-04-17 09:23:00

所以我昨天真的解决了我的问题。我正在发布更新后的代码,以防对某人有帮助。课外:

代码语言:javascript
复制
struct PhysicsCategory {
static let player : UInt32 = 0x1 << 0
static let bullet : UInt32 = 0x1 << 1
static let enemy : UInt32 = 0x1 << 2}

然后,像我前面写的那样,在对每个精灵应用物理之后,在这个类中:

代码语言:javascript
复制
    //Contact with bullet
func contactWithBullet(enemy : SKSpriteNode, bullet: SKSpriteNode) {
    enemy.removeFromParent()
    bullet.removeFromParent()
    score += 1
    updateLabels()
}

//contact with player
func contactWithPlayer(player : SKSpriteNode, enemy : SKSpriteNode) {
    enemy.removeFromParent()
    lives -= 1
    updateLabels() //another function that changes the score and lives labels
}
//CONTACT DETECTION
func didBeginContact(contact: SKPhysicsContact) {
    let firstBody : SKPhysicsBody = contact.bodyA
    let secondBody : SKPhysicsBody = contact.bodyB

    if (firstBody.categoryBitMask == PhysicsCategory.enemy && secondBody.categoryBitMask == PhysicsCategory.bullet || firstBody.categoryBitMask == PhysicsCategory.bullet && secondBody.categoryBitMask == PhysicsCategory.enemy) {
        contactWithBullet(firstBody.node as! SKSpriteNode, bullet: secondBody.node as! SKSpriteNode)
        checkScore()
        enemiesInWave -= 1
    } else if (firstBody.categoryBitMask == PhysicsCategory.enemy && secondBody.categoryBitMask == PhysicsCategory.player || firstBody.categoryBitMask == PhysicsCategory.player && secondBody.categoryBitMask == PhysicsCategory.enemy) {
        contactWithPlayer(firstBody.node as! SKSpriteNode, enemy: secondBody.node as! SKSpriteNode)
        checkLives()
        enemiesInWave -= 1
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36656396

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档