在Swift / SpriteKit中进行碰撞检测

时间:2016-07-27 10:21:36

标签: ios swift xcode

我在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
        }

    }

}
}

1 个答案:

答案 0 :(得分:0)

我没有检查过其他部分。 (您的代码仍需要大量资源......)

但这一行:

func didBeginContact(contact: SKPhysicsContact) {

需要更改为:

func didBegin(_ contact: SKPhysicsContact) {
在Swift 3中的

。(Xcode建议,只需输入didBegin。)

请尝试。