Search code examples
swiftsprite-kituikitsklabelnode

Label not showing on Tutorial SKScene


Good morning,

I am having an issue with my SKLabel not showing on my Tutorial SKScene. My code is below, I can't seem to find where I went wrong. When trying to add the SKLabel manually, it works fine. When adding it via code, nothing happens. Where am I going wrong?

GameviewController:

import UIKit
import SpriteKit
import GameplayKit

class GameViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        // Configure the view
        let skView = self.view as! SKView
        skView.showsFPS = true
        skView.showsNodeCount = true
        
        // Create and present the scene
        let scene = Start(size: skView.bounds.size)
        scene.scaleMode = .aspectFill
        skView.presentScene(scene)
        // Print the size of the scene
                print("Scene size: \(scene.size)")
        
        
         
    }

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        if UIDevice.current.userInterfaceIdiom == .phone {
            return .allButUpsideDown
        } else {
            return .all
        }
    }

    override var prefersStatusBarHidden: Bool {
        return true
    }
}

start scene

import SpriteKit
import GameplayKit

class Start: SKScene {
    
    private var label : SKLabelNode?
    private var PlayButton : SKSpriteNode?
    
    
    
    
    override func didMove(to view: SKView) {
        
        // Create a label node
        let labelNode = SKLabelNode(text: "Block Maze")
        
        // Set position of the label just below the top with a fixed margin
        let topMargin: CGFloat = 100 // Adjust this value for the desired margin
        labelNode.position = CGPoint(x: self.size.width / 2, y: self.size.height - topMargin)
        
        // Add the label node to the scene
        self.addChild(labelNode)
        
        // Print the position of the label
        print("Label position: \(labelNode.position)")
        
        
        // Create a play button box
        let buttonSize = CGSize(width: 150, height: 60)
        let playButtonBox = SKShapeNode(rectOf: buttonSize, cornerRadius: 10)
        playButtonBox.fillColor = SKColor.clear
        playButtonBox.position = CGPoint(x: self.size.width / 2, y: self.size.height / 2)
        
        // Create a label node for the play button text
        let playLabel = SKLabelNode(text: "Play")
        playLabel.fontColor = .white
        playLabel.fontSize = 24
        playLabel.position = CGPoint(x: 0, y: -10) // Adjust this value to position the text inside the box
        
        playButtonBox.name = "playButton" // Set the name property
        
        // Add the label node as a child of the button box
        playButtonBox.addChild(playLabel)
        
        // Add the play button box to the scene
        self.addChild(playButtonBox)
    }
    
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            let location = touch.location(in: self)
            
            // Check if the touch is on the play button
            if let node = self.atPoint(location) as? SKShapeNode, node.name == "playButton" {
                // Perform the action when the play button is tapped
                print("Play button tapped!")
                
                // Add your code here to perform the desired action
                
                //Go to Tutorial
                // Create and present the scene
                // Create and present the scene
                if let tutorialScene = SKScene(fileNamed: "Tutorial") {
                    tutorialScene.scaleMode = .fill
                    
                    // Present the TutorialScene
                    self.view?.presentScene(tutorialScene)
                    
                }
                
            }
            
            
        }
        
        
    }
}

Tutorial Scene

import SpriteKit
import GameplayKit

class Tutorial: SKScene {
    
    override func didMove(to view: SKView) {
        print("Tutorial scene did move to view.") // Confirm that the scene's didMove(to:) method is called
        
        // Create a label node
        let labelNode = SKLabelNode(text: "Block Maze")
        labelNode.fontColor = SKColor.black // Set label text color
        labelNode.fontSize = 24 // Set label font size
        
        // Set position of the label just below the top with a fixed margin
        let topMargin: CGFloat = 100 // Adjust this value for the desired margin
        labelNode.position = CGPoint(x: self.size.width / 2, y: self.size.height - topMargin)
        
        // Add the label node to the scene
        self.addChild(labelNode)
        
        // Print the position of the label
        print("Label position: \(labelNode.position)")
    }
    
}

Solution

  • The Tutorial scene needs a size and a scaling mode so that the view can properly render it. For example, add this code inside didMove:

    class Tutorial: SKScene {
    
        override func didMove(to view: SKView) {
            size = view.bounds.size
            scaleMode = .resizeFill
    
            // ... 
        }
    
    }
    

    view.bounds.size gives the scene a size for its visible portion, and .resizeFill tells the visible portion of the scene to match the proportions of the view holding it.

    The "Block Maze" label showing near the top of the view

    Edit: here is the full working code using SwiftUI for easier live preview.

    import SwiftUI
    import SpriteKit
    
    // MARK: - Live preview
    
    struct LabelPositionView: View {
        var myScene = Start()
        
        var body: some View {
            SpriteView(
                scene: myScene,
                options: [.ignoresSiblingOrder, .shouldCullNonVisibleNodes],
                debugOptions: [.showsNodeCount, .showsDrawCount, .showsFPS]
            )
        }
    }
    
    #Preview {
        LabelPositionView()
    }
    
    // MARK: - SpriteKit
    
    class Start: SKScene {
        
        private var label : SKLabelNode?
        private var PlayButton : SKSpriteNode?
        
        override func didMove(to view: SKView) {
            size = view.bounds.size
            scaleMode = .resizeFill
            
            // Create a label node
            let labelNode = SKLabelNode(text: "Block Maze")
            
            // Set position of the label just below the top with a fixed margin
            let topMargin: CGFloat = 100 // Adjust this value for the desired margin
            labelNode.position = CGPoint(x: self.size.width / 2, y: self.size.height - topMargin)
            
            // Add the label node to the scene
            self.addChild(labelNode)
            
            // Print the position of the label
            print("Label position: \(labelNode.position)")
            
            // Create a play button box
            let buttonSize = CGSize(width: 150, height: 60)
            let playButtonBox = SKShapeNode(rectOf: buttonSize, cornerRadius: 10)
            playButtonBox.fillColor = SKColor.clear
            playButtonBox.position = CGPoint(x: self.size.width / 2, y: self.size.height / 2)
            
            // Create a label node for the play button text
            let playLabel = SKLabelNode(text: "Play")
            playLabel.fontColor = .white
            playLabel.fontSize = 24
            playLabel.position = CGPoint(x: 0, y: -10) // Adjust this value to position the text inside the box
            
            playButtonBox.name = "playButton" // Set the name property
            
            // Add the label node as a child of the button box
            playButtonBox.addChild(playLabel)
            
            // Add the play button box to the scene
            self.addChild(playButtonBox)
        }
        
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            for touch in touches {
                let location = touch.location(in: self)
                
                // Check if the touch is on the play button
                if let node = self.atPoint(location) as? SKShapeNode, node.name == "playButton" {
                    // Perform the action when the play button is tapped
                    print("Play button tapped!")
                    
                    // Add your code here to perform the desired action
                    
                    //Go to Tutorial
                    // Create and present the scene
                    // Create and present the scene
                    if let tutorialScene = SKScene(fileNamed: "Tutorial") {
                        tutorialScene.scaleMode = .fill
                        
                        // Present the TutorialScene
                        self.view?.presentScene(tutorialScene)
                        
                    }
                    /// added this for demo, to work with one code file
                    view?.presentScene(Tutorial())
                }
            }
        }
    }
    
    class Tutorial: SKScene {
        
        override func didMove(to view: SKView) {
            size = view.bounds.size
            scaleMode = .resizeFill
            print("Tutorial scene did move to view.") // Confirm that the scene's didMove(to:) method is called
            
            // Create a label node
            let labelNode = SKLabelNode(text: "Block Maze")
            labelNode.fontColor = SKColor.white // Set label text color
            labelNode.fontSize = 24 // Set label font size
            
            // Set position of the label just below the top with a fixed margin
            let topMargin: CGFloat = 100 // Adjust this value for the desired margin
            labelNode.position = CGPoint(x: self.size.width / 2, y: self.size.height - topMargin)
            
            // Add the label node to the scene
            self.addChild(labelNode)
            
            // Print the position of the label
            print("Label position: \(labelNode.position)")
        }
    }