2016-09-20 49 views
4

这是我在堆栈上发布的第一个问题。我正在使用Xcode 7.3.1,iOS 9.3和Swift 2.还在模拟器和iPad上直接进行了测试。我做了大量搜索,阅读了2本Spritekit物理书,并观看了许多视频教程以及书面教程。我写过身体物理学,之前没有任何问题,而且有许多次小型项目,但这只是给我没有任何反馈。这个问题之前已经在特定情况下提出过,即2次碰撞具有相同的spritenode,或者collisionBitMask和contactTestBitMask有什么区别。我意识到这些差异,并意识到您希望与之联系的每个对象都需要一个categoryBitMask。 首先,我分配了一个全局的Physicsbody结构体(尝试了直接二进制bitMask和相应的Int32,每个都没有成功),一个物理代理和每个SKSpritenode与它的配对联系人对应。我已经尝试了很多方法来实现didBeginContact(关于它的结构),但没有一个在其他方面有所作为。
早些时候我提到了反馈。我已经消除了除主要玩家,子弹,新敌人和敌人之外的所有敌人。当我试图甚至将接触或碰撞的结果打印到控制台时,就好像它甚至没有被读取。我没有得到任何活动。这些spritenodes都在一个类(GameScene)内,我已经尝试了每个功能spritenode单独的类没有运气。而且,对于不同的类,它似乎会让事情变得更糟,即使使用了用于在类和子类之间进行通信的协议。尽管我知道这是首选的方式,但使用单独的类对我来说仍然是新的。我将只显示我认为可能需要减少的代码,但让我知道是否还有其他需要查看的代码。我只想让子弹击中飞机,我可以从那里飞到我的其他物体。我的物理联系人没有联系SpriteKit

import AVFoundation 
import SpriteKit 
import GameKit 

// Binary connections for collision and colliding 
struct PhysicsCategory { 
    static let GroundMask : UInt32 = 1 //0x1 << 0 
    static let BulletMask : UInt32 = 2 //0x1 << 1 
    static let PlayerMask : UInt32 = 4 //0x1 << 2 
    static let EnemyMask : UInt32 = 8 //0x1 << 3 
    static let EnemyFire : UInt32 = 16 //0x1 << 4 
    static let All  : UInt32 = UInt32.max // all nodes 
} 

class GameScene: SKScene, SKPhysicsContactDelegate { 

    // Starting scene, passed to didMoveToView 
    func startScene() { 

     // Sets the physics delegate and physics body 
     view?.showsPhysics = true 
     self.physicsWorld.gravity = CGVectorMake(0, 0) 
     self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame) 
     self.physicsWorld.contactDelegate = self // Physics delegate set 
    } 

    func setupPlayer() { 

     player = SKScene(fileNamed: "Player")!.childNodeWithName("player")! as! SKSpriteNode 

     // Body physics for player's planes 
     player.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "MyFokker2.png"), size: player.size) 
     player.physicsBody?.dynamic = false 
     player.physicsBody?.usesPreciseCollisionDetection = true 
     player.physicsBody?.categoryBitMask = PhysicsCategory.PlayerMask 
     player.physicsBody?.contactTestBitMask = PhysicsCategory.EnemyFire 
     player.physicsBody?.collisionBitMask = 0 

     player.removeFromParent() 
     self.addChild(player) // Add our player to the scene 
    } 

    // Create the ammo for our plane to fire 
    func fireBullets() { 

     bullet = SKSpriteNode(imageNamed: "fireBullet") 

     // Body physics for plane's bulets 
     bullet.physicsBody = SKPhysicsBody(rectangleOfSize: bullet.size) 
     bullet.physicsBody?.dynamic = false 
     bullet.physicsBody?.usesPreciseCollisionDetection = true 
     bullet.physicsBody?.categoryBitMask = PhysicsCategory.BulletMask 
     bullet.physicsBody?.contactTestBitMask = PhysicsCategory.EnemyMask 
     bullet.physicsBody?.collisionBitMask = 0 

     self.addChild(bullet) // Add bullet to the scene 
    } 

    func spawnEnemyPlanes() { 
     let enemy1 = SKScene(fileNamed: "Enemy1")!.childNodeWithName("enemy1")! as! SKSpriteNode 
     let enemy2 = SKScene(fileNamed: "Enemy2")!.childNodeWithName("enemy2")! as! SKSpriteNode 
     let enemy3 = SKScene(fileNamed: "Enemy3")!.childNodeWithName("enemy3")! as! SKSpriteNode 
     let enemy4 = SKScene(fileNamed: "Enemy4")!.childNodeWithName("enemy4")! as! SKSpriteNode 

     enemyPlanes = [enemy1, enemy2, enemy3, enemy4] 

     // Generate a random index 
     let randomIndex = Int(arc4random_uniform(UInt32(enemyPlanes.count))) 

     // Get a random enemy 
     newEnemy = (enemyPlanes[randomIndex]) 

     // Added randomEnemy's physics 
     newEnemy.physicsBody = SKPhysicsBody(rectangleOfSize: newEnemy.size) 
     newEnemy.physicsBody?.dynamic = false 
     newEnemy.physicsBody?.usesPreciseCollisionDetection = true 
     newEnemy.physicsBody?.categoryBitMask = PhysicsCategory.EnemyMask 
     newEnemy.physicsBody?.contactTestBitMask = PhysicsCategory.BulletMask 
     newEnemy.physicsBody?.collisionBitMask = 0 

     newEnemy.removeFromParent() 
     self.addChild(newEnemy) 
    } 

    func spawnEnemyFire() { 

     enemyFire = SKScene(fileNamed: "EnemyFire")!.childNodeWithName("bullet")! as! SKSpriteNode 

     enemyFire.removeFromParent() 
     self.addChild(enemyFire) // Generate enemy fire 

     // Added enemy's fire physics 
     enemyFire.physicsBody = SKPhysicsBody(rectangleOfSize: enemyFire.size) 
     enemyFire.physicsBody?.dynamic = false 
     enemyFire.physicsBody?.usesPreciseCollisionDetection = true 
     enemyFire.physicsBody?.categoryBitMask = PhysicsCategory.EnemyFire 
     enemyFire.physicsBody?.contactTestBitMask = PhysicsCategory.PlayerMask 
     enemyFire.physicsBody?.collisionBitMask = 0 
    } 

    func didBeginContact(contact: SKPhysicsContact) { 

     if !self.gamePaused && !self.gameOver { 

      // beginContact constants 
      firstBody = contact.bodyA 
      secondBody = contact.bodyB 

      if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) {  
       firstBody = contact.bodyA 
       secondBody = contact.bodyB 
      } else { 
       firstBody = contact.bodyB 
       secondBody = contact.bodyA 
      } 

      // Contact statements 
      if ((firstBody.categoryBitMask & PhysicsCategory.BulletMask != 0) && (secondBody.categoryBitMask & PhysicsCategory.EnemyMask != 0)) { 
       print("Bullet hit Enemy") 
      } 
      else if ((firstBody.categoryBitMask & PhysicsCategory.PlayerMask != 0) && (secondBody.categoryBitMask & PhysicsCategory.EnemyFire != 0)) { 
       print("EnemyFire hit our Player") 
      } 
     } 
    } 
} 

我试着省略了明显的代码,但留下了需要知道的代码...对不起,如果它很长。 我也试过checkPhysics函数,他们甚至不能识别我的对象。 所有SpriteNodes都被传递给didMoveToView函数。 任何人都可以看到有什么不对或有一个原因,我为什么没有联系?

+0

你在哪里调用startScene()方法?我想在didMoveToView。 didBeginContact会被触发吗?在该方法的最开始处放置一个断点或一个打印语句,以查看它是否被执行。 – Whirlwind

+0

我在didMoveToView函数中调用了我的startScene函数。我用它来重新使用游戏。它好像根本没有被触发。我将尝试打印语句作为我的didBeginContact函数的第一行。 –

+0

这是因为我相信didBeginContact甚至没有触发。物理学到位,代表到位。即使我没有设置联系人,它仍应该被触发。函数在代码中的位置是否重要?这对我来说是前所未有的。即使使用view?.showsPhysics = true,我也可以在模拟器中看到哪些对象具有物理效果。 –

回答

6

你遇到的问题是因为你所有的物理机构都是非动态的。意味着他们的动态属性设置为false。只有在至少有一个主体是动态的时才会调用方法didBeginContact

docs

动态属性确定主体是否由 物理学子系统模拟。

所以非动态的物体肯定被排除在模拟之外。我无法找到是否有某个地方记录了这适用于联系人,但根据我的经验,我非常肯定联系人不会在两个静态主体之间工作。

希望这会有所帮助。

+0

它的工作!我将所有动态属性更改为TRUE,并且所有打印到控制台都像野火一样消失了!我以为我曾尝试过,但一定是在一个不同的spritenode。我会执行一些代码给我的联系人,看看反应。你不知道我在这方面花了多少时间...谢谢你,谢谢你,谢谢! –

+0

@ABoynton没问题,很高兴听到它的工作:)在此期间,看看帮助部分,找出[你应该做什么时,有人回答你的问题](http://stackoverflow.com/help/someone-答案),并了解更多关于这个网站的工作原理。并欢迎来到StackOverflow :) – Whirlwind

+1

@Whirlwind如果我没有记错的话,如果我没有记错的话,当看着Box2D的源头,碰撞和接触运行相同的功能,接触发生在第一位,设置一些标志,然后处理碰撞代码。这是前一段时间我看了这个,所以不知道它是否改变了,或者Box2D苹果使用的是什么版本。 – Knight0fDragon