使用Swift和SpriteKit实现高级旋转行为

时间:2015-06-24 09:02:38

标签: swift sprite-kit angle

我对使用Xcode,Swift和SpriteKit实现三角形的以下行为感到困惑:

Angle behaviour example

一旦球进入屏幕,三角形应转向球。一旦三角形方向与球对齐,其方向跟随球直到球完全离开屏幕。然后三角形返回其原始位置(如果屏幕内没有另一个球)或者它朝向下一个球。

跟随球的代码(图像3和4)应该没问题:

$('.Select option')  
    .filter(function () { return $(this).html() == data[i].value } )
    .prop('selected', true)
    .attr('value', data[i].value);

我尝试匹配球在一定时间后到达的位置,SKAction旋转三角形然后跟随它,但球不应该以恒定速度移动。所以这不起作用。

当最初转向球时能够轻松(和EaseOut)三角形的旋转将是锦上添花。

任何想法都非常感激。

1 个答案:

答案 0 :(得分:0)

之前有人发布过一个解决方案,但是现在,因为我想接受它,它似乎被删除了。

与此同时,我提出了自己的解决方案,似乎实现了我在我的问题中所描述的行为:

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和.Releasing状态,以便可以实现不同的附加行为。

如果您遇到错误,请随时尝试并告诉我。