SwiftUI で ps4 の DUALSHOCK 4 のボタン検出

iOS

iOS 13 から iPhone, iPadで、ps4 のワイヤレスコントローラー、DUALSHOK 4の接続が正式にサポートされました。

Appleは2019年06月に開催されたWWDC 2019の中で、定額制ゲーム配信サービス「Apple Arcade」を開始するのに伴い、これまでMFi認証を取得したコントローラーのみをサポートしてきたGame Controller frameworkをアップデートし、Sony PlayStation 4の「DualShock 4」およびMicrosoft Xbox Oneの「Xboxワイヤレスコントローラー」をtvOS 13だけでなくiOS 13/iPadOSやmacOS 10.15 CatalinaなどのAppleOSでサポートすると発表しました。

iOS 13ではPS4のDualShock 4のBluetooth接続がサポート
https://applech2.com/archives/20190919-ios-13-iphone-support-sony-ps4-dualshock-4-and-xbox-wireless-controller-over-bluetooth.html

iOS 13より前でも他の Game Controller をサポートしていたので、iOS 13 より前のアプリでも、Game Controller Frameworkに対応していれば、DUALSHOCK 4で操作できる可能性があります。

私の場合 iOS版 FF9, 聖剣伝説2 アプリが、DUALSHOCK 4で操作できることを確認しました。素晴らしいですね!

さて、それでは早速 SwiftUI から DUALSHOCK 4のボタンを検出できるコードを見ていきましょう。

以下のコードを実行する前に iPhone と DUALSHOCK 4を Bluetooth でリンクする必要があります。

以下の参考にして接続してください。

iOS 13の新機能:iPhone/iPadとPS4コントローラの繋ぎ方・使い方を解説
https://mobilelaby.com/blog-entry-how-to-connect-ps4-controller.html

接続できたら、以下のコードを Xcode で実行してください。

実行中にボタンを押すと、デバッグコンソールに各ボタンが押された旨の表示が print によって出ます。

ContentView.swift

import SwiftUI
import GameController

struct ContentView: View {
    var body: some View {
        Group {
            EmptyView()
        }
        .onReceive(NotificationCenter.default.publisher(for: .GCControllerDidConnect))
        { notification in
            print("GCControllerDidConnect")
            
            guard let controller = notification.object as? GCController,
                  let gamepad = controller.extendedGamepad else {
                return
            }
            
            print(String(describing: controller.vendorName))
            
            handleGamePad(gamepad)
        }
        .onReceive(NotificationCenter.default.publisher(for: .GCControllerDidDisconnect))
        { notification in
            print("GCControllerDidDisConnect")
        }
    }
}

func handleGamePad(_ gamepad: GCExtendedGamepad) {
    // △ ○ × □
    var triangleButton: GCControllerButtonInput?
    var circleButton: GCControllerButtonInput?
    var crossButton:GCControllerButtonInput?
    var rectButton:GCControllerButtonInput?
    
    // ↑ ← ↓ → key
    var directionPad: GCControllerDirectionPad?
    
    // thumbstich
    var leftThumbstick: GCControllerDirectionPad?
    var rightThumbstick: GCControllerDirectionPad?
    var leftThumbstickButton: GCControllerButtonInput?
    var rightThumbstickButton: GCControllerButtonInput?
    
    // L1, L2, R1, R2 button
    var l1Button: GCControllerButtonInput?
    var l2Button: GCControllerButtonInput?
    var r1Button: GCControllerButtonInput?
    var r2Button: GCControllerButtonInput?
    
    // setting
    var optionsButton: GCControllerButtonInput?
    var shareButton: GCControllerButtonInput?
    
    // △ ○ × □
    rectButton = gamepad.buttonX
    triangleButton = gamepad.buttonY
    circleButton = gamepad.buttonB
    crossButton = gamepad.buttonA
    
    // ↑ ← ↓ → key
    directionPad = gamepad.dpad
    
    // thumbstich
    leftThumbstick = gamepad.leftThumbstick
    rightThumbstick = gamepad.rightThumbstick
    leftThumbstickButton = gamepad.leftThumbstickButton
    rightThumbstickButton = gamepad.rightThumbstickButton
    
    // L1, L2, R1, R2 button
    l1Button = gamepad.leftShoulder
    l2Button = gamepad.leftTrigger
    r1Button = gamepad.rightShoulder
    r2Button = gamepad.rightTrigger
    
    // setting
    optionsButton = gamepad.buttonMenu
    shareButton = gamepad.buttonOptions
    
    // △ ○ × □
    triangleButton?.pressedChangedHandler = { (input, value, isPressed) in
        guard isPressed else { return }
        
        print("press △")
    }
    
    circleButton?.pressedChangedHandler = { (input, value, isPressed) in
        guard isPressed else { return }
        
        print("press ○")
    }
    
    crossButton?.pressedChangedHandler = { (input, value, isPressed) in
        guard isPressed else { return }
        
        print("press ×")
    }
    
    rectButton?.pressedChangedHandler = { (input, value, isPressed) in
        guard isPressed else { return }
        
        print("press □")
    }
    
    // ↑ ← ↓ → key
    directionPad?.valueChangedHandler = {(_ dPad: GCControllerDirectionPad,
                                          _ x: Float,
                                          _ y: Float) -> Void in
        if x == 0 && y == 0 {
            return
        }
        
        print("x: \(x), y: \(y)")
        
        if x == 1.0 {
            print("→")
        }
        
        if x == -1.0 {
            print("←")
        }
        
        if y == 1.0 {
            print("↑")
        }
        
        if y == -1.0 {
            print("↓")
        }
    }
    
    // thumbstich
    leftThumbstick?.valueChangedHandler = {(_ dpad: GCControllerDirectionPad,
                                            _ xValue: Float,
                                            _ yValue: Float) -> Void in
        print("left stick X: \(xValue)")
        print("left stick Y: \(yValue)")
    }
    
    rightThumbstick?.valueChangedHandler = {(_ dpad: GCControllerDirectionPad,
                                             _ xValue: Float,
                                             _ yValue: Float) -> Void in
        print("right stick X: \(xValue)")
        print("right stick Y: \(yValue)")
    }
    
    leftThumbstickButton?.valueChangedHandler = {(_ button: GCControllerButtonInput,
                                                  _ value: Float,
                                                  _ pressed: Bool) -> Void in
        if pressed {
            print("left thumbstick pressed")
        }
    }
    
    rightThumbstickButton?.valueChangedHandler = {(_ button: GCControllerButtonInput,
                                                   _ value: Float,
                                                   _ pressed: Bool) -> Void in
        if pressed {
            print("right thumbstick presded")
        }
    }
    
    // L1, L2, R1, R2 button
    l1Button?.valueChangedHandler = {(_ button: GCControllerButtonInput,
                                      _ value: Float,
                                      _ pressed: Bool) -> Void in
        if pressed {
            print("L1")
        }
    }
    
    l2Button?.valueChangedHandler = {(_ button: GCControllerButtonInput,
                                      _ value: Float,
                                      _ pressed: Bool) -> Void in
        if pressed {
            print("L2")
        }
    }
    
    r1Button?.valueChangedHandler = {(_ button: GCControllerButtonInput,
                                      _ value: Float,
                                      _ pressed: Bool) -> Void in
        if pressed {
            print("R1")
        }
    }
    
    r2Button?.valueChangedHandler = {(_ button: GCControllerButtonInput,
                                      _ value: Float,
                                      _ pressed: Bool) -> Void in
        if pressed {
            print("R2")
        }
    }
    
    // setting
    optionsButton?.valueChangedHandler = {(_ button: GCControllerButtonInput,
                                           _ value: Float,
                                           _ pressed: Bool) -> Void in
        if pressed {
            print("OPTIONS tapped")
        }
    }
    
    shareButton?.valueChangedHandler = {(_ button: GCControllerButtonInput,
                                         _ value: Float,
                                         _ pressed: Bool) -> Void in
        if pressed {
            print("share tapped")
        }
    }
}

コードは以下のサイトを参考にさせていただきました。

http://harumi.sakura.ne.jp/wordpress/2019/08/21/ios13から対応のdualshock-4のを試す/

それではよい SwiftUI ライフを!

SwiftUIを学ぶのにおすすめの本

SwiftUI 徹底入門

SwiftUIではじめるiPhoneアプリプログラミング入門

iOS/macOS UIフレームワーク SwiftUIプログラミング

コメント

タイトルとURLをコピーしました