检测Swift中两个对象之间的碰撞
碰撞检测在Swift中非常简单 – 但是在这个特定的项目中,碰撞并没有像往常那样触发didBeginContact
事件。
这是我的两个身体碰撞清单(使用士兵和子弹):
- 将
SKPhysicsContactDelegate
添加到类中。 - 正确设置physicsWorld,通常是:
self.physicsWorld.contactDelegate = self
- 为每组节点创build类别。 例如
let bulletCategory = 0x1 << 0
- 为每个子弹和士兵创buildSKNodes。
- 给每个子弹和士兵一个形状匹配的物理机构。
- 将每个子弹的categoryBitMask设置为
bulletCategory
(士兵被设置为士兵类别)。 - 将每个子弹的contactBitMask设置为士兵
soldierCategory
(士兵设置为bulletCategory)。 - 定义
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的一些项目:
- 其中一个物理实体必须是dynamic的
物理实体必须通过力量/冲动或设置速度来移动- 物理体的位置应该匹配它们相应的精灵/形状节点
对于(2),你正在移动每一颗子弹,通过SKAction
随着时间的推移改变它的位置。
对于(3),每个子弹的位置从(0,0)开始,而形状在场景的顶部中心绘制。 由于物理体是以形状节点为中心的,所以形状与物理体的位置是不一致的, 子弹的物理身体永远不会与士兵接触。 要解决这个问题,请尝试
var bullet = SKShapeNode(rectOfSize: CGSizeMake(10, 40)) bullet.position = CGPointMake(self.size.width/2.0, self.size.height)
另外,士兵的物理身体是其半径的一半。