Repeat SKAction starting position changes

2020-05-09 12:27发布

问题:

I've got a path and a SKShapeNode and would like to have the SKShapeNode follow the path forever (Hexagon shape).

let pathHexagon:SKShapeNode = SKShapeNode()
let player:SKShapeNode = SKShapeNode()

pathHexagon.path = playerHexagonPath(pathHexRadius)
pathHexagon.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame))
pathHexagon.strokeColor = UIColor.blackColor()
pathHexagon.lineWidth = 5
addChild(pathHexagon)

player.path = playerPath(playerSize)
player.position = CGPoint(x: CGRectGetMidX(frame), y:CGRectGetMidY(frame))
player.strokeColor = UIColor.blackColor()
player.fillColor = UIColor.blackColor()
addChild(player)

let action = SKAction.followPath(playerHexagonPath(pathHexRadius), speed: CGFloat(300.0))
player.runAction(SKAction.repeatActionForever(action))

It works somewhat but the starting position changes every cycle:

http://recordit.co/lEcLxs4DoD

Why is this happening?

Eventually I would like to link this animation to user input. As practice I am trying to replicate Super Hexagon. So if you know a better approach for this please let me know as well.

回答1:

This is what asOffset parameter does:

@param asOffset If YES, the points in the path are relative offsets to the node’s starting position. If NO, the points in the node are absolute coordinate values.

So from my understanding, when we set it to false, the points from the path are absolute coordinate values in coordinate system of node's parent.

You can do two things to make it work:

1) To make a container and add a player to it

2) To change scene's anchor point, but I doubt this suits you because you will have to re-position everything.

Probably there are few more ways to solve this, but I haven't tried by myself.

Option 1:

  let container = SKNode()
  player.path = playerPath(playerSize)
  player.position = CGPoint(x: 0, y: 0)
  player.strokeColor = UIColor.blackColor()
  player.fillColor = UIColor.blackColor()
  container.addChild(player)
  container.position = CGPoint(x:frame.midX, y:frame.midY)
  addChild(container)

  let action = SKAction.followPath(pathHexagon.path!, asOffset: false, orientToPath: true, speed: CGFloat(300.0))
  player.runAction(SKAction.repeatActionForever(action))

Or, the option two:

self.anchorPoint = CGPoint(x:0.5, y:0.5)

 mainHexagon.path = hexagonPath(mainHexRadius)
 mainHexagon.strokeColor = UIColor.redColor()
 mainHexagon.lineWidth = 10
 addChild(mainHexagon)

 pathHexagon.path = playerHexagonPath(pathHexRadius)
 pathHexagon.strokeColor = UIColor.blackColor()
 pathHexagon.lineWidth = 5
 addChild(pathHexagon)

 player.path = playerPath(playerSize)
 player.position = CGPoint(x: 0, y: 0)
 player.strokeColor = UIColor.blackColor()
 player.fillColor = UIColor.blackColor()
 addChild(player)

 let action = SKAction.followPath(pathHexagon.path!, asOffset: false, orientToPath: true, speed: CGFloat(300.0))
 player.runAction(SKAction.repeatActionForever(action))