Where to call NotificationCenter.default.addObserver() ? in my Xcode Game Project

155 views Asked by At

Where to call NotificationCenter.default.addObserver() ? in my Xcode Game Project

I successfully call the following from my func application (AppDelegate), but when I toggle the Gamepad on/off, my selectors are not being called.

class GameScene: SKScene {
    
    func ObserveForGameControllers() {
        
    //  print("ObserveForGameControllers")
        
        NotificationCenter.default.addObserver(
                    self,
                    selector: #selector(connectControllers),
                    name: NSNotification.Name.GCControllerDidConnect,
                    object: nil)
        
        NotificationCenter.default.addObserver(
                    self,
                    selector: #selector(disconnectControllers),
                    name: NSNotification.Name.GCControllerDidDisconnect,
                    object: nil)
        
    }   // ObserveForGameControllers

}

My selectors look like this:

@objc func connectControllers() {}
@objc func disconnectControllers() {}

One last thing:

Here are my Gamepad settings in my Project

It seems I really need some suggestions here.

Appreciate it.

EDIT

I have been in contact with a very talented jrturton on trying to discover why I am unable to detect the presence of my Gamepad as documented above.

He has asked for a more complete presentation of my Swift code. I initially thought of Dropbox, but he has asked for this EDIT .. so here goes:

I began with a iOS Game Project which presented me with AppDelegate, GameScene, GameViewController + Storyboard.

I’ve already covered AppDelegate above, which per jrturton’s recommendation is now reduced to the standard AppDelegate func’s which essentially are empty, such as:

func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions
                 launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    // currently empty

}

Next, the GameScene ..

import SwiftUI
import WebKit
import SpriteKit
import GameplayKit
import GameController


class GameScene: SKScene {
    
    override func sceneDidLoad() {
        
        super.sceneDidLoad()
        
    //  print("sceneDidLoad")
        
        ObserveForGameControllers()
        
    }   // sceneDidLoad


    func ObserveForGameControllers() {
        
    //  print("ObserveForGameControllers")
        
        NotificationCenter.default.addObserver(
                    self,
                    selector: #selector(connectControllers),
                    name: NSNotification.Name.GCControllerDidConnect,
                    object: nil)
        
        NotificationCenter.default.addObserver(
                    self,
                    selector: #selector(disconnectControllers),
                    name: NSNotification.Name.GCControllerDidDisconnect,
                    object: nil)
        
    }   // ObserveForGameControllers
    
    
    @objc func connectControllers() {
        
    //  print("CONNECT")

        self.isPaused = false
        
        var indexNumber = 0
        
        for controller in GCController.controllers() {
            
            if controller.extendedGamepad != nil {
                controller.playerIndex = GCControllerPlayerIndex.init(rawValue: indexNumber)!
                
                indexNumber += 1
                setupControllerControls(controller: controller)
            }
            
        }
        
    }   // connectControllers

    
    @objc func disconnectControllers() {
        
    //  print("DIS-CONNECT")

        self.isPaused = true
        
    }   // disconnectControllers
    

    func setupControllerControls(controller: GCController) {
        
        controller.extendedGamepad?.valueChangedHandler = {
            (gamepad: GCExtendedGamepad, element: GCControllerElement) in
            
            self.controllerInputDetected(gamepad: gamepad,
                                         element: element,
                                         index: controller.playerIndex.rawValue)
        }
        
    }   // setupControllerControls


    func controllerInputDetected(gamepad: GCExtendedGamepad,
                                 element: GCControllerElement,
                                 index: Int) {
        
        // A-Button
        if (gamepad.buttonA == element)
        {
            if (gamepad.buttonA.value != 0)
            {
                // These print(..) statements will be replaced later
                // by code to access my Javascript methods.
                print("movePaddleDown")
            }
        }
        
        // B-Button
        else if (gamepad.buttonB == element)
        {
            if (gamepad.buttonB.value != 0)
            {
                print("movePaddleRight")
            }
        }
        
        // Y-Button
        else if (gamepad.buttonY == element)
        {
            if (gamepad.buttonY.value != 0)
            {
                print("movePaddleUp")
            }
        }
        
        // X-Button
        else if (gamepad.buttonX == element)
        {
            if (gamepad.buttonX.value != 0)
            {
                print("movePaddleLeft")
            }
        }
        
        // leftShoulder
        else if (gamepad.leftShoulder == element)
        {
            if (gamepad.leftShoulder.value != 0)
            {
                print("cyclePages")
            }
        }
        
        // rightShoulder
        else if (gamepad.rightShoulder == element)
        {
            if (gamepad.rightShoulder.value != 0)
            {
                print("newGame")
            }
        }
        
        // leftTrigger
        else if (gamepad.leftTrigger == element)
        {
            if (gamepad.leftTrigger.value != 0)
            {
                print("pauseGame")
            }
        }
        
        // rightTrigger
        else if (gamepad.rightTrigger == element)
        {
            if (gamepad.rightTrigger.value != 0)
            {
                print("resumeGame")
            }
        }
        
        // Left Thumbstick
        else if (gamepad.leftThumbstick == element)
        {
            if (gamepad.leftThumbstick.xAxis.value > 0)
            {
                print("movePaddleRight")
            }
            else if (gamepad.leftThumbstick.xAxis.value < 0)
            {
                print("movePaddleLeft")
            }
            else if (gamepad.leftThumbstick.xAxis.value == 0)
            {
                print("decreaseSpeed")
            }
            else if (gamepad.leftThumbstick.yAxis.value > 0)
            {
                print("movePaddleDown")
            }
            else if (gamepad.leftThumbstick.yAxis.value < 0)
            {
                print("movePaddleUp")
            }
            else if (gamepad.leftThumbstick.yAxis.value == 0)
            {
                print("decreaseSpeed")
            }
        }
        
        // Right Thumbstick
        if (gamepad.rightThumbstick == element)
        {
            if (gamepad.rightThumbstick.xAxis.value > 0)
            {
                print("movePaddleRight")
            }
            else if (gamepad.rightThumbstick.xAxis.value < 0)
            {
                print("movePaddleLeft")
            }
            else if (gamepad.rightThumbstick.xAxis.value == 0)
            {
                print("decreaseSpeed")
            }
            else if (gamepad.rightThumbstick.yAxis.value > 0)
            {
                print("movePaddleDown")
            }
            else if (gamepad.rightThumbstick.yAxis.value < 0)
            {
                print("movePaddleUp")
            }
            else if (gamepad.rightThumbstick.yAxis.value == 0)
            {
                print("decreaseSpeed")
            }
        }
        
        // D-Pad
        else if (gamepad.dpad == element)
        {
            if (gamepad.dpad.xAxis.value > 0)
            {
                print("scrollWindowRight")
            }
            else if (gamepad.dpad.xAxis.value < 0)
            {
                print("scrollWindowLeft")
            }
            else if (gamepad.dpad.yAxis.value > 0)
            {
                print("scrollWindowDown")
            }
            else if (gamepad.dpad.yAxis.value < 0)
            {
                print("scrollWindowUp")
            }
        }
        
    }   // controllerInputDetected

}   // class GameScene: SKScene

Now, the GameViewController ..

import UIKit
import SpriteKit
import GameplayKit
import WebKit


// This is now available across Classes
var theWebView: WKWebView!


class GameViewController: UIViewController, WKNavigationDelegate {
    
    override func loadView() {
        
    //  print("loadView")
        
        let webConfiguration = WKWebViewConfiguration()
        theWebView = WKWebView(frame: .zero, configuration: webConfiguration)
        theWebView.navigationDelegate = self
        view = theWebView
        
    }   // loadView
    
    
    override func viewDidLoad() {
        
        super.viewDidLoad()
        
    //  print("viewDidLoad")
               
        loadURL(webAddress: "https://www.lovesongforever.com/firstgame")
        
    }   // viewDidLoad
    
    
    func loadURL(webAddress: String) {
        
        let theURL = URL(string: webAddress)
        let theRequest = URLRequest(url: theURL!)
        theWebView.load(theRequest)
        theWebView.allowsBackForwardNavigationGestures = false

    }   // loadURL

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

    
    override var prefersStatusBarHidden: Bool {
        
        return true
        
    }   // prefersStatusBarHidden
    
}   // class GameViewController

Note that when I RUN my iOS App, thanks to the overridden loadView() above, it presents the following in the Simulator:

Simulator presentation

But, that’s is as far as it goes, because pressing all the buttons on my Gamepad does not result in detection of my Gamepad, as evidenced when I UN-comment all the above print(..) statements. In particular, those within:

@objc func connectControllers() and @objc func disconnectControllers() and func controllerInputDetected( .. )

So, hopefully that is all there currently is ..

1

There are 1 answers

0
jrturton On

You are doing this in your app delegate:

let itsGameScene = GameScene() 
itsGameScene.ObserveForGameControllers()

You're creating an instance of GameScene, making it listen for notifications (adding self as the observer)... and then probably throwing that instance away.

Your game isn't actually using SpriteKit, and SpriteKit isn't needed to deal with game controllers, you just need GameController.

You have no need to create this scene at all. The best place to observe the game controller notifications would be in your GameViewController in viewDidLoad. Move the code (the observation method and the controller-related ones) you had in your scene into the view controller, and delete the scene file.