How to make player move to opposite side while is

2019-03-31 02:04发布

enter image description here

I want that when touches began the player (red circle) moves to the opposite side of the circular path. I already made that the player follows a path, but I havent find answer to my question on internet.

    override func didMoveToView(view: SKView) {

    player = SKSpriteNode(imageNamed: "circulo")
    player.position = CGPoint(x: self.frame.width / 2, y: self.frame.height / 2 - 170)
    player.color = colorGris
    player.colorBlendFactor = 1
    player.size = CGSize(width: 25, height: 25)
    self.addChild(player)
    player.zPosition = 3

   }
   override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
   /* Called when a touch begins */

    if gameStarted == false {

        gameStarted = true
        moveClockWise()
        movingClockWise = true

    }

       }



   func moveClockWise(){



    let dx = player.position.x - self.frame.width / 2
    let dy = player.position.y - self.frame.height / 2

    let rad = atan2(dy, dx)

    path = UIBezierPath(arcCenter: CGPoint(x:self.frame.width / 2, y: self.frame.height / 2) , radius: 170, startAngle: rad, endAngle: rad + CGFloat(M_PI * 4), clockwise: true)

    let follow = SKAction.followPath(path.CGPath, asOffset: false, orientToPath: true, speed: 200)
    player.runAction(SKAction.repeatActionForever(follow).reversedAction())

}

2条回答
地球回转人心会变
2楼-- · 2019-03-31 02:18

One of the easiest ways to move an object in a circular path is to

  1. Create a SKNode container
  2. Create a sprite
  3. Add the container to the scene
  4. Set the sprite's x position to the radius of the circular path
  5. Add the sprite to the container
  6. Rotate the container

If you want to move the sprite to the other side or change the rotation's radius, simply

  1. change the sprite's x position

If you want to change the direction of the rotation,

  1. reverse the container's rotation

Example Code:

// 1) Create the container node 
let node = SKNode()
// 2) Create a sprite
let sprite = SKSpriteNode(color:SKColor.blueColor(),size:CGSizeMake(20,20))
var rotation:CGFloat = CGFloat(M_PI)
let radius:CGFloat = 50

override func didMoveToView(view: SKView) {
    scaleMode = .ResizeFill
    node.position = view.center
    // 3) Add the container to the scene
    addChild(node)
    // 4) Set the sprite's x position
    sprite.position = CGPointMake(radius, 0)
    // 5) Add the sprite to the container
    node.addChild(sprite)
    // 6) Rotate the container
    rotate()
}

// Rotate the container
func rotate() {
    let action = SKAction.rotateByAngle(rotation, duration: 4)
    node.runAction(SKAction.repeatActionForever(action),withKey: "rotate")
}

// 8) Reverse the direction of the rotation
func reverse() {
    rotation = -rotation
}

// Stop rotating the container
func stopRotation() {
    if node.actionForKey("rotate") != nil {
        node.removeActionForKey("rotate")
    }
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
   /* 7) Change the sprite's x-position  */
    if sprite.actionForKey("move") == nil {
        stopRotation()
        let opposite = -sprite.position.x * 2
        let move = SKAction.moveByX(opposite, y: 0, duration: 3)
        let rotate = SKAction.runBlock {
            self.rotate()
        }
        sprite.runAction(SKAction.sequence([move, rotate]), withKey: "move")
    }
}
查看更多
Deceive 欺骗
3楼-- · 2019-03-31 02:24

I think you could follow these steps:

  • stop the runAction of your player:

You can do for example:

let follow = SKAction.followPath(path.CGPath, asOffset: false, orientToPath: true, speed: 200)
player.runAction(SKAction.repeatActionForever(follow).reversedAction(),withKey:"followPath")

To stop do simply:

player.removeActionForKey("followPath")
  • Re-build your path to have a new "moveToPoint" (the start point) wit the actual position:

To do it I try to use your code to make it understandable:

var myCircle : CGMutablePath! = CGPathCreateMutable()
let newDx = player.position.x - self.frame.width / 2
let newDy = player.position.y - self.frame.height / 2
let newRad = atan2(newDy, newDx)
let newPath = UIBezierPath(arcCenter: CGPoint(x:self.frame.width / 2, y: self.frame.height / 2) , radius: 170, startAngle: newRad, endAngle: newRad + CGFloat(M_PI * 4), clockwise: true)
  • Mirroring the path:

To do this trick you can write:

var mirroring = CGAffineTransformMakeScale(1.0, -1.0) // flip horizontal
var mirrorPath : CGMutablePath! = CGPathCreateMutable()
CGPathAddPath(mirrorPath, &mirroring, newPath.CGPath)
  • Restart the runAction:

Here you can re-launch:

let newFollow = SKAction.followPath(mirrorPath, asOffset: false, orientToPath: true, speed: 200)
player.runAction(SKAction.repeatActionForever(newFollow).reversedAction(),withKey:"followPath")

Addition: If you can add some nice animation like for example the jump between the point position and the mirrored point in the circle, you need to know the CGPoint destination (in the mirrorPath it will be the "moveToPoint" or the also the first point). Here you can find an extension to obtain all CGPath points so:

var mirrorPoints = mirrorPath.getPathElementsPoints()
let destinationPoint = mirrorPoints.first!

In the Sprite-kit framework there isn't yet a jumpAction between the available SKAction's, so you can create it with few code.
Usually the "jump" is maked by changing the Y coordinate, in you case your view is from high so you can do a zoomIn e zoomOut (scale).

查看更多
登录 后发表回答