Swift/SpriteKit中的碰撞检测问题



我正在Swift/Xcode中玩游戏编程,正在努力让冲突发挥作用。

我使用的是Xcode 8 Beta 3(因为我不能在MacOS Sierra上使用Xcode 7),所以它使用了新的Swift 3.0语法。游戏中有一只小狗(在SK场景文件中定义),它会跳跃并收集右侧投掷的物品。抛出的项在函数中创建,并在抛出新项时删除。

我需要接触投掷的物品来接触小狗。我打开了物理功能,物品从小狗身上弹了下来,但没有登记任何联系人。

这是我的密码。混乱代码的应用程序,但它在Swift上的第一次尝试,以及目前刚刚加入的一切。我看不出我做错了什么:(

更新:正如cocoajoe所建议的,我已经尝试将掩码设置为1,并简化了代码以删除对gamescene.sks文件的引用,并以编程方式创建了所有内容,但仍然不起作用。我已经更新了下面的代码,以反映最新版本的代码。。。

import SpriteKit
import AVFoundation
class GameScene: SKScene, SKPhysicsContactDelegate {
    required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder) is not used in this app")
}
override init(size: CGSize) {
    super.init(size: size)
    anchorPoint = CGPoint(x: 0.0, y: 0.0)
}
var isJumping = false
var gamePaused = false
var gameRunning = false
var playerScore = 0
var lastSpawnTime = 0
var lastTick = 0
var spawnDelay = 4
let PuppyCategory       : UInt32 = 0x1 << 0
let ThrowableCategory   : UInt32 = 0x1 << 1
let GroundCategory      : UInt32 = 0x1 << 2
override func didMove(to view: SKView) {
    physicsWorld.gravity = CGVector(dx: 0.0, dy: -9.8)
    physicsWorld.contactDelegate = self
    let background = SKSpriteNode(imageNamed: "bg")
    background.anchorPoint = CGPoint(x: 0.0, y:0.0)
    background.size = size
    addChild(background)
    // Set up Ground Object
    let Ground = SKSpriteNode()
    Ground.name = "Ground"
    Ground.size = CGSize(width:frame.width, height: frame.height / 10)
    Ground.position = CGPoint(x: frame.midX, y: Ground.frame.height / 2 )
    Ground.zPosition = -20
    Ground.color = SKColor.white()
    // Set up the Physics
    Ground.physicsBody = SKPhysicsBody(rectangleOf: Ground.size)
    Ground.physicsBody!.categoryBitMask = GroundCategory
    Ground.physicsBody!.contactTestBitMask = PuppyCategory | ThrowableCategory
    Ground.physicsBody!.collisionBitMask = PuppyCategory | ThrowableCategory
    Ground.physicsBody?.affectedByGravity = false
    Ground.physicsBody?.allowsRotation = false
    Ground.physicsBody?.isDynamic = false
    Ground.physicsBody?.mass = 1.99999
    // Initialise the Node
    addChild(Ground)
    // Create a Puppy
    let Puppy = SKSpriteNode(imageNamed: "puppy1")
    Puppy.name = "Puppy"
    Puppy.position = CGPoint(x: frame.width / 10, y: frame.height / 2)
    Puppy.size = CGSize(width: frame.width / 7, height: frame.height / 5)
    Puppy.zPosition = 3
    // Set up the Physics
    Puppy.physicsBody = SKPhysicsBody(rectangleOf: Puppy.size)
    Puppy.physicsBody!.categoryBitMask = PuppyCategory
    Puppy.physicsBody!.contactTestBitMask = ThrowableCategory | GroundCategory
    Puppy.physicsBody!.collisionBitMask = ThrowableCategory | GroundCategory
    Puppy.physicsBody?.affectedByGravity = true
    Puppy.physicsBody?.allowsRotation = false
    Puppy.physicsBody?.isDynamic = true
    Puppy.physicsBody?.mass = 1.99999
    // Set up the Textures/Animation Frames
    var TextureAtlas = SKTextureAtlas()
    var TextureArray = [SKTexture]()
    TextureAtlas = SKTextureAtlas(named: "puppy")
    for i in 1...TextureAtlas.textureNames.count {
        let Name = "puppy(i).png"
        TextureArray.append(SKTexture(imageNamed: Name))
    }
    Puppy.run(SKAction.repeatForever(SKAction.animate(with:TextureArray, timePerFrame: 0.1)))
    // Add the Sprite
    addChild(Puppy)

    let gameMessage = SKSpriteNode(imageNamed: "TapToPlay")
    gameMessage.name = "GameMessage"
    gameMessage.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
    gameMessage.zPosition = 30
    gameMessage.setScale(0.0)
    addChild(gameMessage)
    let gameLogo = SKSpriteNode(imageNamed: "pjlogo")
    gameLogo.name = "GameLogo"
    gameLogo.size = CGSize(width: frame.width / 3, height: frame.height / 5)
    gameLogo.position = CGPoint(x: frame.midX, y: (frame.maxY / 100) * 80)
    gameLogo.zPosition = 30
    addChild(gameLogo)
    let scale = SKAction.scale(to: 1.0, duration: 1)
    scene?.childNode(withName: "GameMessage")!.run(scale)
    if let musicURL = Bundle.main.urlForResource("bgmusic", withExtension: "mp3") {
        var backgroundMusic: SKAudioNode!
        backgroundMusic = SKAudioNode(url: musicURL)
        addChild(backgroundMusic)
    }
    startNewGame()
}
func puppyJump() {
    if gameRunning {
        let Puppy = childNode(withName: "Puppy")
        if !isJumping {
            Puppy?.physicsBody?.applyImpulse(CGVector(dx: 0,dy: 1400))
            isJumping = true
        }
    }
}
func generateThrowable() {
    print("new enemy")
    let oldItem = childNode(withName: "throwableItem")
    oldItem?.removeFromParent()
    let throwableItem = SKSpriteNode(imageNamed: "puppy1")
    throwableItem.name = "throwableItem"
    throwableItem.position = CGPoint(x: frame.maxX, y: frame.midY)
    throwableItem.zPosition = 3
    throwableItem.setScale(0.1)
    throwableItem.physicsBody = SKPhysicsBody(rectangleOf: throwableItem.size)
    throwableItem.physicsBody!.categoryBitMask = ThrowableCategory
    throwableItem.physicsBody!.contactTestBitMask = PuppyCategory | GroundCategory
    throwableItem.physicsBody!.collisionBitMask = PuppyCategory | GroundCategory
    throwableItem.physicsBody?.friction = 0.1
    throwableItem.physicsBody?.restitution = 0.1
    throwableItem.physicsBody?.mass = 0.01
    throwableItem.physicsBody?.affectedByGravity = true
    throwableItem.physicsBody?.allowsRotation = true
    throwableItem.physicsBody?.isDynamic = true
    addChild(throwableItem)
    throwableItem.physicsBody?.applyImpulse(CGVector(dx: -7,dy: 4))
    let throwableTrail = SKEmitterNode(fileNamed: "particleTrail.sks")
    throwableTrail?.name = "throwableTrail"
    throwableTrail?.targetNode = scene
    throwableItem.addChild(throwableTrail!)
}
func startNewGame() {
    let logo = childNode(withName: "GameLogo")
    let gameMessage = childNode(withName: "GameMessage")
    logo?.removeFromParent()
    gameMessage?.removeFromParent()
    let gameScore = SKLabelNode(fontNamed: "Arial")
    gameScore.name = "GameScore"
    gameScore.text = "Score:0"
    gameScore.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.right
    gameScore.fontSize = 20
    gameScore.position = CGPoint(x: frame.maxX - 20, y: frame.maxY - 26)
    gameScore.zPosition = 30
    addChild(gameScore)
    let pauseButton = SKLabelNode(fontNamed: "Arial")
    pauseButton.name = "pauseButton"
    pauseButton.text = "PAUSE"
    pauseButton.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.left
    pauseButton.fontSize = 20
    pauseButton.position = CGPoint(x: 20, y: frame.maxY - 26)
    pauseButton.zPosition = 30
    addChild(pauseButton)
    gameRunning = true
}
func didBeginContact(contact: SKPhysicsContact) {
    print("contact")
    var firstBody: SKPhysicsBody
    var secondBody: SKPhysicsBody
    // 2
    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
        firstBody = contact.bodyA
        secondBody = contact.bodyB
    } else {
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    }
    // 3
    if firstBody.categoryBitMask == PuppyCategory && secondBody.categoryBitMask == GroundCategory {
        print("Hit bottom. First contact has been made.")
    }
}
override func update(_ currentTime: TimeInterval) {
    // Called before each frame is rendered
    if gameRunning {
        let gameScore = childNode(withName: "GameScore") as? SKLabelNode
        gameScore?.text = "Score:(playerScore)"
        let currentTick:Int = Int(ceil(currentTime))
        if lastTick < currentTick {
            lastTick = currentTick
        }
        if (lastSpawnTime + spawnDelay) < currentTick {
            // Time to Spawn new Bad Guy
            generateThrowable()
            lastSpawnTime = currentTick
        }
    }
}
}

我没有检查其他部件。(您的代码仍然需要大量资源…)

但这条线:

func didBeginContact(contact: SKPhysicsContact) {

需要更改为:

func didBegin(_ contact: SKPhysicsContact) {

Swift 3中。(这是Xcode建议的,只需键入didBegin。)

请尝试。

最新更新