├── GameCenterMultiplayer
├── Assets.xcassets
│ ├── Contents.json
│ ├── Animations
│ │ ├── Contents.json
│ │ ├── One
│ │ │ ├── Contents.json
│ │ │ ├── one_hit.imageset
│ │ │ │ ├── blue_hit_2.png
│ │ │ │ └── Contents.json
│ │ │ ├── one_attack.imageset
│ │ │ │ ├── blue_kick_2.png
│ │ │ │ └── Contents.json
│ │ │ └── one_idle.imageset
│ │ │ │ ├── blue_idle_1.png
│ │ │ │ └── Contents.json
│ │ ├── Two
│ │ │ ├── Contents.json
│ │ │ ├── two_hit.imageset
│ │ │ │ ├── two_hit_2.png
│ │ │ │ └── Contents.json
│ │ │ ├── two_idle.imageset
│ │ │ │ ├── two_idle_1.png
│ │ │ │ └── Contents.json
│ │ │ └── two_attack.imageset
│ │ │ │ ├── two_kick_3.png
│ │ │ │ └── Contents.json
│ │ └── .DS_Store
│ ├── .DS_Store
│ ├── AccentColor.colorset
│ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Models
│ ├── PlayerStatus.swift
│ ├── GameModel.swift
│ └── Player.swift
├── Source
│ ├── AppDelegate.swift
│ ├── Base.lproj
│ │ └── LaunchScreen.storyboard
│ └── SceneDelegate.swift
├── MenuViewController.swift
├── Info.plist
├── GameCenterHelper.swift
├── GameViewController.swift
└── Base.lproj
│ └── Main.storyboard
└── GameCenterMultiplayer.xcodeproj
├── project.xcworkspace
├── contents.xcworkspacedata
├── xcuserdata
│ └── pedrocontine.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
└── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── xcuserdata
└── pedrocontine.xcuserdatad
│ ├── xcdebugger
│ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes
│ └── xcschememanagement.plist
└── project.pbxproj
/GameCenterMultiplayer/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/Animations/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/Animations/One/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/Animations/Two/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geovanacontine/GameKitMultiplayerTutorial/HEAD/GameCenterMultiplayer/Assets.xcassets/.DS_Store
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/Animations/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geovanacontine/GameKitMultiplayerTutorial/HEAD/GameCenterMultiplayer/Assets.xcassets/Animations/.DS_Store
--------------------------------------------------------------------------------
/GameCenterMultiplayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/Animations/Two/two_hit.imageset/two_hit_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geovanacontine/GameKitMultiplayerTutorial/HEAD/GameCenterMultiplayer/Assets.xcassets/Animations/Two/two_hit.imageset/two_hit_2.png
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/Animations/One/one_hit.imageset/blue_hit_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geovanacontine/GameKitMultiplayerTutorial/HEAD/GameCenterMultiplayer/Assets.xcassets/Animations/One/one_hit.imageset/blue_hit_2.png
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/Animations/Two/two_idle.imageset/two_idle_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geovanacontine/GameKitMultiplayerTutorial/HEAD/GameCenterMultiplayer/Assets.xcassets/Animations/Two/two_idle.imageset/two_idle_1.png
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/Animations/One/one_attack.imageset/blue_kick_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geovanacontine/GameKitMultiplayerTutorial/HEAD/GameCenterMultiplayer/Assets.xcassets/Animations/One/one_attack.imageset/blue_kick_2.png
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/Animations/One/one_idle.imageset/blue_idle_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geovanacontine/GameKitMultiplayerTutorial/HEAD/GameCenterMultiplayer/Assets.xcassets/Animations/One/one_idle.imageset/blue_idle_1.png
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/Animations/Two/two_attack.imageset/two_kick_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geovanacontine/GameKitMultiplayerTutorial/HEAD/GameCenterMultiplayer/Assets.xcassets/Animations/Two/two_attack.imageset/two_kick_3.png
--------------------------------------------------------------------------------
/GameCenterMultiplayer.xcodeproj/xcuserdata/pedrocontine.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer.xcodeproj/project.xcworkspace/xcuserdata/pedrocontine.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geovanacontine/GameKitMultiplayerTutorial/HEAD/GameCenterMultiplayer.xcodeproj/project.xcworkspace/xcuserdata/pedrocontine.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/GameCenterMultiplayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Models/PlayerStatus.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnimationTypes.swift
3 | // GameCenterMultiplayer
4 | //
5 | // Created by Pedro Contine on 29/06/20.
6 | //
7 |
8 | import Foundation
9 | import UIKit
10 |
11 | enum PlayerStatus: String, Codable {
12 | case idle
13 | case attack
14 | case hit
15 |
16 | func image(player: PlayerType) -> UIImage {
17 | return UIImage(named: "\(player.rawValue)_\(self.rawValue)")!
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/Animations/One/one_hit.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "blue_hit_2.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/Animations/Two/two_hit.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "two_hit_2.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/Animations/Two/two_idle.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "two_idle_1.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/Animations/One/one_attack.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "blue_kick_2.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/Animations/One/one_idle.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "blue_idle_1.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/Animations/Two/two_attack.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "two_kick_3.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer.xcodeproj/xcuserdata/pedrocontine.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | GameCenterMultiplayer.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Models/GameModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GameModel.swift
3 | // GameCenterMultiplayer
4 | //
5 | // Created by Pedro Contine on 29/06/20.
6 | //
7 |
8 | import Foundation
9 | import UIKit
10 | import GameKit
11 |
12 | struct GameModel: Codable {
13 | var players: [Player] = []
14 | var time: Int = 60
15 | }
16 |
17 | extension GameModel {
18 | func encode() -> Data? {
19 | return try? JSONEncoder().encode(self)
20 | }
21 |
22 | static func decode(data: Data) -> GameModel? {
23 | return try? JSONDecoder().decode(GameModel.self, from: data)
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Models/Player.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Player.swift
3 | // GameCenterMultiplayer
4 | //
5 | // Created by Pedro Contine on 29/06/20.
6 | //
7 |
8 | import Foundation
9 | import UIKit
10 |
11 | struct Player: Codable {
12 | var displayName: String
13 | var status: PlayerStatus = .idle
14 | var life: Float = 100
15 | }
16 |
17 | enum PlayerType: String, Codable, CaseIterable {
18 | case one
19 | case two
20 | }
21 |
22 | extension PlayerType {
23 | func enemyIndex() -> Int {
24 | switch self {
25 | case .one:
26 | return 1
27 | case .two:
28 | return 0
29 | }
30 | }
31 |
32 | func index() -> Int {
33 | switch self {
34 | case .one:
35 | return 0
36 | case .two:
37 | return 1
38 | }
39 | }
40 |
41 | func color() -> UIColor {
42 | switch self {
43 | case .one:
44 | return .systemBlue
45 | case .two:
46 | return .systemRed
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Source/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // GameCenterMultiplayer
4 | //
5 | // Created by Pedro Contine on 29/06/20.
6 | //
7 |
8 | import UIKit
9 |
10 | @UIApplicationMain
11 | class AppDelegate: UIResponder, UIApplicationDelegate {
12 |
13 |
14 |
15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
16 | // Override point for customization after application launch.
17 | return true
18 | }
19 |
20 | // MARK: UISceneSession Lifecycle
21 |
22 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
23 | // Called when a new scene session is being created.
24 | // Use this method to select a configuration to create the new scene with.
25 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
26 | }
27 |
28 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
29 | // Called when the user discards a scene session.
30 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
31 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
32 | }
33 |
34 |
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Source/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/MenuViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // GameCenterMultiplayer
4 | //
5 | // Created by Pedro Contine on 29/06/20.
6 | //
7 |
8 | import UIKit
9 | import GameKit
10 |
11 | class MenuViewController: UIViewController {
12 |
13 | @IBOutlet weak var buttonMultiplayer: UIButton!
14 |
15 | private var gameCenterHelper: GameCenterHelper!
16 |
17 | override func viewDidLoad() {
18 | super.viewDidLoad()
19 | buttonMultiplayer.isEnabled = false
20 | buttonMultiplayer.layer.cornerRadius = 10
21 |
22 | gameCenterHelper = GameCenterHelper()
23 | gameCenterHelper.delegate = self
24 | gameCenterHelper.authenticatePlayer()
25 | }
26 |
27 | @IBAction func buttonMultiplayerPressed() {
28 | gameCenterHelper.presentMatchmaker()
29 | }
30 |
31 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
32 | guard let vc = segue.destination as? GameViewController,
33 | let match = sender as? GKMatch else { return }
34 |
35 | vc.match = match
36 | }
37 | }
38 |
39 | extension MenuViewController: GameCenterHelperDelegate {
40 | func didChangeAuthStatus(isAuthenticated: Bool) {
41 | buttonMultiplayer.isEnabled = isAuthenticated
42 | }
43 |
44 | func presentGameCenterAuth(viewController: UIViewController?) {
45 | guard let vc = viewController else {return}
46 | self.present(vc, animated: true)
47 | }
48 |
49 | func presentMatchmaking(viewController: UIViewController?) {
50 | guard let vc = viewController else {return}
51 | self.present(vc, animated: true)
52 | }
53 |
54 | func presentGame(match: GKMatch) {
55 | performSegue(withIdentifier: "showGame", sender: match)
56 | }
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "scale" : "1x",
46 | "size" : "20x20"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "scale" : "2x",
51 | "size" : "20x20"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "scale" : "1x",
56 | "size" : "29x29"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "scale" : "2x",
61 | "size" : "29x29"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "scale" : "1x",
66 | "size" : "40x40"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "scale" : "2x",
71 | "size" : "40x40"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "scale" : "1x",
76 | "size" : "76x76"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "scale" : "2x",
81 | "size" : "76x76"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "scale" : "2x",
86 | "size" : "83.5x83.5"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "scale" : "1x",
91 | "size" : "1024x1024"
92 | }
93 | ],
94 | "info" : {
95 | "author" : "xcode",
96 | "version" : 1
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UIApplicationSceneManifest
24 |
25 | UIApplicationSupportsMultipleScenes
26 |
27 | UISceneConfigurations
28 |
29 | UIWindowSceneSessionRoleApplication
30 |
31 |
32 | UISceneConfigurationName
33 | Default Configuration
34 | UISceneDelegateClassName
35 | $(PRODUCT_MODULE_NAME).SceneDelegate
36 | UISceneStoryboardFile
37 | Main
38 |
39 |
40 |
41 |
42 | UIApplicationSupportsIndirectInputEvents
43 |
44 | UILaunchStoryboardName
45 | LaunchScreen
46 | UIMainStoryboardFile
47 | Main
48 | UIRequiredDeviceCapabilities
49 |
50 | armv7
51 | gamekit
52 |
53 | UISupportedInterfaceOrientations
54 |
55 | UIInterfaceOrientationPortrait
56 | UIInterfaceOrientationLandscapeLeft
57 | UIInterfaceOrientationLandscapeRight
58 |
59 | UISupportedInterfaceOrientations~ipad
60 |
61 | UIInterfaceOrientationPortrait
62 | UIInterfaceOrientationPortraitUpsideDown
63 | UIInterfaceOrientationLandscapeLeft
64 | UIInterfaceOrientationLandscapeRight
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Source/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // GameCenterMultiplayer
4 | //
5 | // Created by Pedro Contine on 29/06/20.
6 | //
7 |
8 | import UIKit
9 |
10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
11 |
12 | var window: UIWindow?
13 |
14 |
15 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
16 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
17 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
18 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
19 | guard let _ = (scene as? UIWindowScene) else { return }
20 | }
21 |
22 | func sceneDidDisconnect(_ scene: UIScene) {
23 | // Called as the scene is being released by the system.
24 | // This occurs shortly after the scene enters the background, or when its session is discarded.
25 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
26 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
27 | }
28 |
29 | func sceneDidBecomeActive(_ scene: UIScene) {
30 | // Called when the scene has moved from an inactive state to an active state.
31 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
32 | }
33 |
34 | func sceneWillResignActive(_ scene: UIScene) {
35 | // Called when the scene will move from an active state to an inactive state.
36 | // This may occur due to temporary interruptions (ex. an incoming phone call).
37 | }
38 |
39 | func sceneWillEnterForeground(_ scene: UIScene) {
40 | // Called as the scene transitions from the background to the foreground.
41 | // Use this method to undo the changes made on entering the background.
42 | }
43 |
44 | func sceneDidEnterBackground(_ scene: UIScene) {
45 | // Called as the scene transitions from the foreground to the background.
46 | // Use this method to save data, release shared resources, and store enough scene-specific state information
47 | // to restore the scene back to its current state.
48 | }
49 |
50 |
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/GameCenterHelper.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Matchmaking.swift
3 | // GameCenterMultiplayer
4 | //
5 | // Created by Pedro Contine on 29/06/20.
6 | //
7 |
8 | import Foundation
9 | import GameKit
10 |
11 | protocol GameCenterHelperDelegate: class {
12 | func didChangeAuthStatus(isAuthenticated: Bool)
13 | func presentGameCenterAuth(viewController: UIViewController?)
14 | func presentMatchmaking(viewController: UIViewController?)
15 | func presentGame(match: GKMatch)
16 | }
17 |
18 | final class GameCenterHelper: NSObject, GKLocalPlayerListener {
19 | weak var delegate: GameCenterHelperDelegate?
20 |
21 | private let minPlayers: Int = 2
22 | private let maxPlayers: Int = 3
23 | private let inviteMessage = "Write your default invite message!"
24 |
25 | private var currentVC: GKMatchmakerViewController?
26 |
27 | var isAuthenticated: Bool {
28 | return GKLocalPlayer.local.isAuthenticated
29 | }
30 |
31 | func authenticatePlayer() {
32 | GKLocalPlayer.local.authenticateHandler = { (gameCenterAuthViewController, error) in
33 | self.delegate?.didChangeAuthStatus(isAuthenticated: self.isAuthenticated)
34 |
35 | guard GKLocalPlayer.local.isAuthenticated else {
36 | self.delegate?.presentGameCenterAuth(viewController: gameCenterAuthViewController)
37 | return
38 | }
39 |
40 | GKLocalPlayer.local.register(self)
41 | }
42 | }
43 |
44 | func presentMatchmaker(withInvite invite: GKInvite? = nil) {
45 | guard GKLocalPlayer.local.isAuthenticated,
46 | let vc = createMatchmaker(withInvite: invite) else {
47 | return
48 | }
49 |
50 | currentVC = vc
51 | vc.matchmakerDelegate = self
52 | delegate?.presentMatchmaking(viewController: vc)
53 | }
54 |
55 | private func createMatchmaker(withInvite invite: GKInvite? = nil) -> GKMatchmakerViewController? {
56 |
57 | //If there is an invite, create the matchmaker vc with it
58 | if let invite = invite {
59 | return GKMatchmakerViewController(invite: invite)
60 | }
61 |
62 | return GKMatchmakerViewController(matchRequest: createRequest())
63 | }
64 |
65 | private func createRequest() -> GKMatchRequest {
66 | let request = GKMatchRequest()
67 | request.minPlayers = minPlayers
68 | request.maxPlayers = maxPlayers
69 | request.inviteMessage = inviteMessage
70 |
71 | return request
72 | }
73 | }
74 |
75 |
76 | extension GameCenterHelper: GKMatchmakerViewControllerDelegate {
77 | func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFind match: GKMatch) {
78 | viewController.dismiss(animated: true)
79 | delegate?.presentGame(match: match)
80 | }
81 |
82 | func player(_ player: GKPlayer, didAccept invite: GKInvite) {
83 | currentVC?.dismiss(animated: true, completion: {
84 | self.presentMatchmaker(withInvite: invite)
85 | })
86 | }
87 |
88 | func matchmakerViewControllerWasCancelled(_ viewController: GKMatchmakerViewController) {
89 | viewController.dismiss(animated: true)
90 | }
91 |
92 | func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFailWithError error: Error) {
93 | print("Matchmaker vc did fail with error: \(error.localizedDescription).")
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/GameViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GameViewController.swift
3 | // GameCenterMultiplayer
4 | //
5 | // Created by Pedro Contine on 29/06/20.
6 | //
7 |
8 | import UIKit
9 | import GameKit
10 |
11 | class GameViewController: UIViewController {
12 |
13 | @IBOutlet weak var player1: UIImageView!
14 | @IBOutlet weak var progressPlayer1: UIProgressView!
15 | @IBOutlet weak var player2: UIImageView!
16 | @IBOutlet weak var progressPlayer2: UIProgressView!
17 | @IBOutlet weak var buttonAttack: UIButton!
18 | @IBOutlet weak var labelTime: UILabel!
19 |
20 | var match: GKMatch?
21 | private var timer: Timer!
22 |
23 | private var gameModel: GameModel! {
24 | didSet {
25 | updateUI()
26 | }
27 | }
28 |
29 | override func viewDidLoad() {
30 | super.viewDidLoad()
31 |
32 | gameModel = GameModel()
33 | match?.delegate = self
34 |
35 | //Mirror player 2 images
36 | player2.transform = CGAffineTransform(scaleX: -1, y: 1)
37 |
38 | savePlayers()
39 |
40 | if getLocalPlayerType() == .one, timer == nil {
41 | self.initTimer()
42 | }
43 | }
44 |
45 | private func initTimer() {
46 | timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { (timer) in
47 | let player = self.getLocalPlayerType()
48 | if player == .one, self.gameModel.time >= 1 {
49 | self.gameModel.time -= 1
50 | self.sendData()
51 | }
52 | })
53 | }
54 |
55 | private func savePlayers() {
56 | guard let player2Name = match?.players.first?.displayName else { return }
57 | let player1 = Player(displayName: GKLocalPlayer.local.displayName)
58 | let player2 = Player(displayName: player2Name)
59 |
60 | gameModel.players = [player1, player2]
61 |
62 | gameModel.players.sort { (player1, player2) -> Bool in
63 | player1.displayName < player2.displayName
64 | }
65 |
66 | sendData()
67 | }
68 |
69 | private func getLocalPlayerType() -> PlayerType {
70 | if gameModel.players.first?.displayName == GKLocalPlayer.local.displayName {
71 | return .one
72 | } else {
73 | return .two
74 | }
75 | }
76 |
77 | private func updateUI() {
78 | guard gameModel.players.count >= 2 else { return }
79 |
80 | labelTime.text = "\(gameModel.time)"
81 | player1.image = gameModel.players[0].status.image(player: .one)
82 | progressPlayer1.progress = gameModel.players[0].life / 100.0
83 | player2.image = gameModel.players[1].status.image(player: .two)
84 | progressPlayer2.progress = gameModel.players[1].life / 100.0
85 |
86 | let player = getLocalPlayerType()
87 | buttonAttack.backgroundColor = player.color()
88 | }
89 |
90 | @IBAction func buttonAttackPressed() {
91 | let localPlayer = getLocalPlayerType()
92 |
93 | //Change status to attacking
94 | gameModel.players[localPlayer.index()].status = .attack
95 | gameModel.players[localPlayer.enemyIndex()].status = .hit
96 | gameModel.players[localPlayer.enemyIndex()].life -= 10
97 | sendData()
98 |
99 | //Reset status after 1 second
100 | DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
101 | self.gameModel.players[localPlayer.index()].status = .idle
102 | self.gameModel.players[localPlayer.enemyIndex()].status = .idle
103 | self.sendData()
104 | }
105 | }
106 |
107 | private func sendData() {
108 | guard let match = match else { return }
109 |
110 | do {
111 | guard let data = gameModel.encode() else { return }
112 | try match.sendData(toAllPlayers: data, with: .reliable)
113 | } catch {
114 | print("Send data failed")
115 | }
116 | }
117 | }
118 |
119 | extension GameViewController: GKMatchDelegate {
120 | func match(_ match: GKMatch, didReceive data: Data, fromRemotePlayer player: GKPlayer) {
121 | guard let model = GameModel.decode(data: data) else { return }
122 | gameModel = model
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
--------------------------------------------------------------------------------
/GameCenterMultiplayer.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 20116AE324AA1A6100EABDCF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20116AE224AA1A6100EABDCF /* AppDelegate.swift */; };
11 | 20116AE524AA1A6100EABDCF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20116AE424AA1A6100EABDCF /* SceneDelegate.swift */; };
12 | 20116AE724AA1A6100EABDCF /* MenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20116AE624AA1A6100EABDCF /* MenuViewController.swift */; };
13 | 20116AEA24AA1A6100EABDCF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 20116AE824AA1A6100EABDCF /* Main.storyboard */; };
14 | 20116AEC24AA1A6300EABDCF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 20116AEB24AA1A6300EABDCF /* Assets.xcassets */; };
15 | 20116AEF24AA1A6300EABDCF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 20116AED24AA1A6300EABDCF /* LaunchScreen.storyboard */; };
16 | 20116AF824AA1B0300EABDCF /* GameCenterHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20116AF724AA1B0300EABDCF /* GameCenterHelper.swift */; };
17 | 20116AFB24AA1E0400EABDCF /* GameKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20116AFA24AA1E0400EABDCF /* GameKit.framework */; };
18 | 20116AFD24AA20DB00EABDCF /* GameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20116AFC24AA20DB00EABDCF /* GameViewController.swift */; };
19 | 20116AFF24AA23BC00EABDCF /* GameModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20116AFE24AA23BC00EABDCF /* GameModel.swift */; };
20 | 20116B0324AA4B9400EABDCF /* PlayerStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20116B0224AA4B9400EABDCF /* PlayerStatus.swift */; };
21 | 20116B0524AA4BCA00EABDCF /* Player.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20116B0424AA4BCA00EABDCF /* Player.swift */; };
22 | /* End PBXBuildFile section */
23 |
24 | /* Begin PBXFileReference section */
25 | 20116ADF24AA1A6100EABDCF /* GameCenterMultiplayer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GameCenterMultiplayer.app; sourceTree = BUILT_PRODUCTS_DIR; };
26 | 20116AE224AA1A6100EABDCF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
27 | 20116AE424AA1A6100EABDCF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
28 | 20116AE624AA1A6100EABDCF /* MenuViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuViewController.swift; sourceTree = ""; };
29 | 20116AE924AA1A6100EABDCF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
30 | 20116AEB24AA1A6300EABDCF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
31 | 20116AEE24AA1A6300EABDCF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
32 | 20116AF024AA1A6300EABDCF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
33 | 20116AF724AA1B0300EABDCF /* GameCenterHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameCenterHelper.swift; sourceTree = ""; };
34 | 20116AFA24AA1E0400EABDCF /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System/Library/Frameworks/GameKit.framework; sourceTree = SDKROOT; };
35 | 20116AFC24AA20DB00EABDCF /* GameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameViewController.swift; sourceTree = ""; };
36 | 20116AFE24AA23BC00EABDCF /* GameModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameModel.swift; sourceTree = ""; };
37 | 20116B0224AA4B9400EABDCF /* PlayerStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerStatus.swift; sourceTree = ""; };
38 | 20116B0424AA4BCA00EABDCF /* Player.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Player.swift; sourceTree = ""; };
39 | /* End PBXFileReference section */
40 |
41 | /* Begin PBXFrameworksBuildPhase section */
42 | 20116ADC24AA1A6100EABDCF /* Frameworks */ = {
43 | isa = PBXFrameworksBuildPhase;
44 | buildActionMask = 2147483647;
45 | files = (
46 | 20116AFB24AA1E0400EABDCF /* GameKit.framework in Frameworks */,
47 | );
48 | runOnlyForDeploymentPostprocessing = 0;
49 | };
50 | /* End PBXFrameworksBuildPhase section */
51 |
52 | /* Begin PBXGroup section */
53 | 20116AD624AA1A6100EABDCF = {
54 | isa = PBXGroup;
55 | children = (
56 | 20116AE124AA1A6100EABDCF /* GameCenterMultiplayer */,
57 | 20116AE024AA1A6100EABDCF /* Products */,
58 | 20116AF924AA1E0400EABDCF /* Frameworks */,
59 | );
60 | sourceTree = "";
61 | };
62 | 20116AE024AA1A6100EABDCF /* Products */ = {
63 | isa = PBXGroup;
64 | children = (
65 | 20116ADF24AA1A6100EABDCF /* GameCenterMultiplayer.app */,
66 | );
67 | name = Products;
68 | sourceTree = "";
69 | };
70 | 20116AE124AA1A6100EABDCF /* GameCenterMultiplayer */ = {
71 | isa = PBXGroup;
72 | children = (
73 | 20116AF624AA1A8800EABDCF /* Source */,
74 | 20116B0124AA4B8500EABDCF /* Models */,
75 | 20116AE824AA1A6100EABDCF /* Main.storyboard */,
76 | 20116AE624AA1A6100EABDCF /* MenuViewController.swift */,
77 | 20116AFC24AA20DB00EABDCF /* GameViewController.swift */,
78 | 20116AF724AA1B0300EABDCF /* GameCenterHelper.swift */,
79 | 20116AEB24AA1A6300EABDCF /* Assets.xcassets */,
80 | 20116AF024AA1A6300EABDCF /* Info.plist */,
81 | );
82 | path = GameCenterMultiplayer;
83 | sourceTree = "";
84 | };
85 | 20116AF624AA1A8800EABDCF /* Source */ = {
86 | isa = PBXGroup;
87 | children = (
88 | 20116AED24AA1A6300EABDCF /* LaunchScreen.storyboard */,
89 | 20116AE224AA1A6100EABDCF /* AppDelegate.swift */,
90 | 20116AE424AA1A6100EABDCF /* SceneDelegate.swift */,
91 | );
92 | path = Source;
93 | sourceTree = "";
94 | };
95 | 20116AF924AA1E0400EABDCF /* Frameworks */ = {
96 | isa = PBXGroup;
97 | children = (
98 | 20116AFA24AA1E0400EABDCF /* GameKit.framework */,
99 | );
100 | name = Frameworks;
101 | sourceTree = "";
102 | };
103 | 20116B0124AA4B8500EABDCF /* Models */ = {
104 | isa = PBXGroup;
105 | children = (
106 | 20116AFE24AA23BC00EABDCF /* GameModel.swift */,
107 | 20116B0224AA4B9400EABDCF /* PlayerStatus.swift */,
108 | 20116B0424AA4BCA00EABDCF /* Player.swift */,
109 | );
110 | path = Models;
111 | sourceTree = "";
112 | };
113 | /* End PBXGroup section */
114 |
115 | /* Begin PBXNativeTarget section */
116 | 20116ADE24AA1A6100EABDCF /* GameCenterMultiplayer */ = {
117 | isa = PBXNativeTarget;
118 | buildConfigurationList = 20116AF324AA1A6300EABDCF /* Build configuration list for PBXNativeTarget "GameCenterMultiplayer" */;
119 | buildPhases = (
120 | 20116ADB24AA1A6100EABDCF /* Sources */,
121 | 20116ADC24AA1A6100EABDCF /* Frameworks */,
122 | 20116ADD24AA1A6100EABDCF /* Resources */,
123 | );
124 | buildRules = (
125 | );
126 | dependencies = (
127 | );
128 | name = GameCenterMultiplayer;
129 | productName = GameCenterMultiplayer;
130 | productReference = 20116ADF24AA1A6100EABDCF /* GameCenterMultiplayer.app */;
131 | productType = "com.apple.product-type.application";
132 | };
133 | /* End PBXNativeTarget section */
134 |
135 | /* Begin PBXProject section */
136 | 20116AD724AA1A6100EABDCF /* Project object */ = {
137 | isa = PBXProject;
138 | attributes = {
139 | LastSwiftUpdateCheck = 1200;
140 | LastUpgradeCheck = 1200;
141 | TargetAttributes = {
142 | 20116ADE24AA1A6100EABDCF = {
143 | CreatedOnToolsVersion = 12.0;
144 | };
145 | };
146 | };
147 | buildConfigurationList = 20116ADA24AA1A6100EABDCF /* Build configuration list for PBXProject "GameCenterMultiplayer" */;
148 | compatibilityVersion = "Xcode 9.3";
149 | developmentRegion = en;
150 | hasScannedForEncodings = 0;
151 | knownRegions = (
152 | en,
153 | Base,
154 | );
155 | mainGroup = 20116AD624AA1A6100EABDCF;
156 | productRefGroup = 20116AE024AA1A6100EABDCF /* Products */;
157 | projectDirPath = "";
158 | projectRoot = "";
159 | targets = (
160 | 20116ADE24AA1A6100EABDCF /* GameCenterMultiplayer */,
161 | );
162 | };
163 | /* End PBXProject section */
164 |
165 | /* Begin PBXResourcesBuildPhase section */
166 | 20116ADD24AA1A6100EABDCF /* Resources */ = {
167 | isa = PBXResourcesBuildPhase;
168 | buildActionMask = 2147483647;
169 | files = (
170 | 20116AEF24AA1A6300EABDCF /* LaunchScreen.storyboard in Resources */,
171 | 20116AEC24AA1A6300EABDCF /* Assets.xcassets in Resources */,
172 | 20116AEA24AA1A6100EABDCF /* Main.storyboard in Resources */,
173 | );
174 | runOnlyForDeploymentPostprocessing = 0;
175 | };
176 | /* End PBXResourcesBuildPhase section */
177 |
178 | /* Begin PBXSourcesBuildPhase section */
179 | 20116ADB24AA1A6100EABDCF /* Sources */ = {
180 | isa = PBXSourcesBuildPhase;
181 | buildActionMask = 2147483647;
182 | files = (
183 | 20116AFD24AA20DB00EABDCF /* GameViewController.swift in Sources */,
184 | 20116AF824AA1B0300EABDCF /* GameCenterHelper.swift in Sources */,
185 | 20116AE724AA1A6100EABDCF /* MenuViewController.swift in Sources */,
186 | 20116AE324AA1A6100EABDCF /* AppDelegate.swift in Sources */,
187 | 20116B0524AA4BCA00EABDCF /* Player.swift in Sources */,
188 | 20116B0324AA4B9400EABDCF /* PlayerStatus.swift in Sources */,
189 | 20116AE524AA1A6100EABDCF /* SceneDelegate.swift in Sources */,
190 | 20116AFF24AA23BC00EABDCF /* GameModel.swift in Sources */,
191 | );
192 | runOnlyForDeploymentPostprocessing = 0;
193 | };
194 | /* End PBXSourcesBuildPhase section */
195 |
196 | /* Begin PBXVariantGroup section */
197 | 20116AE824AA1A6100EABDCF /* Main.storyboard */ = {
198 | isa = PBXVariantGroup;
199 | children = (
200 | 20116AE924AA1A6100EABDCF /* Base */,
201 | );
202 | name = Main.storyboard;
203 | sourceTree = "";
204 | };
205 | 20116AED24AA1A6300EABDCF /* LaunchScreen.storyboard */ = {
206 | isa = PBXVariantGroup;
207 | children = (
208 | 20116AEE24AA1A6300EABDCF /* Base */,
209 | );
210 | name = LaunchScreen.storyboard;
211 | sourceTree = "";
212 | };
213 | /* End PBXVariantGroup section */
214 |
215 | /* Begin XCBuildConfiguration section */
216 | 20116AF124AA1A6300EABDCF /* Debug */ = {
217 | isa = XCBuildConfiguration;
218 | buildSettings = {
219 | ALWAYS_SEARCH_USER_PATHS = NO;
220 | CLANG_ANALYZER_NONNULL = YES;
221 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
222 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
223 | CLANG_CXX_LIBRARY = "libc++";
224 | CLANG_ENABLE_MODULES = YES;
225 | CLANG_ENABLE_OBJC_ARC = YES;
226 | CLANG_ENABLE_OBJC_WEAK = YES;
227 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
228 | CLANG_WARN_BOOL_CONVERSION = YES;
229 | CLANG_WARN_COMMA = YES;
230 | CLANG_WARN_CONSTANT_CONVERSION = YES;
231 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
232 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
233 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
234 | CLANG_WARN_EMPTY_BODY = YES;
235 | CLANG_WARN_ENUM_CONVERSION = YES;
236 | CLANG_WARN_INFINITE_RECURSION = YES;
237 | CLANG_WARN_INT_CONVERSION = YES;
238 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
239 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
240 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
241 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
242 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
243 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
244 | CLANG_WARN_STRICT_PROTOTYPES = YES;
245 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
246 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
247 | CLANG_WARN_UNREACHABLE_CODE = YES;
248 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
249 | COPY_PHASE_STRIP = NO;
250 | DEBUG_INFORMATION_FORMAT = dwarf;
251 | ENABLE_STRICT_OBJC_MSGSEND = YES;
252 | ENABLE_TESTABILITY = YES;
253 | GCC_C_LANGUAGE_STANDARD = gnu11;
254 | GCC_DYNAMIC_NO_PIC = NO;
255 | GCC_NO_COMMON_BLOCKS = YES;
256 | GCC_OPTIMIZATION_LEVEL = 0;
257 | GCC_PREPROCESSOR_DEFINITIONS = (
258 | "DEBUG=1",
259 | "$(inherited)",
260 | );
261 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
262 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
263 | GCC_WARN_UNDECLARED_SELECTOR = YES;
264 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
265 | GCC_WARN_UNUSED_FUNCTION = YES;
266 | GCC_WARN_UNUSED_VARIABLE = YES;
267 | IPHONEOS_DEPLOYMENT_TARGET = 14.0;
268 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
269 | MTL_FAST_MATH = YES;
270 | ONLY_ACTIVE_ARCH = YES;
271 | SDKROOT = iphoneos;
272 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
273 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
274 | };
275 | name = Debug;
276 | };
277 | 20116AF224AA1A6300EABDCF /* Release */ = {
278 | isa = XCBuildConfiguration;
279 | buildSettings = {
280 | ALWAYS_SEARCH_USER_PATHS = NO;
281 | CLANG_ANALYZER_NONNULL = YES;
282 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
283 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
284 | CLANG_CXX_LIBRARY = "libc++";
285 | CLANG_ENABLE_MODULES = YES;
286 | CLANG_ENABLE_OBJC_ARC = YES;
287 | CLANG_ENABLE_OBJC_WEAK = YES;
288 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
289 | CLANG_WARN_BOOL_CONVERSION = YES;
290 | CLANG_WARN_COMMA = YES;
291 | CLANG_WARN_CONSTANT_CONVERSION = YES;
292 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
293 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
294 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
295 | CLANG_WARN_EMPTY_BODY = YES;
296 | CLANG_WARN_ENUM_CONVERSION = YES;
297 | CLANG_WARN_INFINITE_RECURSION = YES;
298 | CLANG_WARN_INT_CONVERSION = YES;
299 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
300 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
301 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
302 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
303 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
304 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
305 | CLANG_WARN_STRICT_PROTOTYPES = YES;
306 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
307 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
308 | CLANG_WARN_UNREACHABLE_CODE = YES;
309 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
310 | COPY_PHASE_STRIP = NO;
311 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
312 | ENABLE_NS_ASSERTIONS = NO;
313 | ENABLE_STRICT_OBJC_MSGSEND = YES;
314 | GCC_C_LANGUAGE_STANDARD = gnu11;
315 | GCC_NO_COMMON_BLOCKS = YES;
316 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
317 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
318 | GCC_WARN_UNDECLARED_SELECTOR = YES;
319 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
320 | GCC_WARN_UNUSED_FUNCTION = YES;
321 | GCC_WARN_UNUSED_VARIABLE = YES;
322 | IPHONEOS_DEPLOYMENT_TARGET = 14.0;
323 | MTL_ENABLE_DEBUG_INFO = NO;
324 | MTL_FAST_MATH = YES;
325 | SDKROOT = iphoneos;
326 | SWIFT_COMPILATION_MODE = wholemodule;
327 | SWIFT_OPTIMIZATION_LEVEL = "-O";
328 | VALIDATE_PRODUCT = YES;
329 | };
330 | name = Release;
331 | };
332 | 20116AF424AA1A6300EABDCF /* Debug */ = {
333 | isa = XCBuildConfiguration;
334 | buildSettings = {
335 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
336 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
337 | CODE_SIGN_STYLE = Automatic;
338 | DEVELOPMENT_TEAM = FS3B5ULP9R;
339 | INFOPLIST_FILE = GameCenterMultiplayer/Info.plist;
340 | LD_RUNPATH_SEARCH_PATHS = (
341 | "$(inherited)",
342 | "@executable_path/Frameworks",
343 | );
344 | PRODUCT_BUNDLE_IDENTIFIER = continepedro.GameCenterMultiplayer;
345 | PRODUCT_NAME = "$(TARGET_NAME)";
346 | SWIFT_VERSION = 5.0;
347 | TARGETED_DEVICE_FAMILY = 1;
348 | };
349 | name = Debug;
350 | };
351 | 20116AF524AA1A6300EABDCF /* Release */ = {
352 | isa = XCBuildConfiguration;
353 | buildSettings = {
354 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
355 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
356 | CODE_SIGN_STYLE = Automatic;
357 | DEVELOPMENT_TEAM = FS3B5ULP9R;
358 | INFOPLIST_FILE = GameCenterMultiplayer/Info.plist;
359 | LD_RUNPATH_SEARCH_PATHS = (
360 | "$(inherited)",
361 | "@executable_path/Frameworks",
362 | );
363 | PRODUCT_BUNDLE_IDENTIFIER = continepedro.GameCenterMultiplayer;
364 | PRODUCT_NAME = "$(TARGET_NAME)";
365 | SWIFT_VERSION = 5.0;
366 | TARGETED_DEVICE_FAMILY = 1;
367 | };
368 | name = Release;
369 | };
370 | /* End XCBuildConfiguration section */
371 |
372 | /* Begin XCConfigurationList section */
373 | 20116ADA24AA1A6100EABDCF /* Build configuration list for PBXProject "GameCenterMultiplayer" */ = {
374 | isa = XCConfigurationList;
375 | buildConfigurations = (
376 | 20116AF124AA1A6300EABDCF /* Debug */,
377 | 20116AF224AA1A6300EABDCF /* Release */,
378 | );
379 | defaultConfigurationIsVisible = 0;
380 | defaultConfigurationName = Release;
381 | };
382 | 20116AF324AA1A6300EABDCF /* Build configuration list for PBXNativeTarget "GameCenterMultiplayer" */ = {
383 | isa = XCConfigurationList;
384 | buildConfigurations = (
385 | 20116AF424AA1A6300EABDCF /* Debug */,
386 | 20116AF524AA1A6300EABDCF /* Release */,
387 | );
388 | defaultConfigurationIsVisible = 0;
389 | defaultConfigurationName = Release;
390 | };
391 | /* End XCConfigurationList section */
392 | };
393 | rootObject = 20116AD724AA1A6100EABDCF /* Project object */;
394 | }
395 |
--------------------------------------------------------------------------------