简体   繁体   English

如何在SpriteKit中将“相机视图”作为背景图像?

[英]How can I make Camera View as my background image in SpriteKit?

I wish to set my iPhone's camera view as background image in my Sprite Kit game. 我希望在Sprite Kit游戏中将iPhone的相机视图设置为背景图像。 How to go about doing that ? 如何去做呢? Help would be highly appreciated! 帮助将不胜感激!

import UIKit
    import AVFoundation
    import AssetsLibrary

class ViewController: UIViewController, AVCaptureFileOutputRecordingDelegate {

    var SessionRunningAndDeviceAuthorizedContext = "SessionRunningAndDeviceAuthorizedContext"

@available(iOS 4.0, *)
    public func fileOutput(_ captureOutput: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {

    }


    // MARK: property

    var sessionQueue: DispatchQueue!
    var session: AVCaptureSession?
    var videoDeviceInput: AVCaptureDeviceInput?

    var deviceAuthorized: Bool  = false
    var backgroundRecordId: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
    var sessionRunningAndDeviceAuthorized: Bool {
        get {
            return (self.session?.isRunning != nil && self.deviceAuthorized )
        }
    }

    var runtimeErrorHandlingObserver: AnyObject?
    var lockInterfaceRotation: Bool = false

    @IBOutlet weak var previewView: AVCamPreviewView!

 override func viewDidLoad() {
        super.viewDidLoad()
 let session: AVCaptureSession = AVCaptureSession()
        session.sessionPreset = AVCaptureSession.Preset.photo
        self.session = session

        self.previewView.session = session

        self.checkDeviceAuthorizationStatus()

        let sessionQueue: DispatchQueue = DispatchQueue(label: "KehoeGames.whatever",attributes: [])

        self.sessionQueue = sessionQueue
        sessionQueue.async {
            self.backgroundRecordId = UIBackgroundTaskInvalid

            let videoDevice: AVCaptureDevice! = ViewController.deviceWithMediaType(AVMediaType.video.rawValue, preferringPosition: AVCaptureDevice.Position.back)
            var error: NSError? = nil


            var videoDeviceInput: AVCaptureDeviceInput?
            do {
                videoDeviceInput = try AVCaptureDeviceInput(device: videoDevice)
            } catch let error1 as NSError {
                error = error1
                videoDeviceInput = nil
            } catch {
                fatalError()
            }

            if (error != nil) {
                print(error)
                let alert = UIAlertController(title: "Error", message: error!.localizedDescription
                    , preferredStyle: .alert)
                alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
                self.present(alert, animated: true, completion: nil)
            }

            if session.canAddInput(videoDeviceInput!){
                session.addInput(videoDeviceInput!)
                self.videoDeviceInput = videoDeviceInput

                DispatchQueue.main.async {


                    let orientation: AVCaptureVideoOrientation =  AVCaptureVideoOrientation(rawValue: UIDevice.current.orientation.rawValue)!

                    (self.previewView.layer as! AVCaptureVideoPreviewLayer).connection?.videoOrientation = .portrait
                    (self.previewView.layer as! AVCaptureVideoPreviewLayer).videoGravity = AVLayerVideoGravity.resizeAspectFill

                }
            }
            }
        }
}

override func viewWillAppear(_ animated: Bool) {
        self.sessionQueue.async {

            self.addObserver(self, forKeyPath: "sessionRunningAndDeviceAuthorized", options: [.old , .new] , context: &SessionRunningAndDeviceAuthorizedContext)

            NotificationCenter.default.addObserver(self, selector: #selector(ViewController.subjectAreaDidChange(_:)), name: NSNotification.Name.AVCaptureDeviceSubjectAreaDidChange, object: self.videoDeviceInput?.device)

            self.runtimeErrorHandlingObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.AVCaptureSessionRuntimeError, object: self.session, queue: nil) {
                (note: Notification?) in
                self.sessionQueue.async { [unowned self] in
                    if let sess = self.session {
                        sess.startRunning()
                    }

                }
            }
            self.session?.startRunning()
        }
    }

override func viewWillDisappear(_ animated: Bool) {

        self.sessionQueue.async {

            if let sess = self.session {
                sess.stopRunning()

                NotificationCenter.default.removeObserver(self, name: NSNotification.Name.AVCaptureDeviceSubjectAreaDidChange, object: self.videoDeviceInput?.device)
                NotificationCenter.default.removeObserver(self.runtimeErrorHandlingObserver!)

                self.removeObserver(self, forKeyPath: "sessionRunningAndDeviceAuthorized", context: &SessionRunningAndDeviceAuthorizedContext)
            }
        }
    }

 override var shouldAutorotate : Bool {
        return !self.lockInterfaceRotation
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
            return super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)

    }

@objc func subjectAreaDidChange(_ notification: Notification){
        let devicePoint: CGPoint = CGPoint(x: 0.5, y: 0.5)
        self.focusWithMode(AVCaptureDevice.FocusMode.continuousAutoFocus, exposureMode: AVCaptureDevice.ExposureMode.continuousAutoExposure, point: devicePoint, monitorSubjectAreaChange: false)
    }

    class func deviceWithMediaType(_ mediaType: String, preferringPosition:AVCaptureDevice.Position) -> AVCaptureDevice? {

        var devices = AVCaptureDevice.devices(for: AVMediaType(rawValue: mediaType));

        if (devices.isEmpty) {
            print("This device has no camera. Probably the simulator.")
            return nil
        } else {
            var captureDevice: AVCaptureDevice = devices[0]

            for device in devices {
                if (device as AnyObject).position == preferringPosition {
                    captureDevice = device
                    break
                }
            }
            return captureDevice
        }
    }

 func checkDeviceAuthorizationStatus(){
        let mediaType:String = AVMediaType.video.rawValue;

        AVCaptureDevice.requestAccess(for: AVMediaType(rawValue: mediaType)) { (granted: Bool) in
            if granted {
                self.deviceAuthorized = true;
            } else {

                DispatchQueue.main.async {
                    let alert: UIAlertController = UIAlertController(
                        title: "AVCam",
                        message: "AVCam does not have permission to access camera",
                        preferredStyle: UIAlertControllerStyle.alert)
                    let action = UIAlertAction(title: "OK", style: .default) { _ in }
                    alert.addAction(action)
                    self.present(alert, animated: true, completion: nil)
                }
                self.deviceAuthorized = false;
            }
        }
    }

And create a new class called AVCamPreviewView 并创建一个名为AVCamPreviewView的新类

import Foundation
import UIKit
import AVFoundation


class AVCamPreviewView: UIView {

    var session: AVCaptureSession? {
        get {
            return (self.layer as! AVCaptureVideoPreviewLayer).session
        }
        set (session) {
            (self.layer as! AVCaptureVideoPreviewLayer).session = session
        }
    }

    override class var layerClass : AnyClass {
        return AVCaptureVideoPreviewLayer.self
    }
}

You should be able to have the Preview View at the back of the Scene and then have your game on top of it. 您应该能够在“场景”的背面具有“预览视图”,然后将游戏置于其顶部。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM