我有一个对象保持在两个栏之间。我设置了碰撞,但是当我与顶部或底部杆接触时我没有得到打印消息“我们有联系”,我不知道为什么?我认为这可能与边界物理学有关。下图是给出条形图的示例,其中对象保留在它们之间。
var gameOver = false
override func didMoveToView(view: SKView) {
scene?.scaleMode = SKSceneScaleMode.AspectFill
self.physicsWorld.gravity = CGVectorMake(0.0, 2.0)
physicsWorld.contactDelegate = self
object = SKSpriteNode( imageNamed: "object")
object.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
object.physicsBody = SKPhysicsBody(circleOfRadius: object.size.width / 0.32)
object.physicsBody?.dynamic = true
object.physicsBody?.allowsRotation = true
self.addChild(object)
object.zPosition = 2
struct ColliderType {
static let object: UInt32 = 0x1 << 0
static let boundary: UInt32 = 0x1 << 1
}
let boundary = SKPhysicsBody(edgeLoopFromRect: CGRect(x: 253, y: 138, width:515, height:354))
self.physicsBody = boundary
self.physicsBody?.friction = 0
let push = CGVectorMake(10, 10)
object.physicsBody?.applyImpulse(push)
object.physicsBody?.categoryBitMask = ColliderType.object
object.physicsBody?.contactTestBitMask = ColliderType.boundary
object.physicsBody?.collisionBitMask = ColliderType.boundary
boundary.contactTestBitMask = ColliderType.object
boundary.categoryBitMask = ColliderType.boundary
boundary.collisionBitMask = ColliderType.object
func didBeginContact(contact:SKPhysicsContact) {
print("We have Contact")
gameOver = true
self.speed = 0
}
答案 0 :(得分:2)
在提出问题之前尝试浏览网页和stackoverflow,因为网上有很多教程甚至堆栈溢出。这个问题甚至可能会被关闭,因为碰撞检测是SpriteKit的基础知识之一,并且在SO上已被问到很多。
无论如何,您的代码中存在一些错误/遗漏,所以我们来看看。
1)您需要在场景“didMoveToView”方法中设置物理世界联系委托,以便它实际上正在侦听联系人。这是人们,包括我在内的第一件事,忘记并且不知道为什么没有什么工作。
physicsWorld.contactDelegate = self
2)你也没有给你的精灵一个物理实体
object.physicsBody = SKPhysicsBody(...)
你必须先给它们一个物理体,然后设置一些属性,比如contactTestBitMasks等。
3)尝试使用?代替 !在处理选项时避免零崩溃。尽管你知道它不是零,但要尽量做到这一点。所以说
...physicsBody?.contactTestBitMask...
而不是
...physicsBody!.contactTestBitMask...
你有时会这样做,有时候不这样做。
在你当前的代码中,你可能会崩溃,因为对象没有物理实体,但你强行解开它,基本上告诉它它确实有一个物理主体,这很危险。
例如,代码中的那行不应该起作用
object.physicsBody?.applyImpulse(push)
因为物体上没有物理体,但因为它不是力展开(?)没有任何反应。尝试使用!更改该行!而你应该崩溃。 所以总是使用?处理选项时以及编译器允许的时候。
该行也应该在你之前没有设置对象精灵之后。
4)尝试以不同的方式编写您的物理类别,添加更多类别时,您的方式会很快变得混乱,因为您不能只增加最后一个数字。所以在你的例子中,下一个对撞机类型必须是4,8,16等。
请尝试此操作,只需将最后一个数字递增1。
struct ColliderType {
static let object: UInt32 = 0x1 << 0
static let boundary: UInt32 = 0x1 << 1
....
}
比这样使用
...contactTestBitMask = ColliderType.object
...
您的整个代码应该如下所示
struct ColliderType {
static let object: UInt32 = 0x1 << 0
static let boundary: UInt32 = 0x1 << 1
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var gameOver = false
var object: SKSpriteNode!
override func didMoveToView(view: SKView) {
scene?.scaleMode = SKSceneScaleMode.AspectFill
self.physicsWorld.gravity = CGVectorMake(0.0, 2.0)
physicsWorld.contactDelegate = self
object = SKSpriteNode( imageNamed: "Spaceship")
object.zPosition = 2
object.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
object.physicsBody = SKPhysicsBody(circleOfRadius: object.size.width / 0.32)
object.physicsBody?.dynamic = true
object.physicsBody?.allowsRotation = true
object.physicsBody?.categoryBitMask = ColliderType.object
object.physicsBody?.contactTestBitMask = ColliderType.boundary
object.physicsBody?.collisionBitMask = ColliderType.boundary
self.addChild(object)
let boundary = SKPhysicsBody(edgeLoopFromRect: CGRect(x: 253, y: 138, width:515, height:354))
self.physicsBody = boundary
self.physicsBody?.friction = 0
boundary.contactTestBitMask = ColliderType.object
boundary.categoryBitMask = ColliderType.boundary
boundary.collisionBitMask = ColliderType.object
let push = CGVectorMake(10, 10)
object.physicsBody?.applyImpulse(push)
}
func didBeginContact(contact:SKPhysicsContact) {
print("We have Contact")
gameOver = true
self.speed = 0
}
}
希望这有帮助
答案 1 :(得分:0)
您必须确保两个碰撞形状位于同一碰撞空间中,如果它们不在同一空间中,则永远不会调用碰撞检测算法。关于Seed12的注释,这两个对象不需要是一个刚体(physicsBody)来检查它们之间是否存在碰撞。