【问题标题】:Swift 3 Space Shooting Game: Issue with bullet collisionSwift 3 太空射击游戏:子弹碰撞问题
【发布时间】:2017-04-05 02:35:45
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

    尝试类似的方法,并重构您的 ___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!)
            }
    
        }
    

    【讨论】:

    • 我尝试了您的建议,但仍然无法完全正常工作。碰撞后只有 3/4 的子弹消失了(有些仍然弹跳),还有玩家。但敌人永远不会消失。也不会发生爆炸。爆炸仅偶尔发生在 iPad 的右侧(超出玩家可见范围)。我将尝试按照您提供的教程链接进行操作。谢谢。
    • 我按照教程链接解决了我的问题。再次感谢@eSpecialized!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多