检测Swift中两个对象之间的碰撞

碰撞检测在Swift中非常简单 – 但是在这个特定的项目中,碰撞并没有像往常那样触发didBeginContact事件。

这是我的两个身体碰撞清单(使用士兵和子弹):

  1. SKPhysicsContactDelegate添加到类中。
  2. 正确设置physicsWorld,通常是: self.physicsWorld.contactDelegate = self
  3. 为每组节点创build类别。 例如let bulletCategory = 0x1 << 0
  4. 为每个子弹和士兵创buildSKNodes。
  5. 给每个子弹和士兵一个形状匹配的物理机构。
  6. 将每个子弹的categoryBitMask设置为bulletCategory (士兵被设置为士兵类别)。
  7. 将每个子弹的contactBitMask设置为士兵soldierCategory (士兵设置为bulletCategory)。
  8. 定义didBeginContact()处理程序。

以下是我的完整代码。 这是一个至less20行的“Hello World”碰撞。

如果你创build一个新的“游戏”并将其粘贴到GameScene.swift中,它将运行,只是不会触发碰撞事件。

 // // GameScene.swift // Thesoldier // // Created by Donald Pinkus on 12/19/14. // Copyright (c) 2014 Don Pinkus. All rights reserved. // import SpriteKit class GameScene: SKScene, SKPhysicsContactDelegate { var soldier = SKShapeNode(circleOfRadius: 40) let soldierCategory:UInt32 = 0x1 << 0; let bulletCategory:UInt32 = 0x1 << 1; override func didMoveToView(view: SKView) { self.physicsWorld.contactDelegate = self // THE soldier soldier.fillColor = SKColor.redColor() soldier.position = CGPoint(x: CGRectGetMidX(self.frame), y: 40) soldier.physicsBody = SKPhysicsBody(circleOfRadius: 20) soldier.physicsBody!.dynamic = false soldier.physicsBody!.categoryBitMask = soldierCategory soldier.physicsBody!.contactTestBitMask = bulletCategory soldier.physicsBody!.collisionBitMask = 0 // bulletS var timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("makeBullet"), userInfo: nil, repeats: true) self.addChild(soldier) } func makeBullet() { var bullet = SKShapeNode(rect: CGRect(x: CGRectGetMidX(self.frame), y: self.frame.height, width: 10, height: 40), cornerRadius: CGFloat(0)) bullet.fillColor = SKColor.redColor() bullet.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: 10, height: 40)) bullet.physicsBody?.dynamic = false bullet.physicsBody?.categoryBitMask = bulletCategory bullet.physicsBody?.contactTestBitMask = soldierCategory bullet.physicsBody?.collisionBitMask = soldierCategory var movebullet = SKAction.moveByX(0, y: CGFloat(-400), duration: 1) var movebulletForever = SKAction.repeatActionForever(movebullet) bullet.runAction(movebulletForever) self.addChild(bullet) } func didBeginContact(contact: SKPhysicsContact) { println("CONTACT") } override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { /* Called when a touch begins */ } override func update(currentTime: CFTimeInterval) { /* Called before each frame is rendered */ } } 

以下是您的清单中缺less的一些项目:

  1. 其中一个物理实体必须是dynamic的
  2. 物理实体必须通过力量/冲动或设置速度来移动
  3. 物理体的位置应该匹配它们相应的精灵/形状节点

对于(2),你正在移动每一颗子弹,通过SKAction随着时间的推移改变它的位置。

对于(3),每个子弹的位置从(0,0)开始,而形状在场景的顶部中心绘制。 由于物理体是以形状节点为中心的,所以形状与物理体的位置是不一致的, 子弹的物理身体永远不会与士兵接触。 要解决这个问题,请尝试

  var bullet = SKShapeNode(rectOfSize: CGSizeMake(10, 40)) bullet.position = CGPointMake(self.size.width/2.0, self.size.height) 

另外,士兵的物理身体是其半径的一半。