├── assets ├── ScaleFunction.sketch │ ├── version │ ├── Data │ └── metadata ├── ScaleFunction.png └── SwiftTeamSelect.gif ├── SwiftTeamSelect ├── GameScene.sks ├── Images.xcassets │ ├── Spaceship.imageset │ │ ├── Spaceship.png │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── Info.plist ├── Base.lproj │ └── Main.storyboard ├── GameViewController.swift ├── AppDelegate.swift ├── UIColor+Shorthands.swift └── GameScene.swift ├── SwiftTeamSelect.xcodeproj ├── xcuserdata │ └── kamil.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── SwiftTeamSelect.xcscheme ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── SwiftTeamSelect.xccheckout └── project.pbxproj ├── .gitignore ├── SwiftTeamSelectTests ├── Info.plist └── SwiftTeamSelectTests.swift ├── LICENSE └── README.md /assets/ScaleFunction.sketch/version: -------------------------------------------------------------------------------- 1 | 37 -------------------------------------------------------------------------------- /assets/ScaleFunction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burczyk/SwiftTeamSelect/HEAD/assets/ScaleFunction.png -------------------------------------------------------------------------------- /assets/SwiftTeamSelect.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burczyk/SwiftTeamSelect/HEAD/assets/SwiftTeamSelect.gif -------------------------------------------------------------------------------- /SwiftTeamSelect/GameScene.sks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burczyk/SwiftTeamSelect/HEAD/SwiftTeamSelect/GameScene.sks -------------------------------------------------------------------------------- /assets/ScaleFunction.sketch/Data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burczyk/SwiftTeamSelect/HEAD/assets/ScaleFunction.sketch/Data -------------------------------------------------------------------------------- /SwiftTeamSelect/Images.xcassets/Spaceship.imageset/Spaceship.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/burczyk/SwiftTeamSelect/HEAD/SwiftTeamSelect/Images.xcassets/Spaceship.imageset/Spaceship.png -------------------------------------------------------------------------------- /SwiftTeamSelect.xcodeproj/xcuserdata/kamil.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /SwiftTeamSelect.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # CocoaPods 2 | # 3 | # We recommend against adding the Pods directory to your .gitignore. However 4 | # you should judge for yourself, the pros and cons are mentioned at: 5 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control? 6 | # 7 | # Pods/ 8 | 9 | -------------------------------------------------------------------------------- /SwiftTeamSelect/Images.xcassets/Spaceship.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Spaceship.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /assets/ScaleFunction.sketch/metadata: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | app 6 | com.bohemiancoding.sketch3 7 | build 8 | 7892 9 | commit 10 | a6af16d03e62e9b34da1be1098affa7b56d9838b 11 | fonts 12 | 13 | Helvetica 14 | 15 | length 16 | 33680 17 | version 18 | 37 19 | 20 | 21 | -------------------------------------------------------------------------------- /SwiftTeamSelect.xcodeproj/xcuserdata/kamil.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SwiftTeamSelect.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 8EA05648194F39F500FA580B 16 | 17 | primary 18 | 19 | 20 | 8EA0565E194F39F500FA580B 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /SwiftTeamSelectTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | pl.sigmapoint.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /SwiftTeamSelectTests/SwiftTeamSelectTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftTeamSelectTests.swift 3 | // SwiftTeamSelectTests 4 | // 5 | // Created by Kamil Burczyk on 16.06.2014. 6 | // Copyright (c) 2014 Sigmapoint. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class SwiftTeamSelectTests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | // Put setup code here. This method is called before the invocation of each test method in the class. 16 | } 17 | 18 | override func tearDown() { 19 | // Put teardown code here. This method is called after the invocation of each test method in the class. 20 | super.tearDown() 21 | } 22 | 23 | func testExample() { 24 | // This is an example of a functional test case. 25 | XCTAssert(true, "Pass") 26 | } 27 | 28 | func testPerformanceExample() { 29 | // This is an example of a performance test case. 30 | self.measureBlock() { 31 | // Put the code you want to measure the time of here. 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /SwiftTeamSelect/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "ipad", 20 | "size" : "29x29", 21 | "scale" : "1x" 22 | }, 23 | { 24 | "idiom" : "ipad", 25 | "size" : "29x29", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "ipad", 30 | "size" : "40x40", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "40x40", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "76x76", 41 | "scale" : "1x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "76x76", 46 | "scale" : "2x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } -------------------------------------------------------------------------------- /SwiftTeamSelect/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | pl.sigmapoint.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UIStatusBarHidden 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Kamil Burczyk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /SwiftTeamSelect/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "orientation" : "portrait", 20 | "idiom" : "ipad", 21 | "extent" : "full-screen", 22 | "minimum-system-version" : "7.0", 23 | "scale" : "1x" 24 | }, 25 | { 26 | "orientation" : "landscape", 27 | "idiom" : "ipad", 28 | "extent" : "full-screen", 29 | "minimum-system-version" : "7.0", 30 | "scale" : "1x" 31 | }, 32 | { 33 | "orientation" : "portrait", 34 | "idiom" : "ipad", 35 | "extent" : "full-screen", 36 | "minimum-system-version" : "7.0", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "orientation" : "landscape", 41 | "idiom" : "ipad", 42 | "extent" : "full-screen", 43 | "minimum-system-version" : "7.0", 44 | "scale" : "2x" 45 | } 46 | ], 47 | "info" : { 48 | "version" : 1, 49 | "author" : "xcode" 50 | } 51 | } -------------------------------------------------------------------------------- /SwiftTeamSelect/Base.lproj/Main.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 | -------------------------------------------------------------------------------- /SwiftTeamSelect.xcodeproj/project.xcworkspace/xcshareddata/SwiftTeamSelect.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 2BF1C97E-20C6-4A37-B972-8278A19CC82D 9 | IDESourceControlProjectName 10 | SwiftTeamSelect 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 101092253F7CCF69445BB2B00AC7B20D84C40D6E 14 | https://github.com/burczyk/SwiftTeamSelect.git 15 | 16 | IDESourceControlProjectPath 17 | SwiftTeamSelect.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 101092253F7CCF69445BB2B00AC7B20D84C40D6E 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/burczyk/SwiftTeamSelect.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 101092253F7CCF69445BB2B00AC7B20D84C40D6E 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 101092253F7CCF69445BB2B00AC7B20D84C40D6E 36 | IDESourceControlWCCName 37 | SwiftTeamSelect 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /SwiftTeamSelect/GameViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameViewController.swift 3 | // SwiftTeamSelect 4 | // 5 | // Created by Kamil Burczyk on 16.06.2014. 6 | // Copyright (c) 2014 Sigmapoint. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SpriteKit 11 | 12 | extension SKNode { 13 | class func unarchiveFromFile(file : NSString) -> SKNode? { 14 | 15 | let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") 16 | 17 | var sceneData = NSData(contentsOfFile: path!, options: NSDataReadingOptions.DataReadingMappedIfSafe, error: nil) 18 | var archiver = NSKeyedUnarchiver(forReadingWithData: sceneData!) 19 | 20 | archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene") 21 | let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as GameScene 22 | archiver.finishDecoding() 23 | return scene 24 | } 25 | } 26 | 27 | class GameViewController: UIViewController { 28 | 29 | override func viewDidLoad() { 30 | super.viewDidLoad() 31 | 32 | let scene = GameScene(size:CGSizeMake(self.view.bounds.size.width, self.view.bounds.size.height)) 33 | 34 | let skView = self.view as SKView 35 | skView.showsFPS = true 36 | skView.showsNodeCount = true 37 | 38 | /* Sprite Kit applies additional optimizations to improve rendering performance */ 39 | skView.ignoresSiblingOrder = true 40 | 41 | /* Set the scale mode to scale to fit the window */ 42 | scene.scaleMode = .AspectFill 43 | 44 | skView.presentScene(scene) 45 | 46 | } 47 | 48 | override func shouldAutorotate() -> Bool { 49 | return true 50 | } 51 | 52 | override func supportedInterfaceOrientations() -> Int { 53 | if UIDevice.currentDevice().userInterfaceIdiom == .Phone { 54 | return Int(UIInterfaceOrientationMask.AllButUpsideDown.rawValue) 55 | } else { 56 | return Int(UIInterfaceOrientationMask.All.rawValue) 57 | } 58 | } 59 | 60 | override func didReceiveMemoryWarning() { 61 | super.didReceiveMemoryWarning() 62 | // Release any cached data, images, etc that aren't in use. 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /SwiftTeamSelect/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SwiftTeamSelect 4 | // 5 | // Created by Kamil Burczyk on 16.06.2014. 6 | // Copyright (c) 2014 Sigmapoint. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /SwiftTeamSelect/UIColor+Shorthands.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CGColor+Shorthands.swift 3 | // SwiftTeamSelect 4 | // 5 | // Created by Kamil Burczyk on 30.06.2014. 6 | // Copyright (c) 2014 Sigmapoint. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | extension UIColor { 13 | 14 | //convenience initializers 15 | 16 | convenience init(r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat){ 17 | self.init(red:r/255.0, green:g/255.0, blue:b/255.0, alpha:a) 18 | } 19 | 20 | convenience init(_ r: CGFloat, _ g: CGFloat, _ b: CGFloat){ 21 | self.init(red:r/255.0, green:g/255.0, blue:b/255.0, alpha:1) 22 | } 23 | 24 | //array of all flatUI colors 25 | 26 | class func flatUIColors() -> [UIColor] { 27 | return [UIColor.turquoise(), UIColor.emerald(), UIColor.peterRiver(), UIColor.amethyst(), UIColor.wetAsphalt(), UIColor.greenSea(), UIColor.nephritis(), UIColor.belizeHole(), UIColor.wisteria(), UIColor.midnightBlue(), UIColor.sunFlower(), UIColor.carrot(), UIColor.alizarin(), UIColor.clouds(), UIColor.concrete(), UIColor.orange(), UIColor.pumpkin(), UIColor.pomegranate(), UIColor.silver(), UIColor.asbestos()] 28 | } 29 | 30 | //convenience methods to return flatUI colors 31 | 32 | class func turquoise() -> UIColor { 33 | return UIColor(26, 188, 156) 34 | } 35 | 36 | class func emerald() -> UIColor { 37 | return UIColor(46, 204, 113) 38 | } 39 | 40 | class func peterRiver() -> UIColor { 41 | return UIColor(52, 152, 219) 42 | } 43 | 44 | class func amethyst() -> UIColor { 45 | return UIColor(155, 89, 182) 46 | } 47 | 48 | class func wetAsphalt() -> UIColor { 49 | return UIColor(52, 73, 94) 50 | } 51 | 52 | class func greenSea() -> UIColor { 53 | return UIColor(22, 160, 133) 54 | } 55 | 56 | class func nephritis() -> UIColor { 57 | return UIColor(39, 174, 96) 58 | } 59 | 60 | class func belizeHole() -> UIColor { 61 | return UIColor(41, 128, 185) 62 | } 63 | 64 | class func wisteria() -> UIColor { 65 | return UIColor(142, 68, 173) 66 | } 67 | 68 | class func midnightBlue() -> UIColor { 69 | return UIColor(44, 62, 80) 70 | } 71 | 72 | class func sunFlower() -> UIColor { 73 | return UIColor(241, 196, 15) 74 | } 75 | 76 | class func carrot() -> UIColor { 77 | return UIColor(230, 126, 34) 78 | } 79 | 80 | class func alizarin() -> UIColor { 81 | return UIColor(231, 76, 60) 82 | } 83 | 84 | class func clouds() -> UIColor { 85 | return UIColor(236, 240, 241) 86 | } 87 | 88 | class func concrete() -> UIColor { 89 | return UIColor(149, 165, 166) 90 | } 91 | 92 | class func orange() -> UIColor { 93 | return UIColor(243, 156, 18) 94 | } 95 | 96 | class func pumpkin() -> UIColor { 97 | return UIColor(211, 84, 0) 98 | } 99 | 100 | class func pomegranate() -> UIColor { 101 | return UIColor(192, 57, 43) 102 | } 103 | 104 | class func silver() -> UIColor { 105 | return UIColor(189, 195, 199) 106 | } 107 | 108 | class func asbestos() -> UIColor { 109 | return UIColor(127, 140, 141) 110 | } 111 | 112 | } -------------------------------------------------------------------------------- /SwiftTeamSelect.xcodeproj/xcuserdata/kamil.xcuserdatad/xcschemes/SwiftTeamSelect.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SwiftTeamSelect 2 | =============== 3 | 4 | [Swift](https://developer.apple.com/swift/) implementation of [SpriteKit](https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Introduction/Introduction.html) SKScene with scrollable team selection. 5 | 6 | ![Animation of scrollable selection](https://raw.githubusercontent.com/burczyk/SwiftTeamSelect/master/assets/SwiftTeamSelect.gif) 7 | 8 | My previous project [Flappy Football: Brasil Edition](https://itunes.apple.com/us/app/flappy-football-brasil-edition/id886571229?mt=8) made for UK customer had a screen with team selection. 9 | 10 | It was a SpriteKit scene so I programmed it as draggable Sprites in Objective-C. 11 | 12 | Now, when Swift gains more and more hype and it's time to practice some real code I decided to rewrite that solution in Swift and make it public :) 13 | 14 | ### Main concept 15 | 16 | The whole scene works like a horizontal UIScrollView (but it's written purely in SpriteKit!) with one difference - while item moves to the center it becomes bigger. 17 | There are 2 guides `leftGuide` and `rightGuide` which are minimum and maximum `x` value for moving Sprite. There is also third implicit guide which is half of the screen's width - center player is placed on that position while it's neighbours are arranged on both sides. 18 | 19 | #### Scale computation 20 | 21 | Proper scale is calculated by method 22 | 23 | ``` 24 | func calculateScaleForX(x:CGFloat) -> CGFloat 25 | ``` 26 | 27 | It returns scale from `(0.5..1)` range based on simple assumptions: 28 | 29 | * if Sprite's position becomes smaller or equal to `leftGuide` return 0.5, 30 | * if Sprite's position becomes greater or equal to `rightGuide` return 0.5, 31 | * otherwise calculate value from `(0.5..1)` range based on distance from the center of the screen. 32 | 33 | Our scale function can be seen like this in mathematical sense, where collapse points are three guides described above: 34 | 35 | ![Scale function](https://raw.githubusercontent.com/burczyk/SwiftTeamSelect/master/assets/ScaleFunction.png) 36 | 37 | #### Players' depth 38 | To achieve behavior when center player covers it's neighbours when scrolling I used `zIndex` property of `SKSpriteNode` class. 39 | 40 | Method 41 | 42 | ``` 43 | func calculateZIndexesForPlayers() 44 | ``` 45 | 46 | calculates them increasingly from 0 to centerPlayer and then backwards. 47 | In the beginning we start e.g. with zIndexes: `[0,1,2,3,2,1,0]`. If we move center player to the left they become `[0,1,2,1,0,-1,-2]` and centerPlayer is still on top and it can cover it's neighbours when dragged. 48 | 49 | #### Scrolling 50 | All real scrolling takes place in two methods: 51 | 52 | ``` 53 | override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) 54 | override func touchesEnded(touches: NSSet!, withEvent event: UIEvent!) 55 | ``` 56 | 57 | First one is responsible for dragging Sprite when we move our finger on the screen. 58 | It calculates translation for each movement and calls helper method. 59 | 60 | 61 | `touchesEnded` is responsible for pulling each player to appropriate guide based on it's position when touch stops - when this method finishes all players are placed on `leftGuide`, screen center or `rightGuide`. 62 | 63 | Both `touches*` methods use `SKActions` to make animations smooth. 64 | 65 | #### Usage and adoption 66 | 67 | For implementation details check [GameScene.swift](https://github.com/burczyk/SwiftTeamSelect/blob/master/SwiftTeamSelect/GameScene.swift) - it is complete `SKScene` subclass that you can use in your project. 68 | If you change method `func createPlayers()` to your implementation of Sprites with textures instead of colored rectangles it can become even more interesting ;) 69 | 70 | #### FlatUI colors 71 | When drawing Sprites I used [FlatUI](http://flatuicolors.com/) colors. 72 | [UIColor+Shorthands.swift](https://github.com/burczyk/SwiftTeamSelect/blob/master/SwiftTeamSelect/UIColor%2BShorthands.swift) file is an extension to `UIColor` class that adds all colors from that site as convenience methods: 73 | 74 | ``` 75 | UIColor.turquoise() 76 | UIColor.emerald() 77 | UIColor.peterRiver() 78 | UIColor.amethyst() 79 | UIColor.wetAsphalt() 80 | UIColor.greenSea() 81 | UIColor.nephritis() 82 | UIColor.belizeHole() 83 | UIColor.wisteria() 84 | UIColor.midnightBlue() 85 | UIColor.sunFlower() 86 | UIColor.carrot() 87 | UIColor.alizarin() 88 | UIColor.clouds() 89 | UIColor.concrete() 90 | UIColor.orange() 91 | UIColor.pumpkin() 92 | UIColor.pomegranate() 93 | UIColor.silver() 94 | UIColor.asbestos() 95 | ``` 96 | 97 | It also adds [convenience initializer](https://developer.apple.com/library/prerelease/ios/documentation/swift/conceptual/swift_programming_language/Initialization.html) to `UIColor` so it can be initialized with `(0...255)` ints instead of `(0...1.0)` floats, e.g. `UIColor(26, 188, 156)` gives us Turquoise color. 98 | 99 | #### License 100 | **SwiftTeamSelect** is available under the MIT license. See the LICENSE file for more info. 101 | -------------------------------------------------------------------------------- /SwiftTeamSelect/GameScene.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameScene.swift 3 | // SwiftTeamSelect 4 | // 5 | // Created by Kamil Burczyk on 16.06.2014. 6 | // Copyright (c) 2014 Sigmapoint. All rights reserved. 7 | // 8 | 9 | import SpriteKit 10 | 11 | class GameScene: SKScene { 12 | 13 | enum Zone { 14 | case Left, Center, Right 15 | } 16 | 17 | var players = [SKSpriteNode]() 18 | 19 | var leftPlayer: SKSpriteNode? 20 | var centerPlayer: SKSpriteNode? 21 | var rightPlayer: SKSpriteNode? 22 | 23 | var leftGuide : CGFloat { 24 | return round(view!.bounds.width / 6.0) 25 | } 26 | 27 | var rightGuide : CGFloat { 28 | return view!.bounds.width - leftGuide 29 | } 30 | 31 | var gap : CGFloat { 32 | return (size.width / 2 - leftGuide) / 2 33 | } 34 | 35 | 36 | // Initialization 37 | 38 | override init(size: CGSize) { 39 | super.init(size:size) 40 | createPlayers() 41 | centerPlayer = players[players.count/2] 42 | setLeftAndRightPlayers() 43 | } 44 | 45 | required init?(coder aDecoder: NSCoder) { 46 | super.init(coder: aDecoder) 47 | } 48 | 49 | override func didMoveToView(view: SKView) { 50 | placePlayersOnPositions() 51 | calculateZIndexesForPlayers() 52 | } 53 | 54 | func createPlayers() { 55 | let flatUIColors = UIColor.flatUIColors() 56 | 57 | for i in 0..<9 { 58 | let player = SKSpriteNode(color: flatUIColors[i], size: CGSizeMake(100, 200)) 59 | players.append(player) 60 | } 61 | } 62 | 63 | func placePlayersOnPositions() { 64 | for i in 0.. CGFloat { 85 | let minScale = CGFloat(0.5) 86 | 87 | if x <= leftGuide || x >= rightGuide { 88 | return minScale 89 | } 90 | 91 | if x < size.width/2 { 92 | let a = 1.0 / (size.width - 2 * leftGuide) 93 | let b = 0.5 - a * leftGuide 94 | 95 | return (a * x + b) 96 | } 97 | 98 | let a = 1.0 / (frame.size.width - 2 * rightGuide) 99 | let b = 0.5 - a * rightGuide 100 | 101 | return (a * x + b) 102 | } 103 | 104 | func calculateZIndexesForPlayers() { 105 | var playerCenterIndex : Int = players.count / 2 106 | 107 | for i in 0..= leftGuide { 134 | player.runAction(SKAction.moveByX(x, y: 0, duration: duration), completion: { 135 | player.setScale(self.calculateScaleForX(CGRectGetMidX(player.frame))) 136 | }) 137 | 138 | if CGRectGetMidX(player.frame) < leftGuide { 139 | player.position = CGPointMake(leftGuide, player.position.y) 140 | } else if CGRectGetMidX(player.frame) > rightGuide { 141 | player.position = CGPointMake(rightGuide, player.position.y) 142 | } 143 | } 144 | } 145 | 146 | func zoneOfCenterPlayer() -> Zone { 147 | let gap = size.width / 2 - leftGuide 148 | 149 | switch CGRectGetMidX(centerPlayer!.frame) { 150 | 151 | case let x where x < leftGuide + gap/2: 152 | return .Left 153 | 154 | case let x where x > rightGuide - gap/2: 155 | return .Right 156 | 157 | default: return .Center 158 | 159 | } 160 | } 161 | 162 | func setLeftAndRightPlayers() { 163 | var playerCenterIndex : Int = players.count / 2 164 | 165 | for i in 0.. 0 && playerCenterIndex < players.count { 172 | leftPlayer = players[playerCenterIndex-1] 173 | } else { 174 | leftPlayer = nil 175 | } 176 | 177 | if playerCenterIndex > -1 && playerCenterIndex < players.count-1 { 178 | rightPlayer = players[playerCenterIndex+1] 179 | } else { 180 | rightPlayer = nil 181 | } 182 | } 183 | 184 | 185 | 186 | // Touch interactions 187 | 188 | override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { 189 | let touch = touches.anyObject() as UITouch 190 | let node = self.nodeAtPoint(touch.locationInNode(self)) 191 | 192 | if node == centerPlayer { 193 | let fadeOut = SKAction.fadeAlphaTo(0.5, duration: 0.15) 194 | let fadeIn = SKAction.fadeAlphaTo(1, duration: 0.15) 195 | 196 | centerPlayer!.runAction(fadeOut, completion: { self.centerPlayer!.runAction(fadeIn) }) 197 | } 198 | } 199 | 200 | override func touchesMoved(touches: NSSet, withEvent event: UIEvent) { 201 | let duration = 0.01 202 | let touch = touches.anyObject() as UITouch 203 | let newPosition = touch.locationInNode(self) 204 | let oldPosition = touch.previousLocationInNode(self) 205 | let xTranslation = newPosition.x - oldPosition.x 206 | 207 | if CGRectGetMidX(centerPlayer!.frame) > size.width/2 { 208 | if (leftPlayer != nil) { 209 | let actualTranslation = CGRectGetMidX(leftPlayer!.frame) + xTranslation > leftGuide ? xTranslation : leftGuide - CGRectGetMidX(leftPlayer!.frame) 210 | movePlayerByX(leftPlayer!, x: actualTranslation) 211 | } 212 | } else { 213 | if (rightPlayer != nil) { 214 | let actualTranslation = CGRectGetMidX(rightPlayer!.frame) + xTranslation < rightGuide ? xTranslation : rightGuide - CGRectGetMidX(rightPlayer!.frame) 215 | movePlayerByX(rightPlayer!, x: actualTranslation) 216 | } 217 | } 218 | 219 | movePlayerByX(centerPlayer!, x: xTranslation) 220 | } 221 | 222 | override func touchesEnded(touches: NSSet, withEvent event: UIEvent) { 223 | let touch = touches.anyObject() as UITouch 224 | let duration = 0.25 225 | 226 | switch zoneOfCenterPlayer() { 227 | 228 | case .Left: 229 | if (rightPlayer != nil) { 230 | movePlayerToX(centerPlayer!, x: leftGuide, duration: duration) 231 | if (leftPlayer != nil) { 232 | movePlayerToX(leftPlayer!, x: leftGuide, duration: duration) 233 | } 234 | if (rightPlayer != nil) { 235 | movePlayerToX(rightPlayer!, x: size.width/2, duration: duration) 236 | } 237 | 238 | centerPlayer = rightPlayer 239 | setLeftAndRightPlayers() 240 | } else { 241 | movePlayerToX(centerPlayer!, x: size.width/2, duration: duration) 242 | } 243 | 244 | case .Right: 245 | if (leftPlayer != nil) { 246 | movePlayerToX(centerPlayer!, x: rightGuide, duration: duration) 247 | if (rightPlayer != nil) { 248 | movePlayerToX(rightPlayer!, x: rightGuide, duration: duration) 249 | } 250 | if (leftPlayer != nil) { 251 | movePlayerToX(leftPlayer!, x: size.width/2, duration: duration) 252 | } 253 | 254 | centerPlayer = leftPlayer 255 | setLeftAndRightPlayers() 256 | } else { 257 | movePlayerToX(centerPlayer!, x: size.width/2, duration: duration) 258 | } 259 | 260 | case .Center: 261 | movePlayerToX(centerPlayer!, x: size.width/2, duration: duration) 262 | if (leftPlayer != nil) { 263 | movePlayerToX(leftPlayer!, x: leftGuide, duration: duration) 264 | } 265 | if (rightPlayer != nil) { 266 | movePlayerToX(rightPlayer!, x: rightGuide, duration: duration) 267 | } 268 | } 269 | 270 | calculateZIndexesForPlayers() 271 | } 272 | 273 | } 274 | -------------------------------------------------------------------------------- /SwiftTeamSelect.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8E41006819616A4D001ABE16 /* UIColor+Shorthands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E41006719616A4D001ABE16 /* UIColor+Shorthands.swift */; }; 11 | 8EA0564F194F39F500FA580B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EA0564E194F39F500FA580B /* AppDelegate.swift */; }; 12 | 8EA05651194F39F500FA580B /* GameScene.sks in Resources */ = {isa = PBXBuildFile; fileRef = 8EA05650194F39F500FA580B /* GameScene.sks */; }; 13 | 8EA05653194F39F500FA580B /* GameScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EA05652194F39F500FA580B /* GameScene.swift */; }; 14 | 8EA05655194F39F500FA580B /* GameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EA05654194F39F500FA580B /* GameViewController.swift */; }; 15 | 8EA05658194F39F500FA580B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8EA05656194F39F500FA580B /* Main.storyboard */; }; 16 | 8EA0565A194F39F500FA580B /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8EA05659194F39F500FA580B /* Images.xcassets */; }; 17 | 8EA05666194F39F500FA580B /* SwiftTeamSelectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EA05665194F39F500FA580B /* SwiftTeamSelectTests.swift */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXContainerItemProxy section */ 21 | 8EA05660194F39F500FA580B /* PBXContainerItemProxy */ = { 22 | isa = PBXContainerItemProxy; 23 | containerPortal = 8EA05641194F39F500FA580B /* Project object */; 24 | proxyType = 1; 25 | remoteGlobalIDString = 8EA05648194F39F500FA580B; 26 | remoteInfo = SwiftTeamSelect; 27 | }; 28 | /* End PBXContainerItemProxy section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | 8E41006719616A4D001ABE16 /* UIColor+Shorthands.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+Shorthands.swift"; sourceTree = ""; }; 32 | 8E41006D1962E2BD001ABE16 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; 33 | 8EA05649194F39F500FA580B /* SwiftTeamSelect.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftTeamSelect.app; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | 8EA0564D194F39F500FA580B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 35 | 8EA0564E194F39F500FA580B /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 36 | 8EA05650194F39F500FA580B /* GameScene.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = GameScene.sks; sourceTree = ""; }; 37 | 8EA05652194F39F500FA580B /* GameScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameScene.swift; sourceTree = ""; }; 38 | 8EA05654194F39F500FA580B /* GameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameViewController.swift; sourceTree = ""; }; 39 | 8EA05657194F39F500FA580B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 40 | 8EA05659194F39F500FA580B /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 41 | 8EA0565F194F39F500FA580B /* SwiftTeamSelectTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftTeamSelectTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | 8EA05664194F39F500FA580B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 43 | 8EA05665194F39F500FA580B /* SwiftTeamSelectTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftTeamSelectTests.swift; sourceTree = ""; }; 44 | /* End PBXFileReference section */ 45 | 46 | /* Begin PBXFrameworksBuildPhase section */ 47 | 8EA05646194F39F500FA580B /* Frameworks */ = { 48 | isa = PBXFrameworksBuildPhase; 49 | buildActionMask = 2147483647; 50 | files = ( 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | 8EA0565C194F39F500FA580B /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | /* End PBXFrameworksBuildPhase section */ 62 | 63 | /* Begin PBXGroup section */ 64 | 8EA05640194F39F500FA580B = { 65 | isa = PBXGroup; 66 | children = ( 67 | 8EA0564B194F39F500FA580B /* SwiftTeamSelect */, 68 | 8EA05662194F39F500FA580B /* SwiftTeamSelectTests */, 69 | 8EA0564A194F39F500FA580B /* Products */, 70 | ); 71 | sourceTree = ""; 72 | }; 73 | 8EA0564A194F39F500FA580B /* Products */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 8EA05649194F39F500FA580B /* SwiftTeamSelect.app */, 77 | 8EA0565F194F39F500FA580B /* SwiftTeamSelectTests.xctest */, 78 | ); 79 | name = Products; 80 | sourceTree = ""; 81 | }; 82 | 8EA0564B194F39F500FA580B /* SwiftTeamSelect */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 8EA0564E194F39F500FA580B /* AppDelegate.swift */, 86 | 8EA05650194F39F500FA580B /* GameScene.sks */, 87 | 8EA05652194F39F500FA580B /* GameScene.swift */, 88 | 8E41006719616A4D001ABE16 /* UIColor+Shorthands.swift */, 89 | 8EA05654194F39F500FA580B /* GameViewController.swift */, 90 | 8EA05656194F39F500FA580B /* Main.storyboard */, 91 | 8EA05659194F39F500FA580B /* Images.xcassets */, 92 | 8EA0564C194F39F500FA580B /* Supporting Files */, 93 | ); 94 | path = SwiftTeamSelect; 95 | sourceTree = ""; 96 | }; 97 | 8EA0564C194F39F500FA580B /* Supporting Files */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 8E41006D1962E2BD001ABE16 /* README.md */, 101 | 8EA0564D194F39F500FA580B /* Info.plist */, 102 | ); 103 | name = "Supporting Files"; 104 | sourceTree = ""; 105 | }; 106 | 8EA05662194F39F500FA580B /* SwiftTeamSelectTests */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 8EA05665194F39F500FA580B /* SwiftTeamSelectTests.swift */, 110 | 8EA05663194F39F500FA580B /* Supporting Files */, 111 | ); 112 | path = SwiftTeamSelectTests; 113 | sourceTree = ""; 114 | }; 115 | 8EA05663194F39F500FA580B /* Supporting Files */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 8EA05664194F39F500FA580B /* Info.plist */, 119 | ); 120 | name = "Supporting Files"; 121 | sourceTree = ""; 122 | }; 123 | /* End PBXGroup section */ 124 | 125 | /* Begin PBXNativeTarget section */ 126 | 8EA05648194F39F500FA580B /* SwiftTeamSelect */ = { 127 | isa = PBXNativeTarget; 128 | buildConfigurationList = 8EA05669194F39F500FA580B /* Build configuration list for PBXNativeTarget "SwiftTeamSelect" */; 129 | buildPhases = ( 130 | 8EA05645194F39F500FA580B /* Sources */, 131 | 8EA05646194F39F500FA580B /* Frameworks */, 132 | 8EA05647194F39F500FA580B /* Resources */, 133 | ); 134 | buildRules = ( 135 | ); 136 | dependencies = ( 137 | ); 138 | name = SwiftTeamSelect; 139 | productName = SwiftTeamSelect; 140 | productReference = 8EA05649194F39F500FA580B /* SwiftTeamSelect.app */; 141 | productType = "com.apple.product-type.application"; 142 | }; 143 | 8EA0565E194F39F500FA580B /* SwiftTeamSelectTests */ = { 144 | isa = PBXNativeTarget; 145 | buildConfigurationList = 8EA0566C194F39F500FA580B /* Build configuration list for PBXNativeTarget "SwiftTeamSelectTests" */; 146 | buildPhases = ( 147 | 8EA0565B194F39F500FA580B /* Sources */, 148 | 8EA0565C194F39F500FA580B /* Frameworks */, 149 | 8EA0565D194F39F500FA580B /* Resources */, 150 | ); 151 | buildRules = ( 152 | ); 153 | dependencies = ( 154 | 8EA05661194F39F500FA580B /* PBXTargetDependency */, 155 | ); 156 | name = SwiftTeamSelectTests; 157 | productName = SwiftTeamSelectTests; 158 | productReference = 8EA0565F194F39F500FA580B /* SwiftTeamSelectTests.xctest */; 159 | productType = "com.apple.product-type.bundle.unit-test"; 160 | }; 161 | /* End PBXNativeTarget section */ 162 | 163 | /* Begin PBXProject section */ 164 | 8EA05641194F39F500FA580B /* Project object */ = { 165 | isa = PBXProject; 166 | attributes = { 167 | LastUpgradeCheck = 0600; 168 | ORGANIZATIONNAME = Sigmapoint; 169 | TargetAttributes = { 170 | 8EA05648194F39F500FA580B = { 171 | CreatedOnToolsVersion = 6.0; 172 | }; 173 | 8EA0565E194F39F500FA580B = { 174 | CreatedOnToolsVersion = 6.0; 175 | TestTargetID = 8EA05648194F39F500FA580B; 176 | }; 177 | }; 178 | }; 179 | buildConfigurationList = 8EA05644194F39F500FA580B /* Build configuration list for PBXProject "SwiftTeamSelect" */; 180 | compatibilityVersion = "Xcode 3.2"; 181 | developmentRegion = English; 182 | hasScannedForEncodings = 0; 183 | knownRegions = ( 184 | en, 185 | Base, 186 | ); 187 | mainGroup = 8EA05640194F39F500FA580B; 188 | productRefGroup = 8EA0564A194F39F500FA580B /* Products */; 189 | projectDirPath = ""; 190 | projectRoot = ""; 191 | targets = ( 192 | 8EA05648194F39F500FA580B /* SwiftTeamSelect */, 193 | 8EA0565E194F39F500FA580B /* SwiftTeamSelectTests */, 194 | ); 195 | }; 196 | /* End PBXProject section */ 197 | 198 | /* Begin PBXResourcesBuildPhase section */ 199 | 8EA05647194F39F500FA580B /* Resources */ = { 200 | isa = PBXResourcesBuildPhase; 201 | buildActionMask = 2147483647; 202 | files = ( 203 | 8EA0565A194F39F500FA580B /* Images.xcassets in Resources */, 204 | 8EA05651194F39F500FA580B /* GameScene.sks in Resources */, 205 | 8EA05658194F39F500FA580B /* Main.storyboard in Resources */, 206 | ); 207 | runOnlyForDeploymentPostprocessing = 0; 208 | }; 209 | 8EA0565D194F39F500FA580B /* Resources */ = { 210 | isa = PBXResourcesBuildPhase; 211 | buildActionMask = 2147483647; 212 | files = ( 213 | ); 214 | runOnlyForDeploymentPostprocessing = 0; 215 | }; 216 | /* End PBXResourcesBuildPhase section */ 217 | 218 | /* Begin PBXSourcesBuildPhase section */ 219 | 8EA05645194F39F500FA580B /* Sources */ = { 220 | isa = PBXSourcesBuildPhase; 221 | buildActionMask = 2147483647; 222 | files = ( 223 | 8EA05653194F39F500FA580B /* GameScene.swift in Sources */, 224 | 8E41006819616A4D001ABE16 /* UIColor+Shorthands.swift in Sources */, 225 | 8EA05655194F39F500FA580B /* GameViewController.swift in Sources */, 226 | 8EA0564F194F39F500FA580B /* AppDelegate.swift in Sources */, 227 | ); 228 | runOnlyForDeploymentPostprocessing = 0; 229 | }; 230 | 8EA0565B194F39F500FA580B /* Sources */ = { 231 | isa = PBXSourcesBuildPhase; 232 | buildActionMask = 2147483647; 233 | files = ( 234 | 8EA05666194F39F500FA580B /* SwiftTeamSelectTests.swift in Sources */, 235 | ); 236 | runOnlyForDeploymentPostprocessing = 0; 237 | }; 238 | /* End PBXSourcesBuildPhase section */ 239 | 240 | /* Begin PBXTargetDependency section */ 241 | 8EA05661194F39F500FA580B /* PBXTargetDependency */ = { 242 | isa = PBXTargetDependency; 243 | target = 8EA05648194F39F500FA580B /* SwiftTeamSelect */; 244 | targetProxy = 8EA05660194F39F500FA580B /* PBXContainerItemProxy */; 245 | }; 246 | /* End PBXTargetDependency section */ 247 | 248 | /* Begin PBXVariantGroup section */ 249 | 8EA05656194F39F500FA580B /* Main.storyboard */ = { 250 | isa = PBXVariantGroup; 251 | children = ( 252 | 8EA05657194F39F500FA580B /* Base */, 253 | ); 254 | name = Main.storyboard; 255 | sourceTree = ""; 256 | }; 257 | /* End PBXVariantGroup section */ 258 | 259 | /* Begin XCBuildConfiguration section */ 260 | 8EA05667194F39F500FA580B /* Debug */ = { 261 | isa = XCBuildConfiguration; 262 | buildSettings = { 263 | ALWAYS_SEARCH_USER_PATHS = NO; 264 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 265 | CLANG_CXX_LIBRARY = "libc++"; 266 | CLANG_ENABLE_MODULES = YES; 267 | CLANG_ENABLE_OBJC_ARC = YES; 268 | CLANG_WARN_BOOL_CONVERSION = YES; 269 | CLANG_WARN_CONSTANT_CONVERSION = YES; 270 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 271 | CLANG_WARN_EMPTY_BODY = YES; 272 | CLANG_WARN_ENUM_CONVERSION = YES; 273 | CLANG_WARN_INT_CONVERSION = YES; 274 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 275 | CLANG_WARN_UNREACHABLE_CODE = YES; 276 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 277 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 278 | COPY_PHASE_STRIP = NO; 279 | ENABLE_STRICT_OBJC_MSGSEND = YES; 280 | GCC_C_LANGUAGE_STANDARD = gnu99; 281 | GCC_DYNAMIC_NO_PIC = NO; 282 | GCC_OPTIMIZATION_LEVEL = 0; 283 | GCC_PREPROCESSOR_DEFINITIONS = ( 284 | "DEBUG=1", 285 | "$(inherited)", 286 | ); 287 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 288 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 289 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 290 | GCC_WARN_UNDECLARED_SELECTOR = YES; 291 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 292 | GCC_WARN_UNUSED_FUNCTION = YES; 293 | GCC_WARN_UNUSED_VARIABLE = YES; 294 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 295 | METAL_ENABLE_DEBUG_INFO = YES; 296 | ONLY_ACTIVE_ARCH = YES; 297 | SDKROOT = iphoneos; 298 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 299 | TARGETED_DEVICE_FAMILY = "1,2"; 300 | }; 301 | name = Debug; 302 | }; 303 | 8EA05668194F39F500FA580B /* Release */ = { 304 | isa = XCBuildConfiguration; 305 | buildSettings = { 306 | ALWAYS_SEARCH_USER_PATHS = NO; 307 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 308 | CLANG_CXX_LIBRARY = "libc++"; 309 | CLANG_ENABLE_MODULES = YES; 310 | CLANG_ENABLE_OBJC_ARC = YES; 311 | CLANG_WARN_BOOL_CONVERSION = YES; 312 | CLANG_WARN_CONSTANT_CONVERSION = YES; 313 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 314 | CLANG_WARN_EMPTY_BODY = YES; 315 | CLANG_WARN_ENUM_CONVERSION = YES; 316 | CLANG_WARN_INT_CONVERSION = YES; 317 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 318 | CLANG_WARN_UNREACHABLE_CODE = YES; 319 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 320 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 321 | COPY_PHASE_STRIP = YES; 322 | ENABLE_NS_ASSERTIONS = NO; 323 | ENABLE_STRICT_OBJC_MSGSEND = YES; 324 | GCC_C_LANGUAGE_STANDARD = gnu99; 325 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 326 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 327 | GCC_WARN_UNDECLARED_SELECTOR = YES; 328 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 329 | GCC_WARN_UNUSED_FUNCTION = YES; 330 | GCC_WARN_UNUSED_VARIABLE = YES; 331 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 332 | METAL_ENABLE_DEBUG_INFO = NO; 333 | SDKROOT = iphoneos; 334 | TARGETED_DEVICE_FAMILY = "1,2"; 335 | VALIDATE_PRODUCT = YES; 336 | }; 337 | name = Release; 338 | }; 339 | 8EA0566A194F39F500FA580B /* Debug */ = { 340 | isa = XCBuildConfiguration; 341 | buildSettings = { 342 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 343 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 344 | INFOPLIST_FILE = SwiftTeamSelect/Info.plist; 345 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 346 | PRODUCT_NAME = "$(TARGET_NAME)"; 347 | }; 348 | name = Debug; 349 | }; 350 | 8EA0566B194F39F500FA580B /* Release */ = { 351 | isa = XCBuildConfiguration; 352 | buildSettings = { 353 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 354 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 355 | INFOPLIST_FILE = SwiftTeamSelect/Info.plist; 356 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 357 | PRODUCT_NAME = "$(TARGET_NAME)"; 358 | }; 359 | name = Release; 360 | }; 361 | 8EA0566D194F39F500FA580B /* Debug */ = { 362 | isa = XCBuildConfiguration; 363 | buildSettings = { 364 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/SwiftTeamSelect.app/SwiftTeamSelect"; 365 | FRAMEWORK_SEARCH_PATHS = ( 366 | "$(SDKROOT)/Developer/Library/Frameworks", 367 | "$(inherited)", 368 | ); 369 | GCC_PREPROCESSOR_DEFINITIONS = ( 370 | "DEBUG=1", 371 | "$(inherited)", 372 | ); 373 | INFOPLIST_FILE = SwiftTeamSelectTests/Info.plist; 374 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 375 | METAL_ENABLE_DEBUG_INFO = YES; 376 | PRODUCT_NAME = "$(TARGET_NAME)"; 377 | TEST_HOST = "$(BUNDLE_LOADER)"; 378 | }; 379 | name = Debug; 380 | }; 381 | 8EA0566E194F39F500FA580B /* Release */ = { 382 | isa = XCBuildConfiguration; 383 | buildSettings = { 384 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/SwiftTeamSelect.app/SwiftTeamSelect"; 385 | FRAMEWORK_SEARCH_PATHS = ( 386 | "$(SDKROOT)/Developer/Library/Frameworks", 387 | "$(inherited)", 388 | ); 389 | INFOPLIST_FILE = SwiftTeamSelectTests/Info.plist; 390 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 391 | METAL_ENABLE_DEBUG_INFO = NO; 392 | PRODUCT_NAME = "$(TARGET_NAME)"; 393 | TEST_HOST = "$(BUNDLE_LOADER)"; 394 | }; 395 | name = Release; 396 | }; 397 | /* End XCBuildConfiguration section */ 398 | 399 | /* Begin XCConfigurationList section */ 400 | 8EA05644194F39F500FA580B /* Build configuration list for PBXProject "SwiftTeamSelect" */ = { 401 | isa = XCConfigurationList; 402 | buildConfigurations = ( 403 | 8EA05667194F39F500FA580B /* Debug */, 404 | 8EA05668194F39F500FA580B /* Release */, 405 | ); 406 | defaultConfigurationIsVisible = 0; 407 | defaultConfigurationName = Release; 408 | }; 409 | 8EA05669194F39F500FA580B /* Build configuration list for PBXNativeTarget "SwiftTeamSelect" */ = { 410 | isa = XCConfigurationList; 411 | buildConfigurations = ( 412 | 8EA0566A194F39F500FA580B /* Debug */, 413 | 8EA0566B194F39F500FA580B /* Release */, 414 | ); 415 | defaultConfigurationIsVisible = 0; 416 | defaultConfigurationName = Release; 417 | }; 418 | 8EA0566C194F39F500FA580B /* Build configuration list for PBXNativeTarget "SwiftTeamSelectTests" */ = { 419 | isa = XCConfigurationList; 420 | buildConfigurations = ( 421 | 8EA0566D194F39F500FA580B /* Debug */, 422 | 8EA0566E194F39F500FA580B /* Release */, 423 | ); 424 | defaultConfigurationIsVisible = 0; 425 | defaultConfigurationName = Release; 426 | }; 427 | /* End XCConfigurationList section */ 428 | }; 429 | rootObject = 8EA05641194F39F500FA580B /* Project object */; 430 | } 431 | --------------------------------------------------------------------------------