之前有人发过解决办法,现在想采纳,好像被删了。
与此同时,我还是想出了自己的解决方案,这似乎可以很好地实现我在问题中描述的行为:
import SpriteKit
// Constants
let screenWidth = UIScreen.mainScreen().bounds.width
let screenHeight = UIScreen.mainScreen().bounds.height
let pi = CGFloat(M_PI)
let degreesToRadians = pi / 180
class GameScene: SKScene {
var triangle = Triangle()
override func didMoveToView(view: SKView) {
/* Setup your scene here */
scaleMode = .ResizeFill
addChild(triangle)
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
let circle = Circle()
addChild(circle)
circle.move {
circle.removeFromParent()
self.triangle.state = .Releasing
println("Releasing")
}
}
func updateAngle(from origin: CGPoint, to target: CGPoint) {
let deltaX = target.x - origin.x
let deltaY = target.y - origin.y
let angle = atan2(deltaY, deltaX)
switch triangle.state {
case .Locked:
let x: CGFloat = CGFloat(-M_PI)
triangle.zRotation = angle - 90 * degreesToRadians
case .Acquiring, .Releasing:
let angleDifference: CGFloat = (angle - triangle.zRotation) * degreesToRadians
let ease: CGFloat = 0.7
triangle.zRotation += angleDifference * ease
default:
break
}
if triangle.zRotation >= angle - 90 * degreesToRadians {
switch triangle.state {
case .Acquiring:
triangle.state = .Locked
println("Locked")
case .Releasing:
triangle.state = .Ready
println("Ready")
default:
break
}
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
if let circle = childNodeWithName("circle") as? Circle {
if circle.position.x < screenWidth + circle.size.width/2 && circle.position.x > -circle.size.width/2 {
switch triangle.state {
case .Ready, .Releasing:
triangle.state = .Acquiring
println("Acquiring")
case .Acquiring, .Locked:
updateAngle(from: triangle.position, to: circle.position)
}
}
}
if triangle.state == .Releasing {
updateAngle(from: triangle.position, to: CGPoint(x: triangle.position.x, y: screenHeight/4))
}
}
}
enum TriangleState {
case Ready, Acquiring, Locked, Releasing
}
class Triangle: SKSpriteNode {
var state: TriangleState
init() {
state = .Ready
let texture = SKTexture(imageNamed: "Spaceship.png")
super.init(texture: texture, color: nil, size: texture.size())
setScale(0.25)
position = CGPointMake(screenWidth / 2.0, screenHeight / 2.0)
zRotation = CGFloat(-M_PI)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class Circle: SKSpriteNode {
init() {
let texture = SKTexture(imageNamed: "Spaceship.png")
super.init(texture: texture, color: nil, size: texture.size())
name = "circle"
setScale(0.25)
position = CGPointMake(screenWidth * 1.3, screenHeight / 4.0)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func move(completion: () -> ()) {
let move = SKAction.moveTo(CGPointMake(-size.width/2, screenHeight / 4.0), duration: 6.0)
runAction(move, completion: completion)
}
}
触摸时,目标对象会出现并移动,而三角形会跟随并释放到其初始位置,一旦目标消失。最重要的是,如果有另一个可用的目标对象,三角形将获取该新目标。
我区分了 .Ready 和 .Releating 状态,以便可以实现不同的附加行为。
如果您遇到错误,请随时尝试并告诉我。