【问题标题】:How to correctly set up collisions in spritekite Swift?如何在 spritekit Swift 中正确设置碰撞?
【发布时间】:2018-08-03 15:26:15
【问题描述】:

我正在创建一个游戏,其中球在顶部产生,然后在它们掉下来并从地面反弹(这可行),我现在正在处理碰撞,我的子弹击中球并弹开。如果您需要任何其他代码,我会发布它。 (已编辑)

import Foundation
import SpriteKit

已移至视图

struct PhysicsCategory {
    static let none: UInt32 = 0b0
    static let player: UInt32 = 0b1
    static let ball: UInt32 = 0b10
    static let bullet: UInt32 = 0b100
    static let ground: UInt32 = 0b1000
}

class GameScene: SKScene, SKPhysicsContactDelegate {


override func didMove(to view: SKView) {
    self.physicsWorld.contactDelegate = self
    let sceneBody = SKPhysicsBody(edgeLoopFrom: self.frame)
    sceneBody.friction = 0
    self.physicsBody = sceneBody
    player.position = CGPoint(x: self.size.width/2, y: self.size.height / 8)
    var timer = Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(spawnBullet), userInfo: nil, repeats: true)
    player.size = CGSize(width: 100, height: 100)
    player.physicsBody = SKPhysicsBody(circleOfRadius: player.size.width/2)
    player.physicsBody?.affectedByGravity = false
    player.physicsBody?.isDynamic = true

    ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.width/2)
    ball.physicsBody?.restitution = 1
    ball.physicsBody?.linearDamping = 0


    bullet.size = CGSize(width: 30, height: 30)
    bullet.zPosition = -5
    bullet.position = CGPoint(x: player.position.x, y: player.position.y)
    let action = SKAction.moveTo(y: self.size.height + 30, duration: 1.0)
    bullet.run(SKAction.repeatForever(action))
    bullet.physicsBody = SKPhysicsBody(circleOfRadius: bullet.size.width/2)
    bullet.name = "bullet"
    player.physicsBody?.categoryBitMask = PhysicsCategory.player
    player.physicsBody?.collisionBitMask = PhysicsCategory.none
    player.physicsBody?.contactTestBitMask = PhysicsCategory.ball

    bullet.physicsBody?.categoryBitMask = PhysicsCategory.bullet
    bullet.physicsBody?.collisionBitMask = PhysicsCategory.none
    bullet.physicsBody?.contactTestBitMask = PhysicsCategory.ball


    ball.physicsBody?.categoryBitMask = PhysicsCategory.ball
    ball.physicsBody?.contactTestBitMask = PhysicsCategory.bullet
    ball.physicsBody?.collisionBitMask = PhysicsCategory.ground

    ground.physicsBody?.categoryBitMask = PhysicsCategory.ground
    ground.physicsBody?.collisionBitMask = PhysicsCategory.ball
    ground.physicsBody?.contactTestBitMask = PhysicsCategory.none
    player.name = "player"
    addChild(player)
    ballSpawner(delay: 2.0)
    spawnGround()
}
//didBegin function
func didBegin(_ contact: SKPhysicsContact) {
   // print("didBeginContact entered for \(String(describing: contact.bodyA.node!.name)) and \(String(describing: contact.bodyB.node!.name))")
    let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

我认为这部分是错误的 我的情况对吗?因为当我尝试写一个子弹和球时,它给了我一个错误 - “二元运算符'|'不能应用于两个 'SKSpriteNode' 操作数”。所以只调用默认情况。

    switch contactMask {
  //This case never gets called, i can't see it in the console when i run it
    case PhysicsCategory.bullet | PhysicsCategory.ball:
        let bullet = contact.bodyA.categoryBitMask == 
PhysicsCategory.bullet ? contact.bodyA.node : contact.bodyB.node
        let ball = contact.bodyA.categoryBitMask == 
PhysicsCategory.ball ? contact.bodyA.node : contact.bodyB.node
        collisionBulletAndBall(ball: (ball)!, bullet: (bullet)!)
        print("bullet and ball have contacted.")
    case PhysicsCategory.bullet:
        print("bullet contact")
    case PhysicsCategory.ball & PhysicsCategory.bullet:
        print("collision ball with bullet")
    default:
        print("Some other contact occurred")
    }
}

func gameOver() {
    print("game over")
}

func collisionBulletAndBall(ball: SKNode, bullet: SKNode) {

    ball.removeFromParent()
    bullet.removeFromParent()
    print("collision")
}
 @objc func spawnBullet() {
    var bullet = SKSpriteNode(imageNamed: "bullet")
    bullet.size = CGSize(width: 30, height: 30)
    bullet.zPosition = -5
    bullet.position = CGPoint(x: player.position.x, y: player.position.y)
    let action = SKAction.moveTo(y: self.size.height + 30, duration: 1.0)
    bullet.run(SKAction.repeatForever(action))
    bullet.name = "bullet"
    self.addChild(bullet)
    bullets.append(bullet)
}
 func spawnScoreBall() {
    var ballSize = CGSize(width: 30, height: 30)
    //Random Size
    let randomSize = arc4random() % 3
    switch randomSize {
    case 1:
        ballSize.width *= 1.2
        ballSize.height *= 1.2
    case 2:
        ballSize.width *= 1.5
        ballSize.height *= 1.5
    default:
        break
    }
    var ball = SKSpriteNode(imageNamed: "ball")
    ball.size = ballSize
    let y = size.height-ballSize.height/2
    //Random x
    var randomX = CGFloat(arc4random() % UInt32(size.width - ballSize.width))
    randomX -= size.width/2-ballSize.width*4
    ball.position = CGPoint(x: randomX, y: y)
    //Moving logic
    //        let moveDownAction = SKAction.moveBy(x: 0, y: -size.height + ball.size.height, duration: 2.0)
    //        let destroyAction = SKAction.removeFromParent()
    //        let sequenceAction = SKAction.sequence([moveDownAction, destroyAction])
    //        ball.run(sequenceAction)
    //Rotation
    var rotateAction = SKAction.rotate(byAngle: 1, duration: 1)
    let randomRotation = arc4random() % 2
    if randomRotation == 1 {
        rotateAction = SKAction.rotate(byAngle: -1, duration: 1)
    }
    let repeatForeverAction = SKAction.repeatForever(rotateAction)
    ball.run(repeatForeverAction)
    ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.width/2)
    ball.physicsBody?.affectedByGravity = true
    ball.physicsBody?.restitution = 1
    ball.physicsBody?.linearDamping = 0
    ball.zPosition = 3
    blocks.append(ball)
    self.addChild(ball)
}

生成地面行动

func spawnGround() {
    ground = SKSpriteNode(color: UIColor.white, size: CGSize(width: self.frame.size.width, height: 50))
    ground.position = CGPoint(x: self.size.width/2, y: 0)
 }

【问题讨论】:

  • 这对你来说太多了,以至于你无法抛出并期望有人能够发现错误。你做了什么来调试这个?碰撞如何“不起作用”?
  • 我只是想正确设置它们,我是 swift 和 spritkit 的新手。当子弹与球相撞时,它只是推动它并上升,球改变方向。我认为我的 didbegin 函数有问题
  • 我不想告诉你这个,但我不认为 StackOverflow 现在可能能够帮助你。该站点旨在成为特定编程问题的百科全书资源。现在,你的问题太大太模糊了。花一些时间调试它并阅读swiftsprite-kit 的教程,然后在您对您的问题有更多了解并提出具体 问题时再回来。祝你好运!

标签: swift sprite-kit


【解决方案1】:

playerbullet 似乎没有物理实体(没有 player.physicsBody = SKPhysicsBody... 和 bullet.physicsBody = SKPhysicsBody...

在分配物理体属性后方式分配球体的物理体:

ball.physicsBody?.categoryBitMask = PhysicsCategory.ball
    ball.physicsBody?.contactTestBitMask = PhysicsCategory.bullet | PhysicsCategory.ground | PhysicsCategory.player
    ball.physicsBody?.collisionBitMask = PhysicsCategory.bullet | PhysicsCategory.ground | PhysicsCategory.player

后来

ball.physicsBody = SKPhysicsBody...

所以所有那些ball.physicsBody 分配什么都没做,因为physicsBody? 是'nil'

编辑:您的didBegin 看起来有点乱。试试这个:

func didBegin(_ contact: SKPhysicsContact) {
   print("didBeginContact entered for \(String(describing: contact.bodyA.node!.name)) and \(String(describing: contact.bodyB.node!.name))")
   let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

   switch contactMask {
   case PhysicsCategory.bullet | PhysicsCategory.ball:
      let bullet = contact.bodyA.categoryBitMask == bullet ? contact.bodyA.node : contact.bodyB.node
      let ball = contact.bodyA.categoryBitMask == ball ? contact.bodyA.node : contact.bodyB.node
      ball.removeFromParent()
      bullet.removeFromParent()
      print("bullet and ball have contacted.")
   default:
      print("Some other contact occurred")
 }

我删除了球的物理体的 isDynamicaffectedByGravity 属性的设置,因为您正在删除它。

【讨论】:

  • 在给出需要解决可选选项的错误时,XCode 默认插入? 而不是!,这很可惜
  • @DanielKrupenin “因为当我尝试写子弹和球时”你是什么意思? "二元运算符'|'不能应用于两个 'SKSpriteNode' 操作数”你是不是在反对 case PhysicsCategory.bullet | PhysicsCategory.ball: 行?我看不到您使用 `` 和 2 个 SKSpriteNodes 的任何代码,还是您正在尝试编写此代码?
  • bulletball 之间的合同有 2 个案例 - 您只需要第一个:case PhysicsCategory.bullet | PhysicsCategory.ball:。 .这涵盖了子弹和球的接触。删除第二个case PhysicsCategory.ball & PhysicsCategory.bullet:。还要检查您的 cmets/print 语句 - 联系人不是冲突。这可能看起来很迂腐,但这是错误的术语。还有case PhysicsCategory.bullet: 在检查什么 - 只有当子弹接触到子弹时才会触发。
  • 这里是如何使用各种位掩码的指南; stackoverflow.com/a/40596890/1430420
  • "二元运算符'|'不能应用于两个 'SKSpriteNode' 操作数” - 当我只写球时出现此错误 |子弹但不是 PhysicsCategory.ball | PhysicsCategory.bullet
猜你喜欢
  • 2017-10-07
  • 2020-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多