当前位置: 首页 > 知识库问答 >
问题:

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

傅和璧
2023-03-14

我正在尝试创建一个用 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个答案

武琛
2023-03-14

尝试这样的方法,重构您的___Collided代码以进行调整。

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

获取本教程中的categoryBitMaskhttps://www . raywenderlich . com/145318/sprite kit-swift-3-教程-初学者

或者试试这个;

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

    }
 类似资料:
  • 我已经和LWJGL一起开发这个游戏几个星期了。自从我增加了跳跃的能力后,向上的碰撞给我带来了很多问题。 这个游戏是一个基于2D瓷砖的侧翻游戏。总的来说,除了玩家跳跃时,碰撞几乎是完美的。起初我想“哦,也许我只需要改变跳跃机制”,但后来我意识到只有当玩家通过某个x坐标时才会发生这种情况。 现在,对于实际问题本身:如果玩家在传递某个x坐标时跳转,他们将通过平铺,并测试顶部碰撞返回false。 这是整个

  • 现在我的代码有2个随机外星人射出1颗子弹,但我希望这个循环,这样当子弹离开屏幕时,它会循环2个随机外星人射出子弹,以此类推。 http://pastebin.com/RhXp2zss 外星子弹的类称为类空间内的外星子弹入侵者应该有外星子弹的精灵组,我需要在函数更新中包含循环子弹效果在空间入侵者下

  • 我正在做一个2d平板游戏。到目前为止,我已经做了一些事情。我正在使用libgdx的矩形进行基本的碰撞检测,所以考虑到我现在只有草块,我用Java制作了一个单块世界(文件读取器还没有准备好),问题是我的检测只在第一次工作,换句话说,如果我产生碰撞到一个块,它会检测到碰撞并这样做。虽然如果我在没有碰撞的情况下,让我的球员在方块顶部出现,球员将永远摔倒。 这是代码=

  • 在get_hit=pyGame.sprite的第82行,我检查sprite碰撞的移动时,它会给出错误提示:“:File”c:\Users\pc\VS_PYTHON_PY\pyGame.PY“。”。spritecollide(Player,敌方,True)文件“C:\python py\lib\site packages\pygame\sprite.py”,第1682行,位于spritecrolli

  • 问题内容: 我正在打乒乓球,发现很难编写一种算法来正确地使球从四壁弹回(我将在稍后处理得分,因为只有西+东双方会成为进球)。所以此刻,我希望球在盒子周围弹跳。 检测球是否撞到墙壁很容易,但是我在计算新角度时遇到了麻烦。 到目前为止,这是我想出的: 这仅适用于大约一半的碰撞,并且看起来非常难看。我确信这应该非常简单,并且之前已经做过很多次了。 在我的代码中,dstX / dstY是X / Y目标坐标

  • 我正在开发一个物理游戏,遇到了一个奇怪的bug:有时,在发射大量子弹后,碰撞检测开始失败。 从下面的GIF可以看出,碰撞只在半个平台上起作用,很奇怪。此外,启用了Box2D调试渲染器,还可以看到平台是一个单体。 下面是我如何让这个bug发生的,因为它只有在发射了很多子弹后才会发生(开始时一切都很好): 注意: - 子弹的场设置为 - 我将玩家的场设置为 ,没有区别 - 玩家是 1 米乘 1 米 -