迅速 – 用SKScene和SKActions替换CALayer和CABasicAnimation

迅速 – 用SKScene和SKActions替换CALayer和CABasicAnimation,第1张

概述我试图在Metaballs上重组这个 Github Swift project,这样就可以通过SKActions而不是CABasicAnimation来移动SKShapeNodes来表示这些圈子。 我对viewController中出现的各种Metaball参数(handleLenRate,Spacing等)不感兴趣。我基本上希望能够使用SKActions来指定动画的开始和结束位置。 我不确定如何 我试图在Metaballs上重组这个 Github Swift project,这样就可以通过SKActions而不是CABasicAnimation来移动SKShapeNodes来表示这些圈子。

我对vIEwController中出现的各种Metaball参数(handleLenRate,Spacing等)不感兴趣。我基本上希望能够使用SKActions来指定动画的开始和结束位置。

我不确定如何实现这一点,特别是如何用SKShapeNode与SKActions替换下面的startAnimation函数:

func startAnimation() {    let loadingLayer = self.layer as! DBMetaballLoadingLayer    loadingAnimation = CABasicAnimation(keyPath: "movingBallCenterX")    loadingAnimation!.duration = 2.5    loadingAnimation!.timingFunction = camediatimingFunction(name: kcamediatimingFunctionEaseInEaSEOut)    loadingAnimation!.fromValue = NSValue(CGPoint:fromPoint)    loadingAnimation!.tovalue = NSValue(CGPoint: topoint)    loadingAnimation!.repeatCount = float.infinity    loadingAnimation!.autoreverses = true    loadingLayer.addAnimation(loadingAnimation!,forKey: "loading")}

请看下面我已经做了些什么:

MBCircle类:

struct MBCircle {var center: CGPoint = CGPointZerovar radius: CGfloat = 0.0var frame: CGRect {    get {        return CGRect(x: center.x - radius,y: center.y - radius,wIDth: 2 * radius,height: 2 * radius)    }  }}struct DefaultConfig {    static let radius: CGfloat = 15.0    static let mv: CGfloat = 0.6    static let maxdistance: CGfloat = 10 * DefaultConfig.radius    static let handleLenRate: CGfloat = 2.0    static let spacing: CGfloat = 160.0}

GameScene类(表示DBMetaballLoadingLayer和DBMetaballLoadingVIEw):

class GameScene: SKScene {private let MOVE_BALL_SCALE_RATE: CGfloat = 0.75private let ITEM_COUNT = 2private let SCALE_RATE: CGfloat = 1.0//0.3private var circlePaths = [MBCircle]()var radius: CGfloat = DefaultConfig.radiusvar maxLength: CGfloat {    get {        return (radius * 4 + spacing) * CGfloat(ITEM_COUNT)     }}var maxdistance: CGfloat = DefaultConfig.maxdistancevar mv: CGfloat = DefaultConfig.mvvar spacing: CGfloat = DefaultConfig.spacing {    dIDSet {        _adjustSpacing(spacing)    }}var handleLenRate: CGfloat = DefaultConfig.handleLenRatevar movingBallCenterX : CGfloat = 0.0 {    dIDSet {        if (circlePaths.count > 0) {            circlePaths[0].center = CGPoint(x: movingBallCenterX,y: circlePaths[0].center.y)        }    }}func _generalinit() {    circlePaths = Array(0..<ITEM_COUNT).map { i in        var circlePath = MBCircle()        circlePath.center = CGPoint(x: (radius * 10 + spacing) * CGfloat(i),y: radius * (1.0 + SCALE_RATE))        circlePath.radius = i == 0 ? radius * MOVE_BALL_SCALE_RATE : radius        circlePath.sprite = SKShapeNode(circleOfRadius: circlePath.radius)        circlePath.sprite?.position = circlePath.center        circlePath.sprite?.fillcolor = UIcolor.bluecolor()        addChild(circlePath.sprite!)        return circlePath    }}func _adjustSpacing(spacing: CGfloat) {    if (ITEM_COUNT > 1 && circlePaths.count > 1) {        for i in 1..<ITEM_COUNT {            var circlePath = circlePaths[i]            circlePath.center = CGPoint(x: (radius*2 + spacing) * CGfloat(i),y: radius * (1.0 + SCALE_RATE))        }    }}func _renderPath(path: UIBezIErPath) {    var shapeNode = SKShapeNode()    shapeNode.path = path.CGPath    shapeNode.fillcolor = UIcolor.bluecolor()    addChild(shapeNode)   }func _Metaball(j: Int,i: Int,v: CGfloat,handeLenRate: CGfloat,maxdistance: CGfloat) {    let circle1 = circlePaths[i]    let circle2 = circlePaths[j]    let center1 = circle1.center    let center2 = circle2.center    let d = center1.distance(center2)    var radius1 = circle1.radius    var radius2 = circle2.radius    if (d > maxdistance) {        _renderPath(UIBezIErPath(ovalInRect: circle2.frame))    } else {        let scale2 = 1 + SCALE_RATE * (1 - d / maxdistance)        radius2 *= scale2        _renderPath(UIBezIErPath(ovalInRect: CGRect(x: circle2.center.x - radius2,y: circle2.center.y - radius2,wIDth: 2 * radius2,height: 2 * radius2)))    }    if (radius1 == 0 || radius2 == 0) {        return    }    var u1: CGfloat = 0.0    var u2: CGfloat = 0.0    if (d > maxdistance || d <= abs(radius1 - radius2)) {        return    } else if (d < radius1 + radius2) {        u1 = acos((radius1 * radius1 + d * d - radius2 * radius2) / (2 * radius1 * d))        u2 = acos((radius2 * radius2 + d * d - radius1 * radius1) / (2 * radius2 * d))    } else {        u1 = 0.0        u2 = 0.0    }    let angle1 = center1.angleBetween(center2)    let angle2 = acos((radius1 - radius2) / d)    let angle1a = angle1 + u1 + (angle2 - u1) * v    let angle1b = angle1 - u1 - (angle2 - u1) * v    let angle2a = angle1 + CGfloat(M_PI) - u2 - (CGfloat(M_PI) - u2 - angle2) * v    let angle2b = angle1 - CGfloat(M_PI) + u2 + (CGfloat(M_PI) - u2 - angle2) * v    let p1a = center1.point(radians: angle1a,withLength: radius1)    let p1b = center1.point(radians: angle1b,withLength: radius1)    let p2a = center2.point(radians: angle2a,withLength: radius2)    let p2b = center2.point(radians: angle2b,withLength: radius2)    let totalRadius = radius1 + radius2    var d2 = min(v * handeLenRate,p1a.minus(p2a).length() / totalRadius)    d2 *= min(1,d * 2 / totalRadius)    radius1 *= d2    radius2 *= d2    let cp1a = p1a.point(radians: angle1a - CGfloat(M_PI_2),withLength: radius1)    let cp2a = p2a.point(radians: angle2a + CGfloat(M_PI_2),withLength: radius2)    let cp2b = p2b.point(radians: angle2b - CGfloat(M_PI_2),withLength: radius2)    let cp1b = p1b.point(radians: angle1b + CGfloat(M_PI_2),withLength: radius1)    let pathJoinedCircles = UIBezIErPath()    pathJoinedCircles.movetoPoint(p1a)    pathJoinedCircles.addCurvetoPoint(p2a,controlPoint1: cp1a,controlPoint2: cp2a)    pathJoinedCircles.addlinetoPoint(p2b)    pathJoinedCircles.addCurvetoPoint(p1b,controlPoint1: cp2b,controlPoint2: cp1b)    pathJoinedCircles.addlinetoPoint(p1a)    pathJoinedCircles.closePath()    _renderPath(pathJoinedCircles)}func startAnimation() {}overrIDe func dIDMovetoVIEw(vIEw: SKVIEw) {    _generalinit()}    overrIDe func update(currentTime: CFTimeInterval) {    /* Called before each frame is rendered */   }}

我没有对CGPointExtension类进行任何更改。

UPDATE

我仍然试图获得Metaball效果,这是我迄今为止取得的进展,基于Alessandro Ornano的建议:

import SpriteKitextension CGPoint {func distance(point: CGPoint) -> CGfloat {    let dx = point.x - self.x    let dy = point.y - self.y    return sqrt(dx * dx + dy * dy)}func angleBetween(point: CGPoint) -> CGfloat {    return atan2(point.y - self.y,point.x - self.x)}func point(radians radians: CGfloat,withLength length: CGfloat) -> CGPoint   {    return CGPoint(x: self.x + length * cos(radians),y: self.y + length * sin(radians))}func minus(point: CGPoint) -> CGPoint {    return CGPoint(x: self.x - point.x,y: self.y - point.y)}func length() -> CGfloat {    return sqrt(self.x * self.x + self.y + self.y)}}class GameScene: SKScene {var dBCircle : SKShapeNode!let radiusDBCircle: CGfloat = 10let radiusBall: CGfloat = 15var balls = [SKShapeNode]()var distanceBtwBalls : CGfloat = 15private let SCALE_RATE: CGfloat = 0.3overrIDe func dIDMovetoVIEw(vIEw: SKVIEw) {    // Some parameters    let strokecolor = SKcolor.orangecolor()    let dBHeight = CGRectGetMaxY(self.frame)-84 // 64 navigationController height + 20 reasonable distance    let dBStartX = CGRectGetMIDX(self.frame)-160 // extreme left    let dBStopX = CGRectGetMIDX(self.frame)+160 // extreme right    let dBWIDth = dBStopX - dBStartX    let totalBalls = 7 // first and last will be hIDden    let ballArea = dBWIDth / CGfloat(totalBalls-1)    distanceBtwBalls = ((ballArea-(radiusBall*2))+radiusBall*2)    // Create dbCircle    dBCircle = SKShapeNode.init(circleOfRadius: radiusDBCircle)    dBCircle.position = CGPointMake(CGRectGetMIDX(self.frame),dBHeight)    dBCircle.strokecolor = strokecolor    dBCircle.name = "dBCircle"    dBCircle.fillcolor = UIcolor.clearcolor()    addChild(dBCircle)    // Make static balls    for i in 0..<totalBalls {        let ball = SKShapeNode.init(circleOfRadius: radiusBall)        ball.position =   CGPointMake(dBStartX+(distanceBtwBalls*CGfloat(i)),dBHeight)        ball.strokecolor = strokecolor        ball.name = "ball"        ball.fillcolor = UIcolor.clearcolor()        balls.append(ball)        if i == 0 || i == totalBalls-1 {            ball.hIDden = true        }        addChild(ball)    }    mediaTimingFunctionEaseInEaSEOutEmulate(dBCircle,dBStartX: dBStartX,dBStopX: dBStopX)}func mediaTimingFunctionEaseInEaSEOutEmulate(node:SKShapeNode,dBStartX:CGfloat,dBStopX:CGfloat) {    let actionMoveleft = SKAction.movetoX(dBStartX,duration:1.7)    actionMoveleft.timingMode = SKActionTimingMode.EaseInEaSEOut    let actionMoveRight = SKAction.movetoX(dBStopX,duration:1.7)    actionMoveRight.timingMode = SKActionTimingMode.EaseInEaSEOut        node.runAction(SKAction.repeatActionForever(SKAction.sequence([actionMoveleft,actionMoveRight])))}overrIDe func update(currentTime: NSTimeInterval) {    var i = 0    self.enumerateChildNodesWithname("ball") {        node,stop in        let ball = node as! SKShapeNode        if CGRectContainsRect(ball.frame,self.dBCircle.frame) {            if (ball.actionForKey("zoom") == nil) {                let zoomIn = SKAction.scaleto(1.5,duration: 0.25)                let zoomOut = SKAction.scaleto(1.0,duration: 0.25)                let seq = SKAction.sequence([zoomIn,zoomOut])                ball.runAction(seq,withKey: "zoom")            }        }        i += 1    }    movingBezIErs()}func _renderPath(path: UIBezIErPath) {    let shapeNode = SKShapeNode(path: path.CGPath)    shapeNode.fillcolor = UIcolor.bluecolor()    addChild(shapeNode)}func movingBezIErs()    {    _renderPath(UIBezIErPath(ovalInRect: dBCircle.frame))    for j in 1..<balls.count {    self.latestTestMetaball(j,circleShape: dBCircle,v: 0.6,handleLenRate:  2.0,maxdistance: self.distanceBtwBalls)    }}func latestTestMetaball (j: Int,circleShape: SKShapeNode,handleLenRate: CGfloat,maxdistance: CGfloat)    {    let circle1 = circleShape    let circle2 = balls[j]    let center1 = circle1.position    let center2 = circle2.position    let d = center1.distance(center2)    var radius1 = circle1.frame.wIDth    var radius2 = circle2.frame.wIDth    var u1: CGfloat = 0.0    var u2: CGfloat = 0.0    if (d > maxdistance || d <= abs(radius1 - radius2)) {        return    } else if (d < radius1 + radius2) {        u1 = acos((radius1 * radius1 + d * d - radius2 * radius2) / (2 * radius1 * d))        u2 = acos((radius2 * radius2 + d * d - radius1 * radius1) / (2 * radius2 * d))    } else {        u1 = 0.0        u2 = 0.0    }    let angle1 = center1.angleBetween(center2)    let angle2 = acos((radius1 - radius2) / d)    let angle1a = angle1 + u1 + (angle2 - u1) * v    let angle1b = angle1 - u1 - (angle2 - u1) * v    let angle2a = angle1 + CGfloat(M_PI) - u2 - (CGfloat(M_PI) - u2 - angle2) * v    let angle2b = angle1 - CGfloat(M_PI) + u2 + (CGfloat(M_PI) - u2 - angle2) * v    let p1a = center1.point(radians: angle1a,withLength: radius2)    let totalRadius = radius1 + radius2    var d2 = min(v * handleLenRate,controlPoint2: cp1b)    pathJoinedCircles.addlinetoPoint(p1a)    pathJoinedCircles.closePath()    let shapeNode = SKShapeNode(path: pathJoinedCircles.CGPath)    shapeNode.fillcolor = UIcolor.bluecolor()    addChild(shapeNode)  }}
您可以使用movetoX和timingMode parameter轻松实现这种动画。

在这个答案结尾的下面的新的Swift 3翻译。

举个例子,我使用Xcode Sprite-Kit“Hello,World!”官方项目演示:

class GameScene: SKScene {    overrIDe func dIDMovetoVIEw(vIEw: SKVIEw) {        /* Setup your scene here */        let myLabel = SKLabelNode(Fontnamed:"Chalkduster")        myLabel.text = "Hello,World!"        myLabel.FontSize = 15        myLabel.position = CGPoint(x:CGRectGetMIDX(self.frame),y:CGRectGetMIDY(self.frame))        self.addChild(myLabel)        mediaTimingFunctionEaseInEaSEOutEmulate(myLabel)    }    func mediaTimingFunctionEaseInEaSEOutEmulate(node:SKLabelNode) {        let actionMoveleft = SKAction.movetoX(CGRectGetMIDX(self.frame)-100,duration:1.5)        actionMoveleft.timingMode = SKActionTimingMode.EaseInEaSEOut        let actionMoveRight = SKAction.movetoX(CGRectGetMIDX(self.frame)+100,duration:1.5)        actionMoveRight.timingMode = SKActionTimingMode.EaseInEaSEOut        node.runAction(SKAction.repeatActionForever(SKAction.sequence([actionMoveleft,actionMoveRight])))    }}

输出:

更新(这部分开始模拟静态球和动态球左右移动,但没有Metaball动画)

class GameScene: SKScene {    var dBCircle : SKShapeNode!    let radiusDBCircle: CGfloat = 10    let radiusBall: CGfloat = 15    private let SCALE_RATE: CGfloat = 0.3    overrIDe func dIDMovetoVIEw(vIEw: SKVIEw) {        // Some parameters        let strokecolor = SKcolor.orangecolor()        let dBHeight = CGRectGetMaxY(self.frame)-84 // 64 navigationController height + 20 reasonable distance        let dBStartX = CGRectGetMIDX(self.frame)-160 // extreme left        let dBStopX = CGRectGetMIDX(self.frame)+160 // extreme right        let dBWIDth = dBStopX - dBStartX        let totalBalls = 7 // first and last will be hIDden        let ballArea = dBWIDth / CGfloat(totalBalls-1)        let distanceBtwBalls = ((ballArea-(radiusBall*2))+radiusBall*2)        // Create dbCircle        dBCircle = SKShapeNode.init(circleOfRadius: radiusDBCircle)        dBCircle.position = CGPointMake(CGRectGetMIDX(self.frame),dBHeight)        dBCircle.strokecolor = strokecolor        dBCircle.name = "dBCircle"        dBCircle.fillcolor = UIcolor.clearcolor()        addChild(dBCircle)        // Make static balls        for i in 0..<totalBalls {            let ball = SKShapeNode.init(circleOfRadius: radiusBall)            ball.position =   CGPointMake(dBStartX+(distanceBtwBalls*CGfloat(i)),dBHeight)            ball.strokecolor = strokecolor            ball.name = "ball"            ball.fillcolor = UIcolor.clearcolor()            if i == 0 || i == totalBalls-1 {                ball.hIDden = true            }            addChild(ball)        }        mediaTimingFunctionEaseInEaSEOutEmulate(dBCircle,dBStopX: dBStopX)    }    func mediaTimingFunctionEaseInEaSEOutEmulate(node:SKShapeNode,dBStopX:CGfloat) {        let actionMoveleft = SKAction.movetoX(dBStartX,duration:1.7)        actionMoveleft.timingMode = SKActionTimingMode.EaseInEaSEOut        let actionMoveRight = SKAction.movetoX(dBStopX,duration:1.7)        actionMoveRight.timingMode = SKActionTimingMode.EaseInEaSEOut        node.runAction(SKAction.repeatActionForever(SKAction.sequence([actionMoveleft,actionMoveRight])))    }    overrIDe func update(currentTime: NSTimeInterval) {        var i = 0        self.enumerateChildNodesWithname("ball") {            node,stop in            let ball = node as! SKShapeNode            if CGRectContainsRect(ball.frame,self.dBCircle.frame) {                if (ball.actionForKey("zoom") == nil) {                    let zoomIn = SKAction.scaleto(1.5,duration: 0.25)                    let zoomOut = SKAction.scaleto(1.0,duration: 0.25)                    let seq = SKAction.sequence([zoomIn,zoomOut])                    ball.runAction(seq,withKey: "zoom")                }            }            i += 1        }    }}

使用Metaball动画的新更新:

最后我意识到这个结果,我的目标是使它非常类似于原来的:

可以对时间进行一些变化(例如zoomIn或zoomOut时间值或actionMoveleft,actionMoveRight时间值),这是代码:

import SpriteKitclass GameScene: SKScene {    var dBCircle : SKShapeNode!    let radiusDBCircle: CGfloat = 10    let radiusBall: CGfloat = 15    private let SCALE_RATE: CGfloat = 0.3    overrIDe func dIDMovetoVIEw(vIEw: SKVIEw) {        // Some parameters        let strokecolor = SKcolor.orangecolor()        let dBHeight = CGRectGetMaxY(self.frame)-84 // 64 navigationController height + 20 reasonable distance        let dBStartX = CGRectGetMIDX(self.frame)-160 // extreme left        let dBStopX = CGRectGetMIDX(self.frame)+160 // extreme right        let dBWIDth = dBStopX - dBStartX        let totalBalls = 7 // first and last will be hIDden        let ballArea = dBWIDth / CGfloat(totalBalls-1)        let distanceBtwBalls = ((ballArea-(radiusBall*2))+radiusBall*2)        // Create dbCircle        dBCircle = SKShapeNode.init(circleOfRadius: radiusDBCircle)        dBCircle.position = CGPointMake(CGRectGetMIDX(self.frame),duration:2.5)        actionMoveleft.timingMode = SKActionTimingMode.EaseInEaSEOut        let actionMoveRight = SKAction.movetoX(dBStopX,duration:2.5)        actionMoveRight.timingMode = SKActionTimingMode.EaseInEaSEOut        node.runAction(SKAction.repeatActionForever(SKAction.sequence([actionMoveleft,actionMoveRight])))    }    //MARK: - _Metaball original function    func _Metaball(circle2:SKShapeNode,circle1:SKShapeNode,maxdistance: CGfloat,vanishingTime : NSTimeInterval = 0.015) {        let center1 = circle1.position        let center2 = circle2.position        let d = center1.distance(center2)        var radius1 = radiusDBCircle        var radius2 = radiusBall        if (radius1 == 0 || radius2 == 0) {            return        }        var u1: CGfloat = 0.0        var u2: CGfloat = 0.0        if (d > maxdistance || d <= abs(radius1 - radius2)) {            return        } else if (d < radius1 + radius2) {            u1 = acos((radius1 * radius1 + d * d - radius2 * radius2) / (2 * radius1 * d))            u2 = acos((radius2 * radius2 + d * d - radius1 * radius1) / (2 * radius2 * d))        } else {            u1 = 0.0            u2 = 0.0        }        let angle1 = center1.angleBetween(center2)        let angle2 = acos((radius1 - radius2) / d)        let angle1a = angle1 + u1 + (angle2 - u1) * v        let angle1b = angle1 - u1 - (angle2 - u1) * v        let angle2a = angle1 + CGfloat(M_PI) - u2 - (CGfloat(M_PI) - u2 - angle2) * v        let angle2b = angle1 - CGfloat(M_PI) + u2 + (CGfloat(M_PI) - u2 - angle2) * v        let p1a = center1.point(radians: angle1a,withLength: radius1)        let p1b = center1.point(radians: angle1b,withLength: radius1)        let p2a = center2.point(radians: angle2a,withLength: radius2)        let p2b = center2.point(radians: angle2b,withLength: radius2)        let totalRadius = radius1 + radius2        var d2 = min(v * handeLenRate,p1a.minus(p2a).length() / totalRadius)        d2 *= min(1,d * 2 / totalRadius)        radius1 *= d2        radius2 *= d2        let cp1a = p1a.point(radians: angle1a - CGfloat(M_PI_2),withLength: radius1)        let cp2a = p2a.point(radians: angle2a + CGfloat(M_PI_2),withLength: radius2)        let cp2b = p2b.point(radians: angle2b - CGfloat(M_PI_2),withLength: radius2)        let cp1b = p1b.point(radians: angle1b + CGfloat(M_PI_2),withLength: radius1)        let pathJoinedCircles = UIBezIErPath()        pathJoinedCircles.movetoPoint(p1a)        pathJoinedCircles.addCurvetoPoint(p2a,controlPoint2: cp2a)        pathJoinedCircles.addlinetoPoint(p2b)        pathJoinedCircles.addCurvetoPoint(p1b,controlPoint2: cp1b)        pathJoinedCircles.addlinetoPoint(p1a)        pathJoinedCircles.closePath()        let shapeNode = SKShapeNode(path: pathJoinedCircles.CGPath)        shapeNode.strokecolor = SKcolor.orangecolor()        shapeNode.fillcolor = UIcolor.clearcolor()        addChild(shapeNode)        let wait = SKAction.waitForDuration(vanishingTime)        self.runAction(wait,completion: {            shapeNode.removeFromParent()        })    }    overrIDe func update(currentTime: NSTimeInterval) {        var i = 0        self.enumerateChildNodesWithname("ball") {            node,stop in            let ball = node as! SKShapeNode            let enlargeFrame = CGRectMake(ball.frame.origin.x-self.radiusBall*3,ball.frame.origin.y,ball.frame.wIDth+(self.radiusBall*6),ball.frame.height)            if CGRectContainsRect(enlargeFrame,duration: 0.25)                    zoomIn.timingMode = SKActionTimingMode.EaseInEaSEOut                    let zoomOut = SKAction.scaleto(1.0,duration: 0.25)                    let wait = SKAction.waitForDuration(0.8)                    let seq = SKAction.sequence([zoomIn,zoomOut,wait])                    ball.runAction(seq,withKey: "zoom")                }            }            self._Metaball(ball,circle1: self.dBCircle,handeLenRate: 2.0,maxdistance: 4 * self.radiusBall)            i += 1        }    }}//MARK: - Extensionsextension CGPoint {    func distance(point: CGPoint) -> CGfloat {        let dx = point.x - self.x        let dy = point.y - self.y        return sqrt(dx * dx + dy * dy)    }    func angleBetween(point: CGPoint) -> CGfloat {        return atan2(point.y - self.y,point.x - self.x)    }    func point(radians radians: CGfloat,withLength length: CGfloat) -> CGPoint   {        return CGPoint(x: self.x + length * cos(radians),y: self.y + length * sin(radians))    }    func minus(point: CGPoint) -> CGPoint {        return CGPoint(x: self.x - point.x,y: self.y - point.y)    }    func length() -> CGfloat {        return sqrt(self.x * self.x + self.y + self.y)    }}

Swift 3:

(我对maxdistance做了一些改动:4 * self.radiusBall with maxdistance:5 * self.radiusBall变得更加类似于原来的,但你可以根据需要改变它)

import SpriteKitclass GameScene: SKScene {    var dBCircle : SKShapeNode!    let radiusDBCircle: CGfloat = 10    let radiusBall: CGfloat = 15    private let SCALE_RATE: CGfloat = 0.3    overrIDe func dIDMove(to vIEw: SKVIEw) {        let label = self.childNode(withname: "//hellolabel") as? SKLabelNode        label?.removeFromParent()        self.anchorPoint = CGPoint.zero        // Some parameters        let strokecolor = SKcolor.orange        let dBHeight = self.frame.mIDY        let dBStartX = self.frame.mIDX-260 // extreme left        let dBStopX = self.frame.mIDX+260 // extreme right        let dBWIDth = dBStopX - dBStartX        let totalBalls = 7 // first and last will be hIDden        let ballArea = dBWIDth / CGfloat(totalBalls-1)        let distanceBtwBalls = ((ballArea-(radiusBall*2))+radiusBall*2)        // Create dbCircle        dBCircle = SKShapeNode.init(circleOfRadius: radiusDBCircle)        dBCircle.position = CGPoint(x:self.frame.mIDX,y:dBHeight)        dBCircle.strokecolor = strokecolor        dBCircle.name = "dBCircle"        dBCircle.fillcolor = UIcolor.clear        addChild(dBCircle)        // Make static balls        for i in 0..<totalBalls {            let ball = SKShapeNode.init(circleOfRadius: radiusBall)            ball.position =   CGPoint(x:dBStartX+(distanceBtwBalls*CGfloat(i)),y:dBHeight)            ball.strokecolor = strokecolor            ball.name = "ball"            ball.fillcolor = UIcolor.clear            if i == 0 || i == totalBalls-1 {                ball.isHIDden = true            }            addChild(ball)        }        mediaTimingFunctionEaseInEaSEOutEmulate(node: dBCircle,dBStopX:CGfloat) {        let actionMoveleft = SKAction.moveto(x: dBStartX,duration:2.5)        actionMoveleft.timingMode = SKActionTimingMode.easeInEaSEOut        let actionMoveRight = SKAction.moveto(x: dBStopX,duration:2.5)        actionMoveRight.timingMode = SKActionTimingMode.easeInEaSEOut        node.run(SKAction.repeatForever(SKAction.sequence([actionMoveleft,vanishingTime : TimeInterval = 0.015) {        let center1 = circle1.position        let center2 = circle2.position        let d = center1.distance(point: center2)        var radius1 = radiusDBCircle        var radius2 = radiusBall        if (radius1 == 0 || radius2 == 0) {            return        }        var u1: CGfloat = 0.0        var u2: CGfloat = 0.0        if (d > maxdistance || d <= abs(radius1 - radius2)) {            return        } else if (d < radius1 + radius2) {            u1 = acos((radius1 * radius1 + d * d - radius2 * radius2) / (2 * radius1 * d))            u2 = acos((radius2 * radius2 + d * d - radius1 * radius1) / (2 * radius2 * d))        } else {            u1 = 0.0            u2 = 0.0        }        let angle1 = center1.angleBetween(point: center2)        let angle2 = acos((radius1 - radius2) / d)        let angle1a = angle1 + u1 + (angle2 - u1) * v        let angle1b = angle1 - u1 - (angle2 - u1) * v        let angle2a = angle1 + CGfloat(M_PI) - u2 - (CGfloat(M_PI) - u2 - angle2) * v        let angle2b = angle1 - CGfloat(M_PI) + u2 + (CGfloat(M_PI) - u2 - angle2) * v        let p1a = center1.point(radians: angle1a,p1a.minus(point: p2a).length() / totalRadius)        d2 *= min(1,withLength: radius1)        let pathJoinedCircles = UIBezIErPath()        pathJoinedCircles.move(to: p1a)        pathJoinedCircles.addCurve(to: p2a,controlPoint2: cp2a)        pathJoinedCircles.addline(to: p2b)        pathJoinedCircles.addCurve(to: p1b,controlPoint2: cp1b)        pathJoinedCircles.addline(to: p1a)        pathJoinedCircles.close()        let shapeNode = SKShapeNode(path: pathJoinedCircles.cgPath)        shapeNode.strokecolor = SKcolor.orange        shapeNode.fillcolor = UIcolor.clear        addChild(shapeNode)        let wait = SKAction.wait(forDuration: vanishingTime)        self.run(wait,completion: {            shapeNode.removeFromParent()        })    }    overrIDe func update(_ currentTime: TimeInterval) {        var i = 0        self.enumerateChildNodes(withname: "ball") {            node,stop in            let ball = node as! SKShapeNode            let enlargeFrame = CGRect(x:ball.frame.origin.x-self.radiusBall*3,y:ball.frame.origin.y,wIDth:ball.frame.wIDth+(self.radiusBall*6),height:ball.frame.height)            if enlargeFrame.contains(self.dBCircle.frame) {                if (ball.action(forKey: "zoom") == nil) {                    let zoomIn = SKAction.scale(to: 1.5,duration: 0.25)                    zoomIn.timingMode = SKActionTimingMode.easeInEaSEOut                    let zoomOut = SKAction.scale(to: 1.0,duration: 0.25)                    let wait = SKAction.wait(forDuration: 0.7)                    let seq = SKAction.sequence([zoomIn,wait])                    ball.run(seq,withKey: "zoom")                }            }            self._Metaball(circle2: ball,maxdistance: 5 * self.radiusBall)            i += 1        }    }}//MARK: - Extensionsextension CGPoint {    func distance(point: CGPoint) -> CGfloat {        let dx = point.x - self.x        let dy = point.y - self.y        return sqrt(dx * dx + dy * dy)    }    func angleBetween(point: CGPoint) -> CGfloat {        return atan2(point.y - self.y,point.x - self.x)    }    func point(radians: CGfloat,y: self.y - point.y)    }    func length() -> CGfloat {        return sqrt(self.x * self.x + self.y + self.y)    }}
总结

以上是内存溢出为你收集整理的迅速 – 用SKScene和SKActions替换CALayer和CABasicAnimation全部内容,希望文章能够帮你解决迅速 – 用SKScene和SKActions替换CALayer和CABasicAnimation所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1052874.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存