我一边学习SpriteKit(使用Ray Wenderlich等人的iOS Games by Tutorials),一边基于Breakout创建了一个非常简单的测试游戏,以查看我是否能够应用所学的概念。我决定通过使用.sks文件创建精灵节点并将手动边界检查和碰撞替换为物理体来简化代码。
然而,每当球以陡峭的角度与墙壁/其他矩形碰撞时,它就会沿着它们平行地滑动(即仅向上和向下滑动)。以下是相关代码 - 我已经将物理体属性移入代码中以使其更可见:
import SpriteKit
struct PhysicsCategory {
static let None: UInt32 = 0 // 0
static let Edge: UInt32 = 0b1 // 1
static let Paddle: UInt32 = 0b10 // 2
static let Ball: UInt32 = 0b100 // 4
}
var paddle: SKSpriteNode!
var ball: SKSpriteNode!
class GameScene: SKScene, SKPhysicsContactDelegate {
override func didMoveToView(view: SKView) {
physicsWorld.gravity = CGVector.zeroVector
let edge = SKNode()
edge.physicsBody = SKPhysicsBody(edgeLoopFromRect: frame)
edge.physicsBody!.usesPreciseCollisionDetection = true
edge.physicsBody!.categoryBitMask = PhysicsCategory.Edge
edge.physicsBody!.friction = 0
edge.physicsBody!.restitution = 1
edge.physicsBody!.angularDamping = 0
edge.physicsBody!.linearDamping = 0
edge.physicsBody!.dynamic = false
addChild(edge)
ball = childNodeWithName("ball") as SKSpriteNode
ball.physicsBody = SKPhysicsBody(rectangleOfSize: ball.size))
ball.physicsBody!.usesPreciseCollisionDetection = true
ball.physicsBody!.categoryBitMask = PhysicsCategory.Ball
ball.physicsBody!.collisionBitMask = PhysicsCategory.Edge | PhysicsCategory.Paddle
ball.physicsBody!.allowsRotation = false
ball.physicsBody!.friction = 0
ball.physicsBody!.restitution = 1
ball.physicsBody!.angularDamping = 0
ball.physicsBody!.linearDamping = 0
physicsWorld.contactDelegate = self
}
之前忘记提到了,但我添加了一个简单的touchesBegan函数来调试弹跳 - 它只是将速度调整为指向触摸点的球:
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
let touch = touches.anyObject() as UITouch
let moveToward = touch.locationInNode(self)
let targetVector = (moveToward - ball.position).normalized() * 300.0
ball.physicsBody!.velocity = CGVector(point: targetVector)
}
normalized()函数将球/触摸位置差减小到一个单位向量,minus操作符被重写以允许CGPoint相减。
球/边缘碰撞应该总是以完全相反的角度反射球,但由于某些原因,球似乎真的很喜欢直角。我当然可以实现一些解决方案来手动反射球的角度,但关键是我想使用SpriteKit内置的物理功能来完成所有这些操作。有什么明显的问题我忽略了吗?