import SpriteKit
class GameScene: SKScene {
var node: SKShapeNode! //The node.
let path: [CGPoint] = [CGPoint(x: 100, y: 100),CGPoint(x: 100, y: 300),CGPoint(x: 300, y: 300),CGPoint(x: 300, y: 100)] //The path of points to travel.
let repeats: Bool = true //Whether to repeat the path.
var pathIndex = 0 //The index of the current point to travel.
let pointRadius: CGFloat = 10 //How close the node must be to reach the destination point.
let travelSpeed: CGFloat = 200 //Speed the node will travel at.
let rate: CGFloat = 0.5 //Motion smoothing.
override func didMoveToView(view: SKView) {
node = SKShapeNode(circleOfRadius: 10)
node.physicsBody = SKPhysicsBody(circleOfRadius: 10)
node.physicsBody!.affectedByGravity = false
self.addChild(node)
}
final func didReachPoint() {
//We reached a point!
pathIndex++
if pathIndex >= path.count && repeats {
pathIndex = 0
}
}
override func update(currentTime: NSTimeInterval) {
if pathIndex >= 0 && pathIndex < path.count {
let destination = path[pathIndex]
let displacement = CGVector(dx: destination.x-node.position.x, dy: destination.y-node.position.y)
let radius = sqrt(displacement.dx*displacement.dx+displacement.dy*displacement.dy)
let normal = CGVector(dx: displacement.dx/radius, dy: displacement.dy/radius)
let impulse = CGVector(dx: normal.dx*travelSpeed, dy: normal.dy*travelSpeed)
let relativeVelocity = CGVector(dx:impulse.dx-node.physicsBody!.velocity.dx, dy:impulse.dy-node.physicsBody!.velocity.dy);
node.physicsBody!.velocity=CGVectorMake(node.physicsBody!.velocity.dx+relativeVelocity.dx*rate, node.physicsBody!.velocity.dy+relativeVelocity.dy*rate);
if radius < pointRadius {
didReachPoint()
}
}
}
}
我做得比较快,如果有错误请见谅。我现在没时间,但之后会添加一个gif展示解决方案。
关于碰撞的注意事项
为了修复碰撞时的不稳定移动,当两个物体碰撞后,将"rate"属性设置为0或者更好地是一个非常小的数字,以减少行驶速度的冲量,这样可以给你更多的变形空间。然后在未来的某个时间点(可能是碰撞发生后一段时间,或者最好是当物体再次缓慢移动时)将速率恢复到初始值。如果您真的想要一个好的效果,您实际上可以随着时间的推移逐渐将速率值从0增加到初始值,从而使自己获得平滑和渐进的加速度。
path[pathIndex-2] = CGPoint(x: 140, y: 90)
在接触/碰撞后更改了一个点。这有时会给我想要的结果。其他时候,当运行相同的代码而没有任何更改时,path[pathIndex-2]
是不同的点。日志显示pathIndex
在3和4之间变化。这是我目前的问题。我不知道更新方式是否会导致不一致的值。 - NSSwiftballPath
中的下一个点。这里的想法是计算/使用物体的接触点作为某个临时点,以便让它到达 ballPath
的下一个点。我不太确定该如何处理。 - NSologisticballPath[x]
时与圆形物体发生碰撞,我希望将该物体移动到 ballPath[x+1]
,而不是让它到达 ballPath[x]
。有点像圆形物体与其碰撞的物体的接触点暂时取代了 ballPath[x]
的位置。 - NSologistic使用followPath:duration:快速实现
override func didMoveToView(view: SKView) {
self.backgroundColor = UIColor.blackColor()
let xWidth: CGFloat = CGRectGetMaxX(self.frame)
let yHeight: CGFloat = CGRectGetMaxY(self.frame)
let ball = SKSpriteNode(color: UIColor.redColor(), size: CGSizeMake(50.0, 50.0))
let offset : CGFloat = ball.size.width / 2
// Moving path
let path = CGPathCreateMutable()
CGPathMoveToPoint(path, nil, offset, yHeight / 2)
CGPathAddLineToPoint(path, nil, xWidth * 2 / 3, yHeight - offset)
CGPathAddLineToPoint(path, nil, xWidth - offset, yHeight * 2 / 3)
CGPathAddLineToPoint(path, nil, xWidth / 2, offset)
CGPathAddLineToPoint(path, nil, offset, yHeight / 2)
// Movement
let moveByPath = SKAction.followPath(path, asOffset: false, orientToPath: false, duration: 4.0)
let moveForever = SKAction.repeatActionForever(moveByPath)
ball.runAction(moveForever)
self.addChild(ball)
}
GameScene.unarchiveFromFile
方法更改为 let scene = GameScene(size: view.bounds.size)
以创建场景的大小。