如何在 SpriteKit 中将对象放在不同的 Z 层上

How to put objects on different Z layers in SpriteKit

在我的游戏中,我试图将图像放在不同的层上,以便清楚地知道东西在哪里。

例如地形在 Z 层 0,而改进和城市在 Z 层 1,而单位在更高层。

我正在学习教程 (http://helpmecodeswift.com/sprite-kit/spritekit-gameift-2-0-part-2) 并正在复制他们的方法(更改名称以满足我的需要)但它似乎不起作用。

这里有两张来自完全相同代码的图片(我想要右边的一张,虽然红色城市上面也应该有一个单位):

问题(不是主题问题):为什么这些图片加载不出来?

注意:大方块的颜色是 "cities",而看起来像方格的棋子是单位,在我完成大部分游戏并实际制作专用纹理之前,图形只是填充物。

这是处理图层的代码(单位和城市被放在正确的图层上):

class GameScene: SKScene {

    var mapTerrain: SKTileMapNode!

    override func sceneDidLoad() {
        cam = SKCameraNode()
        cam.xScale = 1
        cam.yScale = 1
        self.camera = cam
        self.addChild(cam)
        cam.position = CGPoint(x: 100, y: 100)
        setUpLayers()
        loadSceneNodes()
        setUpUI()
        testSpawn()
        //print("\(self.frame.width), \(self.frame.height)")
    }

    func setUpUI(){
        zoomIn.setButtonType(NSMomentaryLightButton)
        zoomIn.title = "Zoom In"
        zoomIn.alternateTitle = "Zoom In"
        zoomIn.acceptsTouchEvents = true
        view?.addSubview(zoomIn) //put button on screen

        zoomOut.setButtonType(NSMomentaryLightButton)
        zoomOut.title = "Zoom Out"
        zoomOut.alternateTitle = "Zoom Out"
        zoomOut.acceptsTouchEvents = true
        view?.addSubview(zoomOut) //put button on screen

        endTurn.setButtonType(NSMomentaryLightButton)
        endTurn.title = "End Turn"
        endTurn.alternateTitle = "End Turn"
        endTurn.acceptsTouchEvents = true
        view?.addSubview(endTurn) //put button on screen

    }

    func loadSceneNodes(){
        guard let mapTerrain = childNode(withName: "mapTerrain")
            as? SKTileMapNode else{
            fatalError("Background node not loaded")
        }
        self.mapTerrain = mapTerrain
        //GKGridGraph
    }

    func setUpLayers() {
        improvementsLayer = SKNode()
        improvementsLayer.name = "Objects Layer"
        addChild(improvementsLayer)
        unitsLayer = SKNode()
        unitsLayer.name = "Units Layer"
        addChild(unitsLayer)
    }

    func testSpawn(){
        if spawnCount == 0{
            for i in 0...10{
                spawnRedLegion(at: mapTerrain.centerOfTile(atColumn: 2, row: i), i: i)
            }
            for i in 0...10{
                spawnBlueLegion(at: mapTerrain.centerOfTile(atColumn: 3, row: i), i: i)
            }
            spawnCount += 1
            for i in 0...0{
                spawnRedCity(at: mapTerrain.centerOfTile(atColumn: 0, row: 1), i: i)
                spawnBlueCity(at: mapTerrain.centerOfTile(atColumn: 5, row: 1), i: i) 
            }
        }
    }

    func spawnRedLegion(at: CGPoint, i: Int){
        let RedLegion = legion(texture: textureRedLegion, moveTo: nil, tag: i, health: 2)
        RedLegion.position = at
        RedLegion.team = "Red"
        unitsLayer.addChild(RedLegion)
        legionList.append(RedLegion)
    }

    func spawnBlueLegion(at: CGPoint, i: Int){
        let BlueLegion = legion(texture: textureBlueLegion, moveTo: nil, tag: i, health: 2)
        BlueLegion.position = at
        BlueLegion.team = "Blue"
        unitsLayer.addChild(BlueLegion)
        legionList.append(BlueLegion)
    }

    func spawnRedCity(at: CGPoint, i: Int){
        let RedCity = city(texture: textureRedCity, tag: i, health: 1, production: 1, workDone: 0)
        RedCity.position = at
        RedCity.team = "Red"
        improvementsLayer.addChild(RedCity)
        cityList.append(RedCity)
    }

    func spawnBlueCity(at: CGPoint, i: Int){
        let BlueCity = city(texture: textureBlueCity, tag: i, health: 1, production: 1, workDone: 0)
        BlueCity.position = at
        BlueCity.team = "Blue"
        improvementsLayer.addChild(BlueCity)
        cityList.append(BlueCity)
    }
    ....
}

//this is in another file

let textureRedLegion = SKTexture(imageNamed: "Red Checker")
let textureBlueLegion = SKTexture(imageNamed: "Black Checker")
let textureRedCity = SKTexture(imageNamed: "Red Square")
let textureBlueCity = SKTexture(imageNamed: "Black Square")

struct layers {

    static let background: CGFloat = 0
    static let improvements: CGFloat = 1
    static let units: CGFloat = 3

}

var improvementsLayer: SKNode!
var unitsLayer: SKNode!

我就是这样做的

gameLayer 在 SKS 文件中设置,这就是为什么它的初始化方式不同于 controlsLayer

enum Layer: CGFloat {
    case background = 0
    case gameLayer = 20
    case controls = 100
}

class GameScene: SKScene, SKPhysicsContactDelegate {

    private var gameLayer = SKNode()
    private var controlsLayer = SKNode()

    override func didMove(to view: SKView) {

        if let gameLayer = self.childNode(withName: "gameLayer") {
            self.gameLayer = gameLayer
            self.gameLayer.zPosition = Layer.gameLayer.rawValue
        }

        controlsLayer.zPosition = Layer.controls.rawValue
        addChild(controlsLayer)

        setupObjects()
    }

    func setupObjects() {

        let pauseButton = SKSpriteNode(texture: nil, color: .red, size: CGSize(width: 100, height: 100)
        pauseButton.position = CGPoint(x: 100, y: 100)
        controlsLayer.addChild(pauseButton)

        //OR USE IT THIS WAY

        let ball = SKSpriteNode(texture: nil, color: .red, size: CGSize(width: 100, height: 100)
        ball.position = CGPoint(x: 400, y: 400)
        ball.zPosition = Layer.gameLayer.rawValue
        self.addChild(ball)
    }
}