Swift 3太空射击游戏:子弹碰撞问题

Swift 3太空射击游戏:子弹碰撞问题,swift,sprite-kit,swift3,collision-detection,collision,Swift,Sprite Kit,Swift3,Collision Detection,Collision,我正在尝试创建一个用Swift 3编写的射击游戏。目前在使碰撞正常工作方面遇到困难。如果一颗子弹击中敌人,我需要一次爆炸,然后从游戏中移除那个特定的敌人和子弹。如果一个玩家击中了一个敌人,我需要在这两者之间发生爆炸,然后从屏幕上移除那个特定的敌人和玩家,并结束游戏。这就是我到目前为止所知道的,子弹只是弹回而没有发生碰撞。非常感谢您的帮助 import SpriteKit import GameplayKit enum CollisonType: UInt32 { case player

我正在尝试创建一个用Swift 3编写的射击游戏。目前在使碰撞正常工作方面遇到困难。如果一颗子弹击中敌人,我需要一次爆炸,然后从游戏中移除那个特定的敌人和子弹。如果一个玩家击中了一个敌人,我需要在这两者之间发生爆炸,然后从屏幕上移除那个特定的敌人和玩家,并结束游戏。这就是我到目前为止所知道的,子弹只是弹回而没有发生碰撞。非常感谢您的帮助

import SpriteKit
import GameplayKit

enum CollisonType: UInt32 {
    case player = 1
    case ammo = 2
    case enemy = 4
}

class GameScene: SKScene, SKPhysicsContactDelegate {

    var starfield: SKEmitterNode!
    var player: SKSpriteNode!
    var ammo: SKSpriteNode!
    var enemy: SKSpriteNode!
    var gameScore: SKLabelNode!
    var score: Int = 0 {
        didSet { // didSet a property observer used to update gameScore
            gameScore.text = "Score: \(score)"
        }
    }

    var possibleEnemies = ["ball", "hammer", "tv"]
    var gameTimer: Timer! // Used to create enemies regularly.
    var isGameOver = false //  a boolean that will be set to true when we should stop increasing the player's score

    override func didMove(to view: SKView) {

        backgroundColor = UIColor.black

        starfield = SKEmitterNode(fileNamed: "Starfield")!
        starfield.position = CGPoint(x: 1024, y: 384)
        starfield.advanceSimulationTime(10)
        addChild(starfield)
        starfield.zPosition = -1

        player = SKSpriteNode(imageNamed: "player")
        player.position = CGPoint(x: 100, y: 384)
        player.physicsBody = SKPhysicsBody(texture: player.texture!, size: player.size)
        player.physicsBody!.categoryBitMask = CollisonType.player.rawValue
        player.physicsBody!.contactTestBitMask = CollisonType.enemy.rawValue
        addChild(player)

        gameScore = SKLabelNode(fontNamed: "Chalkduster")
        gameScore.text = "Score: 0"
        gameScore.horizontalAlignmentMode = .left
        gameScore.position = CGPoint(x: 8, y: 8)
        addChild(gameScore)

        physicsWorld.gravity = CGVector(dx: 0, dy: 0) 
        physicsWorld.contactDelegate = self

        gameTimer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)

        gameTimer = Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(createAmmo), userInfo: nil, repeats: true)

    }

    func createAmmo() {
        if isGameOver {
            return
        }

        ammo = SKSpriteNode(imageNamed: "bullet")
        ammo.name = "ammo"
        ammo.position = CGPoint(x: player.position.x + 100, y: player.position.y)
        addChild(ammo)

        ammo.physicsBody = SKPhysicsBody(texture: ammo.texture!, size: ammo.size)
        ammo.physicsBody!.categoryBitMask = CollisonType.ammo.rawValue
        ammo.physicsBody!.contactTestBitMask = CollisonType.enemy.rawValue

        ammo.physicsBody!.velocity = CGVector(dx: 900, dy: 0)
        ammo.physicsBody!.linearDamping = 0
        ammo.physicsBody!.angularDamping = 0

    }

    func createEnemy() {
        possibleEnemies = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: possibleEnemies) as! [String]
        let randomDistribution = GKRandomDistribution(lowestValue: 50, highestValue: 736)

        enemy = SKSpriteNode(imageNamed: possibleEnemies[0])
        enemy.name = "enemy"
        enemy.position = CGPoint(x: 1200, y: randomDistribution.nextInt())
        addChild(enemy)

        enemy.physicsBody = SKPhysicsBody(texture: enemy.texture!, size: enemy.size)
        enemy.physicsBody!.categoryBitMask = CollisonType.enemy.rawValue
        enemy.physicsBody!.contactTestBitMask = CollisonType.player.rawValue | CollisonType.ammo.rawValue

        enemy.physicsBody!.velocity = CGVector(dx: -300, dy: 0)
        enemy.physicsBody!.angularVelocity = 5
        enemy.physicsBody!.linearDamping = 0
        enemy.physicsBody!.angularDamping = 0

    }

    override func update(_ currentTime: TimeInterval) {
        for node in children {
            if node.position.x < -300 || node.position.x > 1300 || node.position.y < -300 || node.position.y > 1000 {
                node.removeFromParent()
            }
        }

        if !isGameOver {
            score += 1
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else { return }
        var location = touch.location(in: self)

        if location.y < 50 {
            location.y = 50
        } else if location.y > 730 {
            location.y = 730
        }

        player.position = location
    }

    func didBegin(_ contact: SKPhysicsContact) {

        if contact.bodyA.node == player {
            playerCollided(with: contact.bodyB.node!)
        } else if contact.bodyB.node == player {
            playerCollided(with: contact.bodyA.node!)
        }

        if contact.bodyA.node == ammo {
            ammoCollided(with: contact.bodyB.node!)
        } else if contact.bodyB.node == ammo {
            ammoCollided(with: contact.bodyA.node!)
        }

    }

    func playerCollided(with node:SKNode) {
        if node.name == "enemy" {
            let explosion = SKEmitterNode(fileNamed: "explosion")!
            explosion.position = enemy.position
            addChild(explosion)

            player.removeFromParent()
            enemy.removeFromParent()
            isGameOver = true
        }
    }

    func ammoCollided(with node:SKNode) {
        if node.name == "enemy" {
            let explosion = SKEmitterNode(fileNamed: "explosion")!
            explosion.position = enemy.position
            addChild(explosion)

            ammo.removeFromParent()
            enemy.removeFromParent()
        }
    }
}
导入SpriteKit
导入游戏工具包
枚举碰撞类型:UInt32{
案例玩家=1
弹药箱=2
案例敌人=4
}
类游戏场景:SKScene,SKPhysicContactDelegate{
var starfield:SKEmitterNode!
var玩家:斯普林泰诺德!
var ammo:SKSpriteNode!
我们的敌人:斯普林泰诺德!
var gameScore:SKLabelNode!
变量分数:Int=0{
didSet{//didSet用于更新游戏分数的属性观察者
gameScore.text=“分数:\(分数)”
}
}
var possibleEnemies=[“球”、“锤”、“电视”]
var gameTimer:Timer!//用于定期创建敌人。
var isGameOver=false//当我们停止增加玩家的分数时,该布尔值将设置为true
覆盖func didMove(到视图:SKView){
backgroundColor=UIColor.black
starfield=SKEmitterNode(文件名为:“starfield”)!
starfield.position=CGPoint(x:1024,y:384)
starfield.高级模拟时间(10)
addChild(starfield)
starfield.zPosition=-1
player=SKSpriteNode(图像名为“player”)
player.position=CGPoint(x:100,y:384)
player.physicsBody=SKPhysicsBody(纹理:player.texture!,大小:player.size)
player.physicsBody!.categoryBitMask=CollisonType.player.rawValue
player.physicsBody!.contactTestBitMask=CollisonType.敌军.rawValue
addChild(玩家)
gameScore=SKLabelNode(FontName:“粉笔掸子”)
gameScore.text=“分数:0”
gameScore.horizontalAlignmentMode=.left
gameScore.position=CGPoint(x:8,y:8)
addChild(游戏分数)
physicsWorld.gravity=CGVector(dx:0,dy:0)
physicsWorld.contactDelegate=self
gameTimer=Timer.scheduledTimer(时间间隔:0.5,目标:self,选择器:#选择器(CreateEquire),用户信息:nil,重复:true)
gameTimer=Timer.scheduledTimer(时间间隔:0.4,目标:self,选择器:#选择器(createAmmo),用户信息:nil,重复:true)
}
func createAmmo(){
如果游戏结束了{
返回
}
弹药=SKSpriteNode(图像名称:“子弹”)
ammo.name=“ammo”
ammo.position=CGPoint(x:player.position.x+100,y:player.position.y)
addChild(弹药)
ammo.physicsBody=SKPhysicsBody(纹理:ammo.texture!,大小:ammo.size)
ammo.physicsBody!.categoryBitMask=CollisonType.ammo.rawValue
ammo.physicsBody!.contactTestBitMask=CollisonType.敌方.rawValue
弹药.physicsBody!.velocity=CGVector(dx:900,dy:0)
ammo.physicsBody!.linearDamping=0
弹药.物理体!.angularDamping=0
}
函数{
possibleEnemies=GKRandomSource.SharedAndom().arrayByShufflingObjects(在:possibleEnemies中)作为![String]
let randomDistribution=GK随机分布(最低值:50,最高值:736)
敌方=SKSpriteNode(图像名称:可能事件[0])
敌军名称=“敌军”
敌方.position=CGPoint(x:1200,y:randomdribution.nextInt())
addChild(敌人)
敌方.physicsBody=SKPhysicsBody(纹理:敌方.texture!,大小:敌方.size)
敌方.physicsBody!.categoryBitMask=CollisonType.敌方.rawValue
敌方.physicsBody!.contactTestBitMask=CollisonType.player.rawValue | CollisonType.ammo.rawValue
敌方.physicsBody!.velocity=CGVector(dx:-300,dy:0)
敌人。物理体!。角度速度=5
敌方.physicsBody!.linearDamping=0
敌人.物理体!.angularDamping=0
}
覆盖函数更新(uCurrentTime:TimeInterval){
用于子节点中的节点{
如果node.position.x<-300 | node.position.x>1300 | node.position.y<-300 | node.position.y>1000{
node.removeFromParent()节点
}
}
如果!游戏结束了吗{
分数+=1
}
}
覆盖功能触摸移动(touchs:Set,带有事件:UIEvent?){
guard let touch=touch.first else{return}
var位置=触摸位置(in:self)
如果位置y<50{
位置y=50
}否则,如果位置y>730{
位置y=730
}
player.position=位置
}
func didbegen(uu联系人:skphysiccontact){
如果contact.bodyA.node==玩家{
playerCollided(使用:contact.bodyB.node!)
}否则,如果contact.bodyB.node==播放器{
playerCollided(使用:contact.bodyA.node!)
}
如果contact.bodyA.node==弹药{
弹药碰撞(与:contact.bodyB.node!)
}否则,如果contact.bodyB.node==弹药{
弹药碰撞(与:contact.bodyA.node!)
}
}
func playerCollided(带节点:SKNode){
如果node.name==“敌人”{
让explosion=SKEmitterNode(文件名为:“explosion”)!
爆炸位置=敌人位置
addChild(爆炸)
player.removeFromParent()
敌人。从父对象中移除()
isGameOver=true
}
}
func弹药碰撞(与节点:SKNode){
如果node.name==“敌人”{
让explosion=SKEmitterNode(文件名为:“explosion”)!
爆炸位置=敌人位置
addChild(爆炸)
ammo.removeFromParent()
敌人。从父对象中移除()
}
}
}

尝试类似的方法,重构冲突的代码
func didBegin(_ contact: SKPhysicsContact) {

        if contact.bodyA.node.name == "player1" {
            playerCollided(with: contact.bodyB.node!)
        } else if contact.node.name == "player1" {
            playerCollided(with: contact.bodyA.node!)
        }

        if contact.bodyA.node.name == "ammo" {
            ammoCollided(with: contact.bodyB.node!)
        } else if contact.node.name == "ammo" {
            ammoCollided(with: contact.bodyA.node!)
        }

    }