这是我在堆栈上发布的第一个问题 . 我正在使用Xcode 7.3.1,iOS 9.3和Swift 2.还在模拟器和我的iPad上直接测试 . 我做了大量的搜索,阅读了2本Spritekit Physics书籍,观看了大量的视频教程以及书面教程 . 我以前写的身体物理没有问题,而且很多时候都有较小的项目,但这个只是给我没有反馈 . 这个问题之前已在特定情况下提出过,即2次与同一spritenode的碰撞或者collisionBitMask和contactTestBitMask之间的区别是什么 . 我知道这些差异并且还意识到您希望联系的每个对象都需要categoryBitMask . 首先,我已经分配了一个全局的Physicsbody结构(尝试直接二进制bitMask和相应的Int32,每个对应的Int32都没有成功),物理代表和每个SKSpritenode对应其配对的联系人 . 我已经尝试了很多方法来实现didBeginContact(关于它的结构方式),没有一种方法可以与另一方面有所区别 .
之前我提到了反馈 . 除了我的主要球员,子弹,新敌人和敌人之外,我已经淘汰了所有人 . 当我尝试将接触或碰撞的结果打印到控制台时,就好像它甚至无法读取 . 我没有活动 . 这些spritenode都在1级(GameScene)中,我已经为每个功能spritenode尝试了单独的类,没有运气 . 此外,对于单独的类,它似乎会使事情变得更糟,即使有用于在类和子类之间进行通信的协议 . 哪些使用单独的类对我来说仍然是新的,尽管我知道它是首选的方式 . 我将只展示我认为可能需要被视为最小化的代码,但如果还有其他需要被看到的话,请告诉我 . 我只是希望子弹击中飞机,我可以从那里到我的其他物体 .
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函数 . 任何人都可以看到有什么问题或有理由说我根本没有联系吗?
1 回答
您遇到的问题是因为您的所有物理实体都是非动态的 . 表示其动态属性设置为
false
. 仅当至少一个实体是动态的时,才会调用didBeginContact
方法 .来自docs:
因此,非动态物体肯定会被排除在模拟之外 . 我无法找到是否有某些文件证明这适用于联系人,但根据我的经验,我非常肯定联系人不会在两个静态机构之间工作 .
希望这可以帮助 .