Playing a local video in a SpriteKit scene

186 views Asked by At

Working on taking around 23 ".mov" files - short animations - that will piece together to make a children's book, with a choose-your-own-adventure style to it.

I feel like I have a decent grasp on what needs to be done on a macro sense, present the video in a scene, once the video finishes create x number of buttons that will launch the user into the next chapter/scene. Furtherdown the road will add some simple animations and music/sound as well.

However, I am having some issues with playing the videos, I was successful in creating a scene with a screenshot as the background which had a button to launch the next scene, but for adding the video, I am both lost and having a hard time finding resources on the topic.

Apple Dev's solution is to use:



    let sample = SKVideoNode(fileNamed: "sample.mov")
    sample.position = CGPoint(x: frame.midX,
                          y: frame.midY)
    addChild(sample)
    sample.play()


I tried this, albeit probably improperly, in my GameScene.swift file.

    import SpriteKit
    import GameplayKit

        class GameScene: SKScene {
    
        private var label : SKVideoNode?
    
        override func didMove(to view: SKView) {
        let sample = SKVideoNode(fileNamed: "V1.mov")
        sample.position = CGPoint(x: frame.midX,
                                  y: frame.midY)
        addChild(sample)
        sample.play()
        
        }
    }

I was hoping this would be - and who knows, maybe it still is, my golden egg of a solution, cause then the rest would really be just a copy and paste session with multiple scenes, but I was not able to get the video to load.

Do I need to further connect the SKVideoNode to the "V1.mov" file?

Furthermore, I think some of my confusion stems from whether or not I implement the video programatically or through the .sks / storyboard files, is one easier than the other?

Also am aware that this question may be more-so to do with something very rudimentary that I've brushed over in my learning process, and if that is the case, I apologize for my over zealousness :p

Appreciate any advice you folks can give would be greatly appreciated:)

UPDATE:

Okay, so here is the code I have so far which works, it is the skeleton framework for the book I am making, it's a choose your own adventure, so each scene has multiple options to take you to other scenes:

    import SpriteKit
import Foundation
import SceneKit

class v1Scene: SKScene {
    
    var trashButtonNode:SKSpriteNode!
    var bikeButtonNode:SKSpriteNode!
    var backButtonNode:SKSpriteNode!
    
    override func didMove(to view: SKView) {
        
        trashButtonNode = (self.childNode(withName: "trashButton") as? SKSpriteNode)
        bikeButtonNode = (self.childNode(withName: "bikeButton") as? SKSpriteNode)
        backButtonNode = (self.childNode(withName: "backButton") as? SKSpriteNode)
        
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        let v2Scene = v2Scene(fileNamed: "v2Scene")
        let v3Scene = v3Scene(fileNamed: "v3Scene")
        let MainMenu = MainMenu(fileNamed: "MainMenu")
        
        if let location = touch?.location(in: self) {
            let nodesArray = self.nodes(at: location)
            
            if nodesArray.first?.name == "trashButton" {
                let transistion = SKTransition.fade(withDuration: 2)
                self.view?.presentScene(v2Scene!, transition: transistion)
                
            } else if nodesArray.first?.name == "bikeButton" {
                let transistion = SKTransition.fade(withDuration: 2)
                self.view?.presentScene(v3Scene!, transition: transistion)
                
            } else if nodesArray.first?.name == "backButton" {
                let transistion = SKTransition.fade(withDuration: 2)
                self.view?.presentScene(MainMenu!, transition: transistion)
                }
                
            }
        }
    }

What I am trying to achieve is that when the "trashButton" is clicked, v2Scene is launched and a video automatically plays. Each video is a "page" in a book, so need to assign each video to a scene.

The files are in a folder in my project and the Assets.xcasstes folder, although, the .mov files do not seem to work in that folder.

Thanks, Owen

1

There are 1 answers

0
Swift Dev Journal On

Because the video files are in their own folder, you won't be able to use the SKVideoNode init that takes a file name. You must use the init that takes a URL as an argument.

To get the URL for a video file, you must call the Bundle class's url function, supplying the file name, extension, and the name of the path to the folder where your video files are.

The following code shows what you need to do to create a video node from a file in the app bundle, using the V1.mov file from your question as the example:

let bundle = Bundle.main
if let videoURL = bundle.url(forResource: "V1", 
    withExtension: "mov", 
    subdirectory "FolderName" {

    sample = SKVideoNode(url: videoURL)
}

FolderName is the folder where the video files are.

Make sure the folder with the video files is in the app target's Copy Bundle Resources build phase. The folder must be in this build phase for Xcode to copy it to the app bundle when it builds the project. Take the following steps to view the build phases for a target:

  1. Open the project editor by selecting the project file on the left side of the project window.
  2. Select the target on the left side of the project editor.
  3. Click the Build Phases button at the top of the project editor.