5

ゲームに実装ReplayKitしましたSpriteKitが、すべてがGameViewController記録ボタン内で行われるため、表示されるのが早すぎます。GameViewController以下の私のクラスをご覧ください:

class GameViewController: UIViewController, RPPreviewViewControllerDelegate {

var videoRecButton: UIButton!
var videoRecImage: UIImage!

override func viewDidLoad() {
    super.viewDidLoad()

    let skView = self.view as? SKView

    if skView?.scene == nil  {
        skView?.showsFPS = true
        skView?.showsNodeCount = true
        skView?.showsPhysics = true
        skView?.ignoresSiblingOrder = false

        //starting the game with the Poster Scene
        let posterScene = PosterScene(size: skView!.bounds.size)
        posterScene.scaleMode = .aspectFill
        skView?.presentScene(posterScene)
    }

    videoRecButton = UIButton(type: .custom)
    videoRecImage = UIImage(named:"videoRecButton.png")

    videoRecButton.frame = CGRect(x:0, y: 0, width: (videoRecImage?.size.width)!, height: (videoRecImage?.size.height)!)
    videoRecButton.setImage(videoRecImage, for: .normal)
    videoRecButton.addTarget(self, action:#selector(self.videoRecButtonClicked), for: .touchUpInside)
    self.view.addSubview(videoRecButton)
}

func videoRecButtonClicked() {
    print("Button Clicked")
    startRecording()
}

func startRecording() {
    let recorder = RPScreenRecorder.shared()

    recorder.startRecording{ [unowned self] (error) in
        if let unwrappedError = error {
            print(unwrappedError.localizedDescription)
        } else {

            self.videoRecButton.addTarget(self, action:#selector(self.stopRecording), for: .touchUpInside)
        }
    }
}

func stopRecording() {
    let recorder = RPScreenRecorder.shared()

    recorder.stopRecording { [unowned self] (preview, error) in
        self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Start", style: .plain, target: self, action: #selector(self.startRecording))

        if let unwrappedPreview = preview {
            unwrappedPreview.previewControllerDelegate = self
            self.present(unwrappedPreview, animated: true)
        }
    }
}

func previewControllerDidFinish(_ previewController: RPPreviewViewController) {
    dismiss(animated: true)
}

override var shouldAutorotate: Bool {
    return true
}

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

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Release any cached data, images, etc that aren't in use.
}

override var prefersStatusBarHidden: Bool {
    return true
}
}
  1. likeクラスから継承するクラスからstartRecordingand関数を呼び出すにはどうすればよいですか?stopRecordingSKSceneGameScene

  2. クラスvideoRecButtonからボタンを有効、無効、非表示にするにはどうすればよいですか?GameScene

アップデート

crashoverride777 からの回答に基づいて、SKSceneクラスに次のコードを配置しましたが、録画されたビデオのプレビューを含むナビゲーション コントローラーが表示される前に、画面がわずか数秒間記録されます。録画されたビデオはただの黒い画面で、キャンセル ボタンと保存ボタンは反応しません。

    func startRecording() {
    let recorder = RPScreenRecorder.shared()

    if #available(iOS 10.0, *) {
        recorder.startRecording{ [unowned self] (error) in
            if let unwrappedError = error {
                print(unwrappedError.localizedDescription)
            } else {

                self.stopRecording()

            }
        }
    } else {
        // Fallback on earlier versions
    }
}

func stopRecording() {
    let recorder = RPScreenRecorder.shared()

    recorder.stopRecording { [unowned self] (preview, error) in
        self.view?.window?.rootViewController?.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Start", style: .plain, target: self, action: #selector(self.startRecording))

        if let unwrappedPreview = preview {
            unwrappedPreview.previewControllerDelegate = self
            self.view?.window?.rootViewController?.present(unwrappedPreview, animated: true)
        }
    }

}

func previewControllerDidFinish(_ previewController: RPPreviewViewController) {
    view?.window?.rootViewController?.dismiss(animated: true)
}

録音ボタンを作成しました:

let videoRecButtonSprite = SKSpriteNode(imageNamed: "videoButton")
videoRecButtonSprite.position = CGPoint(x: self.frame.width/15, y: self.frame.height - self.frame.height/12)
self.addChild(videoRecButtonSprite)

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    for touch: AnyObject in touches {
        let location = touch.location(in: self)
        if videoRecButtonSprite.contains(location){
            startRecording()
        }
    }
}
4

2 に答える 2

6

ボタンは GameViewController で作成するのではなく、SKScene で直接作成してください。SpriteKit ゲームの UI に GameViewController を使用することはお勧めできません。

SpriteKit でボタンを作成する方法に関するチュートリアルはたくさんあります。

ReplayKit に関しては、必要な SKScene で直接使用できます。すでに持っているコードを取得して、関連するシーンに移動するだけです。

SKScene でプレビュー ビュー コントローラーを表示するには、次のように言います。

view?.window?.rootViewController?.present(unwrappedPreview, animated: true)

また、記録を停止した後、View Controller を表示していることにも気付きました。本当にこれをしたいですか?通常、ゲーム オーバー メニューには、録画を視聴できる別のボタンがあります。

これが一般的なコードです。また、apples Sample game DemoBots をチェックすることをお勧めします。

個人的には Singleton クラスを使用して記録を管理します。このようにして、さまざまなシーンで必要になった場合に備えて、すべてのメソッドを簡単に呼び出すことができます。クラスを開始するには、新しい Swift ファイルを作成し、このコードを追加します。

 class ScreenRecoder: NSObject {

      /// Shared instance
      static let shared = ScreenRecorder()

      /// Preview controller
      var previewController: RPPreviewViewController?

      /// Private singleton init
      private override init() { }
 }

録画を開始するには、このメソッドを ScreenRecorder クラスに追加します。

func start() {
    let sharedRecorder = RPScreenRecorder.shared()

    // Do nothing if screen recording is not available
    guard sharedRecorder.isAvailable else { return }

    // Stop previous recording if necessary
    if sharedRecorder.isRecording {
        stopScreenRecording()
    }

    print("Starting screen recording")

    // Register as the recorder's delegate to handle errors.
    sharedRecorder.delegate = self

    // Start recording
    if #available(iOS 10.0, *) {
        #if os(iOS)
            sharedRecorder.isMicrophoneEnabled = true
            //sharedRecorder.isCameraEnabled = true // fixme
        #endif

        sharedRecorder.startRecording { [unowned self] error in
            if let error = error as? NSError, error.code != RPRecordingErrorCode.userDeclined.rawValue {
                print(error.localizedDescription)
                // Show alert
                return
            }
        }
    } else {
        // Fallback on earlier versions
        sharedRecorder.startRecording(withMicrophoneEnabled: true) { error in
            if let error = error as? NSError, error.code != RPRecordingErrorCode.userDeclined.rawValue {
                print(error.localizedDescription)
                // Show alert
                return
            }
        }
    }
}

録音を停止するには、これを呼び出します。実際にはまだプレビューを表示していません。後で使用するために保存しているだけです。これが通常のやり方です。

 func stop() {
    let sharedRecorder = RPScreenRecorder.shared()

    // Do nothing if screen recording is not available
    guard sharedRecorder.isAvailable else { return }

    // Stop recording
    sharedRecorder.stopRecording { [unowned self] (previewViewController, error) in
        if let error = error {
            // If an error has occurred, display an alert to the user.
            print(error.localizedDescription)
            // Show alert
            return
        }

        print("Stop screen recording")

        if let previewViewController = previewViewController {
            // Set delegate to handle view controller dismissal.
            previewViewController.previewControllerDelegate = self

            /*
             Keep a reference to the `previewViewController` to
             present when the user presses on preview button.
             */
            self.previewViewController = previewViewController
        }
    }
}

ReplayKit デリゲートに準拠する ScreenRecorder クラスで 2 つの拡張機能を作成するよりも。

プレビュー コントローラー デリゲート

 /// RPPreviewViewControllerDelegate
 extension ScreenRecorder: RPPreviewViewControllerDelegate {

     /// Preview controller did finish
    func previewControllerDidFinish(_ previewController: RPPreviewViewController) {
          previewController.dismiss(animated: true, completion: nil)
    }
}

と録音デリゲート

extension ScreenRecorder: RPScreenRecorderDelegate {

      /// Screen recoder did stop with error
      func screenRecorder(_ screenRecorder: RPScreenRecorder, didStopRecordingWithError error: Error, previewViewController: RPPreviewViewController?) {

         // Display the error the user to alert them that the recording failed.
        let error = error as NSError
        if error.code != RPRecordingErrorCode.userDeclined.rawValue {
            print(message: error.localizedDescription)
            // show alert
        }

         // Hold onto a reference of the `previewViewController` if not nil.
         if let previewViewController = previewViewController {
             self.previewViewController = previewViewController     
         }
      }

      /// Screen recoder did change availability
      func screenRecorderDidChangeAvailability(_ screenRecorder: RPScreenRecorder) {
           // e.g update your button UI etc
           // you can use something like delegation to pass something to your SKScenes
     }
}

最後に、プレビューを表示するメソッドを作成します。できれば、ゲーム オーバー メニューのボタンからこれを呼び出します。

func showPreview() {
    guard let previewViewController = previewViewController else { return }

    print("Showing screen recording preview")

    // `RPPreviewViewController` only supports full screen modal presentation.
    previewViewController.modalPresentationStyle = .fullScreen

    let rootViewController = UIApplication.shared.keyWindow?.rootViewController
    rootViewController?.present(previewViewController, animated: true, completion:nil)
}

これで、プロジェクト内の好きな場所でメソッドを呼び出すことができます

ScreenRecorder.shared.start()
ScreenRecorder.shared.stop()
ScreenRecorder.shared.showPreview() // call stop before calling this

このコードは、DemoBot からほとんどそのままです。

画面録画を処理する最も良い方法は、メイン メニューに自動録画ボタンを作成することだと思います。UserDefaults を使用して、オン/オフ状態を保存します。オンにすると、ゲームプレイの開始時に startRecording を呼び出し、ゲーム オーバー時に stop recording を呼び出します。ゲーム オーバー メニューにプレビュー ボタンを表示して、ユーザーが必要に応じて録画を視聴できるようにします。

お役に立てれば

于 2016-10-02T12:46:23.083 に答える
0

DemoBot は難しいです。ReplayKit、RPPreviewViewControllerDelegate、RPScreenRecorderDelegate を忘れずにインポートしてください。最終的なコードを GitHub などに投稿できますか、crashoverride777. これは私が書いたもので、プレビュー表示を取得できません:

func startRecording() {
    let sharedRecorder = RPScreenRecorder.shared()

    // Do nothing if screen recording is not available
    guard sharedRecorder.isAvailable else { return }

    // Stop previous recording if necessary
    if sharedRecorder.isRecording {
        stopScreenRecording()
    }

    print("Starting screen recording")

    // Register as the recorder's delegate to handle errors.
    sharedRecorder.delegate = self

    // Start recording
    sharedRecorder.isMicrophoneEnabled = true
    //sharedRecorder.isCameraEnabled = true // fixme


    sharedRecorder.startRecording { error in
        if let error = error as NSError?, error.code != RPRecordingErrorCode.userDeclined.rawValue {
            print(error.localizedDescription)
            // Show alert
            return
        }
    }
}

func stopScreenRecording() {
    let sharedRecorder = RPScreenRecorder.shared()

    // Do nothing if screen recording is not available
    guard sharedRecorder.isAvailable else { return }

    // Stop recording
    sharedRecorder.stopRecording { [unowned self] (previewViewController, error) in
        if let error = error {
            // If an error has occurred, display an alert to the user.
            print(error.localizedDescription)
            // Show alert
            return
        }

        print("Stop screen recording")

        if let previewViewController = previewViewController {
            // Set delegate to handle view controller dismissal.
            previewViewController.previewControllerDelegate = self

            /*
             Keep a reference to the `previewViewController` to
             present when the user presses on preview button.
             */
            self.previewController = previewViewController
        }
    }
}

func previewControllerDidFinish(_ previewController: RPPreviewViewController) {
    view?.window?.rootViewController?.dismiss(animated: true)
}
于 2017-02-09T06:09:27.880 に答える