问题
So I made some adjustments to the ball in my game and to avoid an unwrapping optional value error, I commmented out the following
//didMoveToView
self.physicsWorld.gravity = CGVectorMake(0, 0)
self.physicsWorld.contactDelegate = self
let fieldBody = SKPhysicsBody.init(edgeLoopFromRect: self.frame)
self.physicsBody = fieldBody
self.physicsBody!.affectedByGravity = false
self.physicsBody!.usesPreciseCollisionDetection = true
self.physicsBody!.dynamic = true
self.physicsBody!.mass = 0
self.physicsBody!.friction = 0
self.physicsBody!.linearDamping = 0
self.physicsBody!.angularDamping = 0
self.physicsBody!.restitution = 1
self.physicsBody!.categoryBitMask = CollisionTypes.Floor.rawValue
self.physicsBody!.contactTestBitMask = CollisionTypes.Ball.rawValue
// Prepare the ball - physics engine.
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.frame.width/2)
ball.physicsBody!.affectedByGravity = true
ball.physicsBody!.restitution = 0.8
ball.physicsBody!.linearDamping = 0
ball.physicsBody!.friction = 0.3
ball.physicsBody!.dynamic = true
ball.physicsBody!.mass = 0.5
ball.physicsBody!.allowsRotation = true
ball.physicsBody!.categoryBitMask = CollisionTypes.Ball.rawValue
ball.physicsBody!.contactTestBitMask = CollisionTypes.Floor.rawValue
ball.physicsBody!.collisionBitMask = CollisionTypes.Floor.rawValue
}
I did that, my game launced but as soon as toucheBegan, the same error popped up. I do not know how to get around all of these unrwapping errors. I am new to swift and not sure how i should adjust thse physics. My contactBegin looks this:
func didBeginContact(contact: SKPhysicsContact) {
let bitMaskAAndB = contact.bodyA.categoryBitMask == CollisionTypes.Floor.rawValue &&
contact.bodyB.categoryBitMask == CollisionTypes.Ball.rawValue
let ballAndBoardMask = CollideType.Ball.toMask() | boards.usedCollideMasks
// ball and board, handle it by board delegate
if bitMaskAAndB | ballAndBoardMask == ballAndBoardMask {
let boardNode: SKNode! = contact.bodyA.categoryBitMask == CollideType.Ball.toMask() ? contact.bodyB.node : contact.bodyA.node
let board = boardNode.bind as! BoardDelegate
board.didBeginContact(boardNode, ball: ball, contact: contact, game: self)
}
// ball and ceil => stop game
else if bitMaskAAndB == CollideType.toMask([.Ball, .Ceil]) {
stopGame()
}
// ball and floor => stop game add explosion or fall off screen
else if bitMaskAAndB == CollideType.toMask([.Ball, .Floor]) {
stopGame()
}
}
func didEndContact(contact: SKPhysicsContact) {
let ballAndBoardMask = CollideType.Ball.toMask() | boards.usedCollideMasks
// ball and board, handle it by board delegate
if contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask | ballAndBoardMask == ballAndBoardMask {
let boardNode: SKNode! = contact.bodyA.categoryBitMask == CollideType.Ball.toMask() ? contact.bodyB.node : contact.bodyA.node
let board = boardNode.bind as! BoardDelegate
board.didEndContact(boardNode, ball: ball, contact: contact, game: self)
}
}
EDIT: I set up my physics world to the suggestions you made and adjusted my didBeginContact fun however with the following code, I am getting multiple errors regarding: cannot convert value of type bool to UInt32.
PS. thank you for your help and patience, this is all new terminology and Im doing my best to understand. :)
回答1:
I don't know your CollideType
class or declaration, so my code below explain to you how to build a correct physicsWorld
and physicsBody
to don't have issues during the collisions.
But first: we're going to be using the categoryBitMask, contactTestBitMask and collisionBitMask properties in their fullest for this project, because we have very precise rules that make the project work:
categoryBitMask is a number defining the type of object this is for considering collisions.
collisionBitMask is a number defining what categories of object this node should collide with.
contactTestBitMask is a number defining which collisions we want to be notified about.
SpriteKit expects these three bitmasks to be described using a UInt32
.Your bitmasks should start at 1 then double each time.
The code:
class GameScene: SKScene, SKPhysicsContactDelegate {
var ball: Ball!
let ballSpeedX = CGFloat(500)
enum CollisionTypes: UInt32 {
case Field = 1
case Ball = 2
}
override func didMoveToView(view: SKView) {
// ball
ball = Ball(imageNamed:"colorBall.png")
ball.position = CGPointMake(self.ball.frame.size.width,self.ball.frame.size.height)
// Prepare the world - physics engine.
self.physicsWorld.gravity = CGVectorMake(0, -6)
self.physicsWorld.contactDelegate = self
let fieldBody = SKPhysicsBody.init(edgeLoopFromRect: self.frame)
self.physicsBody = fieldBody
self.physicsBody!.affectedByGravity = false
self.physicsBody!.usesPreciseCollisionDetection = true
self.physicsBody!.dynamic = true
self.physicsBody!.mass = 0
self.physicsBody!.friction = 0
self.physicsBody!.linearDamping = 0
self.physicsBody!.angularDamping = 0
self.physicsBody!.restitution = 1
self.physicsBody!.categoryBitMask = CollisionTypes.Field.rawValue
self.physicsBody!.contactTestBitMask = CollisionTypes.Ball.rawValue
// Prepare the ball - physics engine.
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.frame.width/2)
ball.physicsBody!.affectedByGravity = true
ball.physicsBody!.restitution = 0.8
ball.physicsBody!.linearDamping = 0
ball.physicsBody!.friction = 0.3
ball.physicsBody!.dynamic = true
ball.physicsBody!.mass = 0.5
ball.physicsBody!.allowsRotation = true
ball.physicsBody!.categoryBitMask = CollisionTypes.Ball.rawValue
ball.physicsBody!.contactTestBitMask = CollisionTypes.Field.rawValue
ball.physicsBody!.collisionBitMask = CollisionTypes.Field.rawValue
//ball.physicsBody!.categoryBitMask = CollideType.Ball.toMask()
//ball.physicsBody!.collisionBitMask = CollideType.toMask([.Scene, .Ceil, .Floor]) | boards.usedCollideMasks
//ball.physicsBody!.contactTestBitMask = CollideType.toMask([.Scene, .Ceil, .Floor]) | boards.usedCollideMasks
ball.hidden = false
self.addChild(ball)
}
func didBeginContact(contact: SKPhysicsContact) {
if (contact.bodyA.categoryBitMask == CollisionTypes.Field.rawValue &&
contact.bodyB.categoryBitMask == CollisionTypes.Ball.rawValue) {
print("contact between field and ball")
}
}
}
As you can see, the first important thing is to prepare the physicsWorld (track the boundaries within wich your physics must work), assign it a category and all the other parameters need to interact with the other objects. Then you build the physicsBody of your object , in this case the ball.
来源:https://stackoverflow.com/questions/38280426/unwrapping-optional-values-physicsbody-swift-spritekit