Swift:对SKSpriteNode渐变进行动画处理 [英] Swift : Animate SKSpriteNode Gradient

查看:83
本文介绍了Swift:对SKSpriteNode渐变进行动画处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想做的事情对我来说似乎很简单,但是鉴于我对iOS还是很陌生,所以我想不出一种实现它的方法。

What i want to do seems very simple to me, but I can't figure out a way to implement it given that I am pretty new to iOS.

我想非常让我的背景具有渐变,该渐变可以通过淡入和淡出来缓慢地改变颜色。

I want to pretty much have my background a gradient that changes colors by fading in and fading out very slowly.

我在github上发现了它,并用它创建了两个具有不同颜色的渐变节点,唯一的问题是我似乎无法为其alpha设置动画或使其褪色以任何方式进出。
https://github.com/braindrizzlestudio/BDGradientNode
这就是我做到了:

I found this on github and used it to create two gradient nodes with different colors, the only issue is that I can't seem to animate its alpha or have it fade in and out in any way. https://github.com/braindrizzlestudio/BDGradientNode Here is what I did:

//Blueish
    let color1 = UIColor(red: 0.965, green: 0.929, blue: 0.667, alpha: 1)
    let color2 = UIColor(red: 0.565, green: 0.71, blue: 0.588, alpha: 1)
    let color3 = UIColor(red: 0.259, green: 0.541, blue: 0.529, alpha: 1)
    let colors = [color1, color2, color3]

    //Redish
    let color4 = UIColor(red: 1, green: 0.518, blue: 0.769, alpha: 1)
    let color5 = UIColor(red: 0.859, green: 0.22, blue: 0.541, alpha: 1)
    let color6 = UIColor(red: 0.737, green: 0, blue: 0.314, alpha: 1)
    let colors2 = [color4, color5, color6]

    let blending : Float = 0.3

    let location1 : CGFloat = 0.5
    let locations : [CGFloat] = [location1]

    let startPoint = CGPoint(x: 0.3, y: 0.0)
    let endPoint = CGPoint(x: 0.6, y: 0.8)

    let size = CGSize(width: self.size.width, height: self.size.height)

    let texture = SKTexture(imageNamed: "White Background")


    myGradientNode = BDGradientNode(linearGradientWithTexture: texture, colors: colors, locations: nil, startPoint: startPoint, endPoint: endPoint, blending: blending, keepTextureShape: true, size: size)

    myGradientNode2 = BDGradientNode(linearGradientWithTexture: texture, colors: colors2, locations: nil, startPoint: startPoint, endPoint: endPoint, blending: blending, keepTextureShape: true, size: size)
    myGradientNode2?.blending = 0

    self.addChild(myGradientNode2!)
    self.addChild(myGradientNode!)

我觉得有一种更简单的方法,也许不用。
您现在在很多游戏应用程序中都看到了这一点,如果有人可以帮助我实现这一令人惊叹的设计,这将大有帮助!

I feel like there is an easier way, maybe not using this. You see this in a lot of gaming apps now and it would help so much if someone could assist me with achieving this stunning design!

推荐答案

这是一个可能的完整解决方案(在 Swift 2.2 中),您可以调整其内容(包括对您的应用有意义的错误处理)。我将以相反的顺序布置代码,首先要能够编写以下代码:

Here is a possible complete solution (in Swift 2.2), which you can tweak to your heart's content (including error handling that makes sense for your app). I'll lay out the code in reverse order, starting with the goal of being able to write:

// assuming:
scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)

if let bg = HorizontalGradientNode(
    size: scene.size,
    fadingFrom: [.AliceBlue, .BurlyWood],
    to: [.AliceBlue, .CornflowerBlue],
    wait: 1,
    duration: 2)
{
    scene.addChild(bg)
}

这将在场景中添加一个节点,该节点封装了两个子渐变精灵节点,顶部之一将永远消失。 Horizo​​ntalGradientNode.init 接受两个 CGColor 数组。它们可以分别包含两种或多种颜色!名为 CGColor s( AliceBlue CornflowerBlue 等。 )可以通过以下方式构造:

This will add a node to the scene encapsulating two child gradient sprite nodes, the top one of which will fade in and out forever. The HorizontalGradientNode.init takes two arrays of CGColor. They can contain two or more colours each! The named CGColors (AliceBlue, CornflowerBlue, etc.) can be constructed in the following way:

public extension CGColor {

    public static func withHex(hex: Int, alpha: CGFloat = 1) -> CGColor {
        let x = max(0, min(hex, 0xffffff))
        let r = CGFloat((x & 0xff0000) >> 16)   / 0xff
        let g = CGFloat((x & 0x00ff00) >> 8)    / 0xff
        let b = CGFloat( x & 0x0000ff)          / 0xff
        return CGColorCreateGenericRGB(r, g, b, alpha)
    }

    public static var AliceBlue: CGColor { return .withHex(0xF0F8FF) }
    public static var BurlyWood: CGColor { return .withHex(0xDEB887) }
    public static var CornflowerBlue: CGColor { return .withHex(0x6495ED) }
    // see named colours at: http://www.w3schools.com/colors/colors_names.asp
}

最简单的 Horizo​​ntalGradientNode 版本如下:

class HorizontalGradientNode : SKNode {

    init?(size: CGSize, fadingFrom colors1: [CGColor], to colors2: [CGColor], wait: NSTimeInterval, duration: NSTimeInterval) {
        guard
            let grad1 = CGImage.withHorizontalGradient(size: size, colors: colors1),
            let grad2 = CGImage.withHorizontalGradient(size: size, colors: colors2)
            else
        {
            return nil
        }
        let bg1 = SKSpriteNode(texture: SKTexture(CGImage: grad1))
        let bg2 = SKSpriteNode(texture: SKTexture(CGImage: grad2))
        bg2.alpha = 0

        super.init()
        addChild(bg1)
        addChild(bg2)

        bg2.runAction(
            .repeatActionForever(
                .sequence(
                    [
                        .waitForDuration(wait),
                        .fadeInWithDuration(duration),
                        .waitForDuration(wait),
                        .fadeOutWithDuration(duration)
                    ]
                )
            )
        )
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

CGImage.withHorizo​​ntalGradient(size :, colors:)可以实现如下:

public extension CGImage {

    public static func withHorizontalGradient(size size: CGSize, colors: [CGColor]) -> CGImage? {
        guard colors.count >= 2 else { return nil }
        let locations: [CGFloat] = colors.indices.map{
            CGFloat($0) / CGFloat(colors.count - 1)
        }
        guard let gradient = CGGradientCreateWithColors(nil, colors, locations) else {
            return nil
        }
        let start = CGPoint(x: size.width / 2, y: size.height)
        let end = CGPoint(x: size.width / 2, y: 0)
        return CGContext.rgb(size)?
            .draw(linearGradient: gradient, start: start, end: end)
            .image
    }
}

使用 CGContext 的点语法扩展,例如:

Making use of dot syntax extensions of CGContext like:

public extension CGContext {

    public static func rgb(size: CGSize) -> CGContext? {
        let sp = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB)
        let bi = CGImageAlphaInfo.PremultipliedLast.rawValue
        return CGBitmapContextCreate(nil, Int(ceil(size.width)), Int(ceil(size.height)), 8, 0, sp, bi)
    }

    public var image: CGImage? { return CGBitmapContextCreateImage(self) }

    public func draw(linearGradient
        gradient: CGGradient?,
        start: CGPoint,
        end: CGPoint,
        options: CGGradientDrawingOptions = [.DrawsBeforeStartLocation, .DrawsAfterEndLocation]
        ) -> CGContext
    {
        CGContextDrawLinearGradient(self, gradient, start, end, options)
        return self
    }
}

如果您想在游乐场中尝试此操作,则可以粘贴所有内容,并以以下代码段作为前缀(对于OS X),以确保您拥有游乐场的时间轴在助理编辑器中:

If you want to try this in a playground you can paste all this in, prefixed by the following snippet (for OS X) making sure you have the playground's timeline in the Assistant editor:

import XCPlayground
import Cocoa
import SpriteKit

let scene = SKScene(size: CGSize(width: 400, height: 400))
let view = SKView(frame: CGRect(origin: .zero, size: scene.size))
XCPlaygroundPage.currentPage.liveView = view
view.presentScene(scene)

这篇关于Swift:对SKSpriteNode渐变进行动画处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆