我对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所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)