4 Replies
      Latest reply on Sep 30, 2018 8:19 AM by igorland
      igorland Level 1 Level 1 (0 points)

        Hi.

         

        I am trying to add background with gradient color to my SKScene:

         

        class GameScene: SKScene
        {
            override func didMove(to view: SKView)
            {
                let gradientView = UIView(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height))
        
                let image = UIImage.gradientBackgroundImage(bounds: CGRect(x: 0, y: 0, width: frame.width, height: frame.height),
                                                            colors: [UIColor.yellow.cgColor, UIColor.blue.cgColor])
        
                let background = SKSpriteNode(color: UIColor(patternImage: image), size: frame.size)
                addChild(background)
            }
        }
        
        extension UIImage
        {
            /**
             http://www.riptutorial.com/ios/example/14328/gradient-image-with-colors
             */
            static func gradientBackgroundImage(bounds: CGRect, colors: [CGColor]) -> UIImage
            {
                let gradientLayer = CAGradientLayer()
                gradientLayer.frame = bounds
                gradientLayer.colors = colors
               
                UIGraphicsBeginImageContext(gradientLayer.bounds.size)
                gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
                let image = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                return image!
            }
        }

         

        This is not working. Is there a better way to add gradient background to the SKScene?

         

        Thanks a lot!

         

        EDIT:

         

        If I do this in didMove(to view:):

         

        self.view?.backgroundColor = UIColor.blue
        let backgroundDep = IGABackgroundLayer().gradientMetar() // My method to create CAGradientLayer
        backgroundDep.frame = self.view!.bounds
        self.view!.layer.insertSublayer(backgroundDep, at: 0)

         

        ...background is created nicely but added SKNodes are not seen on top of it.

        • Re: Adding gradient background to SKScene
          QuinceyMorris Level 8 Level 8 (6,050 points)

          I'm not sure offhand, but I don't think color patterns work in Sprite Kit.

           

          Unless I'm misreading your code, you create an image with a gradient of the correct size for the sprite node. Why would you not just use that image as the sprite's texture? If anything, keeping the texture around is plausibly going to be cheaper (memory and performance)  than keeping the gradient image around for the UIColor.

            • Re: Adding gradient background to SKScene
              igorland Level 1 Level 1 (0 points)

              Thank you, QuinceyMorris.

               

              Tried to do it through SKTexture in didMove(to view:):

               

              let backgroundImg = UIImage.imageFromLayer(layer: IGABackgroundLayer().gradientMetar())
                    
              if let backgroundImg = backgroundImg
              {
                          // https://stackoverflow.com/questions/21765128/sktexture-from-uiimage-looks-different
                          let backgroundTexture = SKTexture(image: backgroundImg)
                          let background = SKSpriteNode(texture: backgroundTexture)
                          background.position = CGPoint(x: frame.width/2, y: frame.height/2)
                          addChild(background)
              }
              
              extension UIImage
              {  
                  /**
                   https://stackoverflow.com/questions/3454356/uiimage-from-calayer-iphone-sdk
                   */
                  static func imageFromLayer(layer: CALayer) -> UIImage?
                  {
                      UIGraphicsBeginImageContextWithOptions(layer.bounds.size,
                                                             layer.isOpaque, UIScreen.main.scale)
                     
                      defer { UIGraphicsEndImageContext() }
                     
                      // Don't proceed unless we have context
                      guard let context = UIGraphicsGetCurrentContext() else
                      {
                          return nil
                      }
                     
                      layer.render(in: context)
                      return UIGraphicsGetImageFromCurrentImageContext()
                  }
              }

               

              Still no background image. Not sure where the problem is...

               

              Thanks.

                • Re: Adding gradient background to SKScene
                  QuinceyMorris Level 8 Level 8 (6,050 points)

                  One frequent cause of "disappearing" nodes is an incorrect zPosition. If you have another background covering the screen, you'll need to put these sprite nodes above it.

                   

                  Regarding the other solution, I wouldn't try to use a separate layer. It'll either be on top of the SKScene (and hide the scene) or underneath the scene (and not be visible).

                    • Re: Adding gradient background to SKScene
                      igorland Level 1 Level 1 (0 points)

                      In case someone is interested, this has been solved the following way:

                       

                      let color1 = UIColor(red: 255/255, green: 153/255, blue: 102/255, alpha: 1)
                          let color2 = UIColor(red: 255/255, green: 204/255, blue: 153/255, alpha: 1)
                          let backgroundImg = UIImage.radialGradientImage(size: frame.size, outerColor: color1, innerColor: color2)
                          let backgroundTexture = SKTexture(image: backgroundImg)
                          let background = SKSpriteNode(texture: backgroundTexture)
                          background.position = CGPoint(x: frame.width/2, y: frame.height/2)
                          addChild(background)
                      
                          /**
                           https://gist.github.com/zummenix/67adccc1ee893ade8fb27a5a5a790498
                           */
                          static func radialGradientImage(size: CGSize, outerColor: UIColor, innerColor: UIColor) -> UIImage
                          {
                              let colorSpace = CGColorSpaceCreateDeviceRGB()
                              let gradient = CGGradient(colorsSpace: colorSpace, colors: [outerColor.cgColor, innerColor.cgColor] as CFArray, locations: [1.0, 0.0])
                              let center = CGPoint(x: size.width / 2.0, y: size.height / 2.0)
                             
                              UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
                              let imageContext = UIGraphicsGetCurrentContext()
                             
                              imageContext!.drawRadialGradient(gradient!, startCenter: center, startRadius: 0.0, endCenter: center, endRadius: size.width / 2.0, options: CGGradientDrawingOptions.drawsAfterEndLocation)
                             
                              let image = UIGraphicsGetImageFromCurrentImageContext()
                              UIGraphicsEndImageContext()
                             
                              return image!
                          }