Swift - Adding background image behind a Sprite Ki

2019-09-01 10:13发布

I am trying to add a background image in my view controller so my sprite kit game scenes can be in the foreground. It's important for me for my background image to stay on screen while the game scenes transition to each other. The problem I am having is how to place the subview I created for my background to be behind my skscene, at the moment my background image is in front of my game scene and all you can see is the image sendSubviewToBack doesn't seem to work. The following is my viewDidLoad Thanks

import UIKit
import SpriteKit

class GameViewController: UIViewController {

    override func viewDidLoad() {

        super.viewDidLoad()
        let scene = MainMenuScene(size: CGSize(width: 1536, height: 2048))
        let skView = self.view as! SKView

        scene.scaleMode = .AspectFill
        skView.presentScene(scene)

        let backgroundImageView = UIImageView(image: UIImage(named: "bg.jpg"))
        backgroundImageView.frame = view.frame
        backgroundImageView.contentMode = .ScaleAspectFill
        view.addSubview(backgroundImageView)
        view.sendSubviewToBack(backgroundImageView)

    }
}

5条回答
孤傲高冷的网名
2楼-- · 2019-09-01 10:32

What you're describing can't be done with UIKit because your view can't be visible behind the SKView which renders your scene.

In iOS 8+ you can use the SKView's allowsTransparency property. Documentation states:

This property tells the drawing system as to how it should treat the view. If set to NO, the drawing system treats the view as fully opaque, which allows the drawing system to optimize some drawing operations and improve performance. If set to YES, the drawing system composites the view normally with other content. The default value of this property is NO.

But in my opinion this is not the best solution. The best solution is to use Sprite Kit, but the problem is you can't preserve nodes across scenes. You must add the node again during each scene transition. This is why I do not use Apple's scene transitions the way the documentation describes. Instead I use my own custom SKNodes and make my own custom transitions using those nodes, which I highly recommend you do. I gave a detailed answer about this here

查看更多
Deceive 欺骗
3楼-- · 2019-09-01 10:33

Generally UI elements are placed on top of each other depending on the order they were added to the view.

If you want to customize that you can use the property .layer.zPosition which is any value you pick. The lowest value is in the very back while the highest one is on top.

Hope that helps :)

查看更多
祖国的老花朵
4楼-- · 2019-09-01 10:35

You can use insertSubView: instead of addSubView and specify the index, which determines z-order of views. A view with a higher index lies above those with lower indices.

查看更多
姐就是有狂的资本
5楼-- · 2019-09-01 10:47

Make a SKSpriteNode with the background texture!

background.size = self.frame.size //Make the background as big as the screen
查看更多
成全新的幸福
6楼-- · 2019-09-01 10:47

I dealt with the same issue, and here is how to fix it:

  1. Put the code in viewWillLayoutSubviews(), not in viewDidLoad() - this will ensure you have access to all the view's properties.
  2. Don't cast the self.view as an SKView, leave it as an UIView and instead create two child views: one for the background image and one for the SKScene

Here is the corrected code:

var skView : SKView? = nil

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    if (skView == nil) {
        let backgroundImageView = UIImageView(image: UIImage(named: "bg.jpg"))
        view.addSubview(backgroundImageView)

        skView = SKView(frame: CGRect(origin: CGPointZero, size: CGSize(width: 1536, height: 2048)))
        skView!.ignoreSiblingOrder = true
        let scene = MainMenuScene(size: CGSize(width: 1536, height: 2048))
        scene.scaleMode = .AspectFill

        view.addSubView(skView!)
        skView!.presentScene(scene)
    }
}

My particular reason to do this was so I could have a game that would be playable on both iPhones and iPads without aspect ratio distortion. The 'playable area' is always 16:9, and when seen on an iPad, you see a background image that extends to the sides of the playable area.

What I did was to load a background image meant for the iPad (which has an aspect ratio of 4:3), defined the skView to have an aspect ratio of 16:9 (So instead of 1536/2048 I am using 750/1334, for example) and set the scene's scaleMode to .AspectFit. When seen on an iPhone, the scene covers the background completely. When seen on an iPad, you can see the background image complement the sides of the playable area.

Hope this helps!

查看更多
登录 后发表回答