问题
So I have adjusted my games ball type from a shape to an image which forced me to redo the physics of my game. I am new to swift and have struggled with fixing my collisions in my swift game.
class GameScene: SKScene, GameDelegate, SKPhysicsContactDelegate {
var ball: Ball!
let ballSpeedX = CGFloat(500)
//ball = Ball(imageNamed:"colorBall.png")
enum CollisionTypes: UInt32 {
case Floor = 1
case Ball = 2
}
// board
let boards = Boards.make(CollideType.BoardStart.rawValue)
var lastBoard: SKNode?
var boardSpeedY: CGFloat { get { return CGFloat(160) * accelerate }}
let boardDistanceY = CGFloat(300)
let boardYDistanceHide = CGFloat(30)
override func didMoveToView(view: SKView) {
self.physicsWorld.gravity = CGVectorMake(0, 0)
self.physicsWorld.contactDelegate = self
let flooeBody = SKPhysicsBody.init(edgeLoopFromRect: self.frame)
self.physicsBody = floorBody
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
ball.hidden = false
self.addChild(ball)
// scene
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody!.categoryBitMask = CollideType.Scene.toMask()
self.physicsBody!.dynamic = false
self.physicsBody!.friction = 0
// ceil
let ceil = SKShapeNode(rectOfSize: CGSize(width: self.frame.width, height: 2))
ceil.position.x = CGRectGetMidX(self.frame)
ceil.position.y = self.frame.height - CGRectGetMidY(ceil.frame)
ceil.physicsBody = SKPhysicsBody(rectangleOfSize: ceil.frame.size)
ceil.physicsBody!.categoryBitMask = CollideType.Ceil.toMask()
ceil.physicsBody!.dynamic = false
ceil.alpha = 0
self.addChild(ceil)
// floor
let floor = SKShapeNode(rectOfSize: CGSize(width: self.frame.width, height: 2))
floor.position.x = CGRectGetMidX(self.frame)
floor.position.y = CGRectGetMidY(floor.frame)
floor.physicsBody = SKPhysicsBody(rectangleOfSize: floor.frame.size)
//floor.physicsBody!.categoryBitMask = CollideType.Floor.toMask() two
floor.physicsBody!.dynamic = false
floor.alpha = 0
self.addChild(floor)
}
That is the scene and physics I attempted to set up and was directed with. Below is the collide errors which cause the app to crash upon touch.
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 error: CANNOT CONVERT VALUE OF TYPE BOOL TO EXPCTD ARG TYPE UIINT32
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 => ERROR
else if bitMaskAAndB == CollideType.toMask([.Ball, .Ceil]) {
stopGame()
}
// ball and floor => stop game
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)
}
}
CollideType
definition as below:
enum CollideType: Int {
case Scene = 0
case Ceil = 1
case Floor = 2
case Ball = 3
case BoardStart = 4
func toMask()-> UInt32 {
return UInt32(1 << self.rawValue)
}
static func toMask(masks: [CollideType])-> UInt32 {
var toMask = UInt32(0)
for type in masks {
toMask |= type.toMask()
}
return toMask
}
回答1:
So the issue now is that you have two definition for your masks:
Remove this one:
enum CollisionTypes: UInt32 {
case Floor = 1
case Ball = 2
}
Use only this one:
enum CollideType: Int {
case Scene = 0
case Ceil = 1
case Floor = 2
case Ball = 3
case BoardStart = 4
func toMask()-> UInt32 {
return UInt32(1 << self.rawValue)
}
static func toMask(masks: [CollideType])-> UInt32 {
var toMask = UInt32(0)
for type in masks {
toMask |= type.toMask()
}
return toMask
}
Correct all code to match with CollideType
definitions.
Correct this line in didBeginContact
:
let bitMaskAAndB = contact.bodyA.categoryBitMask == CollisionTypes.Floor.rawValue && contact.bodyB.categoryBitMask == CollisionTypes.Ball.rawValue
with:
let bitMaskAAndB = contact.bodyA.categoryBitMask == CollideType.Floor.toMask() ? contact.bodyB.categoryBitMask : CollideType.Ball.toMask()
If you have correct all you will don't have yet this error:
// ball and ceil => ERROR
来源:https://stackoverflow.com/questions/38289783/collide-type-source-error-spritekit-swift-game