斯威夫特3太空射击游戏:子弹碰撞问题

时间:2016-11-21 16:13:17

标签: swift sprite-kit swift3 collision-detection collision

enter image description here

我正在尝试创建一个用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()
        }
    }
}

1 个答案:

答案 0 :(得分:0)

尝试这样的事情,然后重构你的___Collided代码进行调整。

不要测试节点相等性。使用名称或.categoryBitMask来确定它是什么类型的节点。

在本教程中获取categoryBitMask; https://www.raywenderlich.com/145318/spritekit-swift-3-tutorial-beginners

或试试这个;

player.name =“player1”

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!)
        }

    }