├── .DS_Store
├── Snake
├── Actions.sks
├── GameScene.sks
├── Assets.xcassets
│ ├── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── GameViewController.swift
├── Base.lproj
│ ├── Main.storyboard
│ └── LaunchScreen.storyboard
├── Info.plist
├── AppDelegate.swift
├── GameManager.swift
└── GameScene.swift
├── screenshots
├── game.png
└── menu.png
├── Snake.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── project.pbxproj
├── README.md
├── SnakeTests
├── Info.plist
└── SnakeTests.swift
├── SnakeUITests
├── Info.plist
└── SnakeUITests.swift
├── LICENSE
└── .gitignore
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyozer/Swift-Snake-Game/HEAD/.DS_Store
--------------------------------------------------------------------------------
/Snake/Actions.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyozer/Swift-Snake-Game/HEAD/Snake/Actions.sks
--------------------------------------------------------------------------------
/Snake/GameScene.sks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyozer/Swift-Snake-Game/HEAD/Snake/GameScene.sks
--------------------------------------------------------------------------------
/screenshots/game.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyozer/Swift-Snake-Game/HEAD/screenshots/game.png
--------------------------------------------------------------------------------
/screenshots/menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyozer/Swift-Snake-Game/HEAD/screenshots/menu.png
--------------------------------------------------------------------------------
/Snake/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Snake.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Snake.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Swift Snake Game
2 |
3 | This Snake game has been made to learn how to do a game in Swift (iOS App)
4 | I started by follow a tutorial at begining, but after I do it myself.
5 |
6 | ## Screenshots
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/SnakeTests/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 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/SnakeUITests/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 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/SnakeTests/SnakeTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnakeTests.swift
3 | // SnakeTests
4 | //
5 | // Created by Jean-Charles Moussé on 14/02/2019.
6 | // Copyright © 2019 Jean-Charles Moussé. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import Snake
11 |
12 | class SnakeTests: XCTestCase {
13 |
14 | override func 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 | }
21 |
22 | func testExample() {
23 | // This is an example of a functional test case.
24 | // Use XCTAssert and related functions to verify your tests produce the correct results.
25 | }
26 |
27 | func testPerformanceExample() {
28 | // This is an example of a performance test case.
29 | self.measure {
30 | // Put the code you want to measure the time of here.
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Jean-Charles Moussé
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.
22 |
--------------------------------------------------------------------------------
/SnakeUITests/SnakeUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SnakeUITests.swift
3 | // SnakeUITests
4 | //
5 | // Created by Jean-Charles Moussé on 14/02/2019.
6 | // Copyright © 2019 Jean-Charles Moussé. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class SnakeUITests: XCTestCase {
12 |
13 | override func setUp() {
14 | // Put setup code here. This method is called before the invocation of each test method in the class.
15 |
16 | // In UI tests it is usually best to stop immediately when a failure occurs.
17 | continueAfterFailure = false
18 |
19 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
20 | XCUIApplication().launch()
21 |
22 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
23 | }
24 |
25 | override func tearDown() {
26 | // Put teardown code here. This method is called after the invocation of each test method in the class.
27 | }
28 |
29 | func testExample() {
30 | // Use recording to get started writing UI tests.
31 | // Use XCTAssert and related functions to verify your tests produce the correct results.
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/Snake/GameViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GameViewController.swift
3 | // Snake
4 | //
5 | // Created by Jean-Charles Moussé on 14/02/2019.
6 | // Copyright © 2019 Jean-Charles Moussé. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SpriteKit
11 | import GameplayKit
12 |
13 | class GameViewController: UIViewController {
14 |
15 | override func viewDidLoad() {
16 | super.viewDidLoad()
17 |
18 | if let view = self.view as! SKView? {
19 | // Load the SKScene from 'GameScene.sks'
20 | if let scene = SKScene(fileNamed: "GameScene") {
21 | // Set the scale mode to scale to fit the window
22 | scene.scaleMode = .aspectFill
23 | // Present the scene
24 | view.presentScene(scene)
25 | }
26 | view.ignoresSiblingOrder = true
27 | view.showsFPS = true
28 | view.showsNodeCount = true
29 | }
30 | }
31 |
32 | override var shouldAutorotate: Bool {
33 | return true
34 | }
35 |
36 | override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
37 | if UIDevice.current.userInterfaceIdiom == .phone {
38 | return .allButUpsideDown
39 | } else {
40 | return .all
41 | }
42 | }
43 |
44 | override var prefersStatusBarHidden: Bool {
45 | return true
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Snake/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 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xccheckout
23 | *.xcscmblueprint
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 | *.dSYM.zip
29 | *.dSYM
30 |
31 | ## Playgrounds
32 | timeline.xctimeline
33 | playground.xcworkspace
34 |
35 | # Swift Package Manager
36 | #
37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
38 | # Packages/
39 | # Package.pins
40 | # Package.resolved
41 | .build/
42 |
43 | # CocoaPods
44 | #
45 | # We recommend against adding the Pods directory to your .gitignore. However
46 | # you should judge for yourself, the pros and cons are mentioned at:
47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
48 | #
49 | # Pods/
50 |
51 | # Carthage
52 | #
53 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
54 | # Carthage/Checkouts
55 |
56 | Carthage/Build
57 |
58 | # fastlane
59 | #
60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
61 | # screenshots whenever they are needed.
62 | # For more information about the recommended setup visit:
63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
64 |
65 | fastlane/report.xml
66 | fastlane/Preview.html
67 | fastlane/screenshots/**/*.png
68 | fastlane/test_output
69 |
--------------------------------------------------------------------------------
/Snake/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 |
--------------------------------------------------------------------------------
/Snake/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Snake
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleURLTypes
22 |
23 |
24 | CFBundleURLSchemes
25 |
26 | snakegameschool
27 |
28 | CFBundleURLName
29 | com.pyozer.Snake
30 |
31 |
32 | CFBundleVersion
33 | 1
34 | LSRequiresIPhoneOS
35 |
36 | UILaunchStoryboardName
37 | LaunchScreen
38 | UIMainStoryboardFile
39 | Main
40 | UIRequiredDeviceCapabilities
41 |
42 | armv7
43 |
44 | UIStatusBarHidden
45 |
46 | UISupportedInterfaceOrientations
47 |
48 | UIInterfaceOrientationPortrait
49 | UIInterfaceOrientationLandscapeLeft
50 | UIInterfaceOrientationLandscapeRight
51 |
52 | UISupportedInterfaceOrientations~ipad
53 |
54 | UIInterfaceOrientationPortrait
55 | UIInterfaceOrientationPortraitUpsideDown
56 | UIInterfaceOrientationLandscapeLeft
57 | UIInterfaceOrientationLandscapeRight
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Snake/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/Snake/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Snake
4 | //
5 | // Created by Jean-Charles Moussé on 14/02/2019.
6 | // Copyright © 2019 Jean-Charles Moussé. 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: [UIApplication.LaunchOptionsKey: Any]?) -> 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 invalidate graphics rendering callbacks. 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 active 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 |
--------------------------------------------------------------------------------
/Snake/GameManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GameManager.swift
3 | // Snake
4 | //
5 | // Created by Jean-Charles Moussé on 14/02/2019.
6 | // Copyright © 2019 Jean-Charles Moussé. All rights reserved.
7 | //
8 |
9 | import SpriteKit
10 |
11 | enum PlayerDirection {
12 | case LEFT
13 | case RIGHT
14 | case UP
15 | case DOWN
16 | case DIED
17 | }
18 |
19 | class GameManager {
20 |
21 | private var scene: GameScene!
22 | var numRows: Int!
23 | var numCols: Int!
24 |
25 | private var nextTime: Double?
26 | private var timeExtension: Double = 0.12
27 | private var playerDirection: PlayerDirection = .LEFT
28 | private var playerPositions: [Point] = []
29 |
30 | private var scorePos: Point?
31 | private var currentScore: Int = 0
32 |
33 | init(scene: GameScene, numRows: Int, numCols: Int) {
34 | self.scene = scene
35 | self.numRows = numRows
36 | self.numCols = numCols
37 | }
38 |
39 | func initGame() {
40 | //starting player position
41 | playerPositions.append(Point(10, 10))
42 | playerPositions.append(Point(10, 11))
43 | playerPositions.append(Point(10, 12))
44 | playerDirection = .LEFT
45 | renderChange()
46 | generateNewScorePos()
47 | }
48 |
49 | func update(time: Double) {
50 | if nextTime == nil {
51 | nextTime = time + timeExtension
52 | } else if time >= nextTime! {
53 | nextTime = time + timeExtension
54 | if playerPositions.count > 0 {
55 | updatePlayerPosition()
56 | checkForScore()
57 | checkPlayerDied()
58 | } else if playerPositions.count == 0 && playerDirection == .DIED { // If no more snake and died
59 | playerPositions.removeAll()
60 | playerDirection = .LEFT // Change direction
61 | renderChange()
62 | scene.finishAnimation()
63 | }
64 | }
65 | }
66 |
67 | func changeDirection(_ direction: PlayerDirection) {
68 | if playerDirection == .DIED { return }
69 |
70 | if playerDirection == .LEFT && direction != .RIGHT { playerDirection = direction }
71 | else if playerDirection == .RIGHT && direction != .LEFT { playerDirection = direction }
72 | else if playerDirection == .UP && direction != .DOWN { playerDirection = direction }
73 | else if playerDirection == .DOWN && direction != .UP { playerDirection = direction }
74 | }
75 |
76 | private func updatePlayerPosition() {
77 | // Init changes like if user died
78 | var xChange = 0
79 | var yChange = 0
80 | if playerDirection == .LEFT {
81 | xChange = -1
82 | } else if playerDirection == .RIGHT {
83 | xChange = 1
84 | } else if playerDirection == .UP {
85 | yChange = -1
86 | } else if playerDirection == .DOWN {
87 | yChange = 1
88 | }
89 |
90 | if playerPositions.count > 0 {
91 | if playerDirection == .DIED {
92 | playerPositions.removeLast()
93 | } else {
94 | var start = playerPositions.count - 1
95 | while start > 0 {
96 | playerPositions[start] = playerPositions[start - 1]
97 | start -= 1
98 | }
99 | playerPositions[0] = Point(
100 | playerPositions[0].x + xChange,
101 | playerPositions[0].y + yChange
102 | )
103 | }
104 | }
105 | // Avoid snake go outside screen
106 | if playerPositions.count > 0 {
107 | let x = playerPositions[0].x
108 | let y = playerPositions[0].y
109 | if y >= numRows {
110 | playerPositions[0].y = 0
111 | } else if y < 0 {
112 | playerPositions[0].y = numRows - 1
113 | }
114 | if x >= numCols {
115 | playerPositions[0].x = 0
116 | } else if x < 0 {
117 | playerPositions[0].x = numCols - 1
118 | }
119 | }
120 | renderChange()
121 | }
122 |
123 | func checkForScore() {
124 | if scorePos != nil && playerPositions.count > 0 {
125 | let playerPos: Point = playerPositions[0]
126 | if playerPos.equals(scorePos!) { // Player hit scorePos
127 | currentScore += 1
128 | scene.currentScore.text = "Score: \(currentScore)"
129 | generateNewScorePos()
130 | playerPositions.append(playerPositions.last!)
131 | playerPositions.append(playerPositions.last!)
132 | playerPositions.append(playerPositions.last!)
133 | }
134 | }
135 | }
136 |
137 | func generateNewScorePos() {
138 | var p: Point? = nil
139 | // While score point is at same of player position, generate new one
140 | while p == nil || contains(allPoint: playerPositions, point: p!) {
141 | p = Point(Int.random(in: 0 ..< numCols), Int.random(in: 0 ..< numRows))
142 | }
143 | scorePos = p!
144 | }
145 |
146 | func checkPlayerDied() {
147 | if playerPositions.count > 0 {
148 | var positions = playerPositions.filter { _ in return true }
149 | let headSnake = positions[0]
150 | positions.remove(at: 0)
151 | if contains(allPoint: positions, point: headSnake) {
152 | changeDirection(.DIED)
153 | return
154 | }
155 | }
156 | }
157 |
158 | func renderChange() {
159 | for (node, point) in scene.gameArray {
160 | let isScorePos = scorePos != nil && point.equals(scorePos!)
161 | let isPlayerPos = contains(allPoint: playerPositions, point: point)
162 |
163 | if isPlayerPos && playerDirection != .DIED {
164 | node.fillColor = SKColor.green
165 | } else if isScorePos {
166 | node.fillColor = SKColor.red
167 | } else if isPlayerPos && playerDirection == .DIED {
168 | node.fillColor = SKColor.orange
169 | } else {
170 | node.fillColor = SKColor.clear
171 | }
172 | }
173 | }
174 |
175 | func contains(allPoint: [Point], point: Point) -> Bool {
176 | for p in allPoint {
177 | if point.x == p.x && point.y == p.y { return true }
178 | }
179 | return false
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/Snake/GameScene.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GameScene.swift
3 | // Snake
4 | //
5 | // Created by Jean-Charles Moussé on 14/02/2019.
6 | // Copyright © 2019 Jean-Charles Moussé. All rights reserved.
7 | //
8 |
9 | import SpriteKit
10 | import GameplayKit
11 |
12 | class Point {
13 | var x: Int
14 | var y: Int
15 |
16 | init(_ x: Int, _ y: Int) {
17 | self.x = x
18 | self.y = y
19 | }
20 |
21 | func equals(_ other: Point) -> Bool {
22 | return self.x == other.x && self.y == other.y
23 | }
24 | }
25 |
26 | class GameScene: SKScene {
27 | // Main screen
28 | private var gameLogo: SKLabelNode!
29 | private var bestScore: SKLabelNode!
30 | private var playButton: SKShapeNode!
31 | // Died screen
32 | private var youDiedText: SKLabelNode!
33 |
34 | // Game screen
35 | private var game: GameManager!
36 | var currentScore: SKLabelNode!
37 | private var gameBG: SKShapeNode!
38 | var gameArray: [(node: SKShapeNode, point: Point)] = []
39 |
40 | private var scaleOutAction: SKAction!
41 | private var scaleInAction: SKAction!
42 | private var moveOutsideTopAction: SKAction!
43 | private var moveBackFromTopAction: SKAction!
44 |
45 | override func didMove(to view: SKView) {
46 | scaleInAction = SKAction.init(named: "ScaleIn")
47 | scaleOutAction = SKAction.init(named: "ScaleOut")
48 | moveOutsideTopAction = SKAction.init(named: "MoveOutsideTop")
49 | moveBackFromTopAction = SKAction.init(named: "MoveBackFromTop")
50 |
51 | initializeMenu()
52 | game = GameManager(scene: self, numRows: 30, numCols: 20)
53 | initializeGameView()
54 |
55 | let swipeRight: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(swipeR))
56 | swipeRight.direction = .right
57 | view.addGestureRecognizer(swipeRight)
58 |
59 | let swipeLeft: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(swipeL))
60 | swipeLeft.direction = .left
61 | view.addGestureRecognizer(swipeLeft)
62 |
63 | let swipeUp: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(swipeU))
64 | swipeUp.direction = .up
65 | view.addGestureRecognizer(swipeUp)
66 |
67 | let swipeDown: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(swipeD))
68 | swipeDown.direction = .down
69 | view.addGestureRecognizer(swipeDown)
70 | }
71 |
72 | @objc func swipeR() { game.changeDirection(.RIGHT) }
73 | @objc func swipeL() { game.changeDirection(.LEFT) }
74 | @objc func swipeU() { game.changeDirection(.UP) }
75 | @objc func swipeD() { game.changeDirection(.DOWN) }
76 |
77 | override func update(_ currentTime: TimeInterval) {
78 | game.update(time: currentTime)
79 | }
80 |
81 | override func touchesBegan(_ touches: Set, with event: UIEvent?) {
82 | for touch in touches {
83 | let location = touch.location(in: self)
84 | let touchedNode = nodes(at: location)
85 | for node in touchedNode {
86 | if node.name == "play_button" { startGame() }
87 | }
88 | }
89 | }
90 |
91 | private func startGame() {
92 | self.gameBG.setScale(0)
93 | self.currentScore.setScale(0)
94 |
95 | playButton.run(scaleOutAction) {
96 | self.playButton.isHidden = true
97 | }
98 |
99 | gameLogo.run(moveOutsideTopAction) {
100 | self.gameLogo.isHidden = true
101 | self.gameBG.isHidden = false
102 | self.currentScore.isHidden = false
103 | self.currentScore.run(self.scaleInAction)
104 | self.gameBG.run(self.scaleInAction) {
105 | // Init game
106 | self.game.initGame()
107 | }
108 | }
109 | }
110 |
111 | private func initializeMenu() {
112 | //Create game title
113 | gameLogo = SKLabelNode(fontNamed: "Avenir Next")
114 | gameLogo.zPosition = 1
115 | gameLogo.position = CGPoint(x: 0, y: (frame.size.height / 2) - 200)
116 | gameLogo.fontSize = 60
117 | gameLogo.text = "SNAKE"
118 | gameLogo.fontColor = SKColor.red
119 | self.addChild(gameLogo)
120 | //Create play button
121 | playButton = SKShapeNode()
122 | playButton.name = "play_button"
123 | playButton.zPosition = 1
124 | playButton.position = CGPoint(x: 0, y: (frame.size.height / -2) + 200)
125 | playButton.fillColor = SKColor.green
126 | let topCorner = CGPoint(x: -50, y: 50)
127 | let bottomCorner = CGPoint(x: -50, y: -50)
128 | let middle = CGPoint(x: 50, y: 0)
129 | let path = CGMutablePath()
130 | path.addLine(to: topCorner)
131 | path.addLines(between: [topCorner, bottomCorner, middle])
132 | playButton.path = path
133 | self.addChild(playButton)
134 | }
135 |
136 | private func initializeGameView() {
137 | currentScore = SKLabelNode(fontNamed: "Avenir Next")
138 | currentScore.zPosition = 1
139 | currentScore.position = CGPoint(x: 0, y: (frame.size.height / -2) + 60)
140 | currentScore.fontSize = 40
141 | currentScore.isHidden = true
142 | currentScore.text = "Score: 0"
143 | currentScore.fontColor = SKColor.white
144 | self.addChild(currentScore)
145 |
146 | let width = frame.size.width - 200
147 | let cellSize = width / CGFloat(game.numCols)
148 | let height = cellSize * CGFloat(game.numRows)
149 |
150 | let rect = CGRect(x: -width / 2, y: -height / 2, width: width, height: height)
151 | gameBG = SKShapeNode(rect: rect, cornerRadius: 0.02)
152 | gameBG.fillColor = SKColor.darkGray
153 | gameBG.zPosition = 2
154 | gameBG.isHidden = true
155 | self.addChild(gameBG)
156 |
157 | createGameBoard(width: width, height: height, cellSize: cellSize)
158 | }
159 |
160 | //create a game board, initialize array of cells
161 | private func createGameBoard(width: CGFloat, height: CGFloat, cellSize: CGFloat) {
162 | var x = -width / 2 + cellSize / 2
163 | var y = height / 2 - cellSize / 2
164 | //loop through rows and columns, create cells
165 | for i in 0...game.numRows - 1 {
166 | for j in 0...game.numCols - 1 {
167 | let cellNode = SKShapeNode(rectOf: CGSize(width: cellSize, height: cellSize))
168 | cellNode.strokeColor = SKColor.black
169 | cellNode.zPosition = 2
170 | cellNode.position = CGPoint(x: x, y: y)
171 | //add to array of cells -- then add to game board
172 | gameArray.append((node: cellNode, point: Point(j, i)))
173 | gameBG.addChild(cellNode)
174 | //iterate x
175 | x += cellSize
176 | }
177 | //reset x, iterate y
178 | x = CGFloat(width / -2) + (cellSize / 2)
179 | y -= cellSize
180 | }
181 | }
182 |
183 | func finishAnimation() {
184 | currentScore.run(scaleOutAction) {
185 | self.currentScore.isHidden = true
186 | }
187 | gameBG.run(scaleOutAction) {
188 | self.gameBG.isHidden = true
189 | self.gameLogo.isHidden = false
190 | self.gameLogo.run(self.moveBackFromTopAction) {
191 | self.playButton.isHidden = false
192 | self.playButton.run(self.scaleInAction)
193 | }
194 | }
195 | }
196 |
197 | }
198 |
--------------------------------------------------------------------------------
/Snake.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 51FEEDCB2215AB720012D2A8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FEEDCA2215AB720012D2A8 /* AppDelegate.swift */; };
11 | 51FEEDCD2215AB720012D2A8 /* GameScene.sks in Resources */ = {isa = PBXBuildFile; fileRef = 51FEEDCC2215AB720012D2A8 /* GameScene.sks */; };
12 | 51FEEDCF2215AB720012D2A8 /* Actions.sks in Resources */ = {isa = PBXBuildFile; fileRef = 51FEEDCE2215AB720012D2A8 /* Actions.sks */; };
13 | 51FEEDD12215AB720012D2A8 /* GameScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FEEDD02215AB720012D2A8 /* GameScene.swift */; };
14 | 51FEEDD32215AB720012D2A8 /* GameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FEEDD22215AB720012D2A8 /* GameViewController.swift */; };
15 | 51FEEDD62215AB720012D2A8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 51FEEDD42215AB720012D2A8 /* Main.storyboard */; };
16 | 51FEEDD82215AB730012D2A8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 51FEEDD72215AB730012D2A8 /* Assets.xcassets */; };
17 | 51FEEDDB2215AB730012D2A8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 51FEEDD92215AB730012D2A8 /* LaunchScreen.storyboard */; };
18 | 51FEEDE62215AB730012D2A8 /* SnakeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FEEDE52215AB730012D2A8 /* SnakeTests.swift */; };
19 | 51FEEDF12215AB730012D2A8 /* SnakeUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FEEDF02215AB730012D2A8 /* SnakeUITests.swift */; };
20 | 51FEEDFF2215AF960012D2A8 /* GameManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51FEEDFE2215AF960012D2A8 /* GameManager.swift */; };
21 | /* End PBXBuildFile section */
22 |
23 | /* Begin PBXContainerItemProxy section */
24 | 51FEEDE22215AB730012D2A8 /* PBXContainerItemProxy */ = {
25 | isa = PBXContainerItemProxy;
26 | containerPortal = 51FEEDBF2215AB720012D2A8 /* Project object */;
27 | proxyType = 1;
28 | remoteGlobalIDString = 51FEEDC62215AB720012D2A8;
29 | remoteInfo = Snake;
30 | };
31 | 51FEEDED2215AB730012D2A8 /* PBXContainerItemProxy */ = {
32 | isa = PBXContainerItemProxy;
33 | containerPortal = 51FEEDBF2215AB720012D2A8 /* Project object */;
34 | proxyType = 1;
35 | remoteGlobalIDString = 51FEEDC62215AB720012D2A8;
36 | remoteInfo = Snake;
37 | };
38 | /* End PBXContainerItemProxy section */
39 |
40 | /* Begin PBXFileReference section */
41 | 51FEEDC72215AB720012D2A8 /* Snake.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Snake.app; sourceTree = BUILT_PRODUCTS_DIR; };
42 | 51FEEDCA2215AB720012D2A8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
43 | 51FEEDCC2215AB720012D2A8 /* GameScene.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = GameScene.sks; sourceTree = ""; };
44 | 51FEEDCE2215AB720012D2A8 /* Actions.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = Actions.sks; sourceTree = ""; };
45 | 51FEEDD02215AB720012D2A8 /* GameScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameScene.swift; sourceTree = ""; };
46 | 51FEEDD22215AB720012D2A8 /* GameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameViewController.swift; sourceTree = ""; };
47 | 51FEEDD52215AB720012D2A8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
48 | 51FEEDD72215AB730012D2A8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
49 | 51FEEDDA2215AB730012D2A8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
50 | 51FEEDDC2215AB730012D2A8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
51 | 51FEEDE12215AB730012D2A8 /* SnakeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SnakeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
52 | 51FEEDE52215AB730012D2A8 /* SnakeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnakeTests.swift; sourceTree = ""; };
53 | 51FEEDE72215AB730012D2A8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
54 | 51FEEDEC2215AB730012D2A8 /* SnakeUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SnakeUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
55 | 51FEEDF02215AB730012D2A8 /* SnakeUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnakeUITests.swift; sourceTree = ""; };
56 | 51FEEDF22215AB730012D2A8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
57 | 51FEEDFE2215AF960012D2A8 /* GameManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameManager.swift; sourceTree = ""; };
58 | /* End PBXFileReference section */
59 |
60 | /* Begin PBXFrameworksBuildPhase section */
61 | 51FEEDC42215AB720012D2A8 /* Frameworks */ = {
62 | isa = PBXFrameworksBuildPhase;
63 | buildActionMask = 2147483647;
64 | files = (
65 | );
66 | runOnlyForDeploymentPostprocessing = 0;
67 | };
68 | 51FEEDDE2215AB730012D2A8 /* Frameworks */ = {
69 | isa = PBXFrameworksBuildPhase;
70 | buildActionMask = 2147483647;
71 | files = (
72 | );
73 | runOnlyForDeploymentPostprocessing = 0;
74 | };
75 | 51FEEDE92215AB730012D2A8 /* Frameworks */ = {
76 | isa = PBXFrameworksBuildPhase;
77 | buildActionMask = 2147483647;
78 | files = (
79 | );
80 | runOnlyForDeploymentPostprocessing = 0;
81 | };
82 | /* End PBXFrameworksBuildPhase section */
83 |
84 | /* Begin PBXGroup section */
85 | 51FEEDBE2215AB720012D2A8 = {
86 | isa = PBXGroup;
87 | children = (
88 | 51FEEDC92215AB720012D2A8 /* Snake */,
89 | 51FEEDE42215AB730012D2A8 /* SnakeTests */,
90 | 51FEEDEF2215AB730012D2A8 /* SnakeUITests */,
91 | 51FEEDC82215AB720012D2A8 /* Products */,
92 | );
93 | sourceTree = "";
94 | };
95 | 51FEEDC82215AB720012D2A8 /* Products */ = {
96 | isa = PBXGroup;
97 | children = (
98 | 51FEEDC72215AB720012D2A8 /* Snake.app */,
99 | 51FEEDE12215AB730012D2A8 /* SnakeTests.xctest */,
100 | 51FEEDEC2215AB730012D2A8 /* SnakeUITests.xctest */,
101 | );
102 | name = Products;
103 | sourceTree = "";
104 | };
105 | 51FEEDC92215AB720012D2A8 /* Snake */ = {
106 | isa = PBXGroup;
107 | children = (
108 | 51FEEDCA2215AB720012D2A8 /* AppDelegate.swift */,
109 | 51FEEDCC2215AB720012D2A8 /* GameScene.sks */,
110 | 51FEEDCE2215AB720012D2A8 /* Actions.sks */,
111 | 51FEEDD02215AB720012D2A8 /* GameScene.swift */,
112 | 51FEEDD22215AB720012D2A8 /* GameViewController.swift */,
113 | 51FEEDD42215AB720012D2A8 /* Main.storyboard */,
114 | 51FEEDD72215AB730012D2A8 /* Assets.xcassets */,
115 | 51FEEDD92215AB730012D2A8 /* LaunchScreen.storyboard */,
116 | 51FEEDDC2215AB730012D2A8 /* Info.plist */,
117 | 51FEEDFE2215AF960012D2A8 /* GameManager.swift */,
118 | );
119 | path = Snake;
120 | sourceTree = "";
121 | };
122 | 51FEEDE42215AB730012D2A8 /* SnakeTests */ = {
123 | isa = PBXGroup;
124 | children = (
125 | 51FEEDE52215AB730012D2A8 /* SnakeTests.swift */,
126 | 51FEEDE72215AB730012D2A8 /* Info.plist */,
127 | );
128 | path = SnakeTests;
129 | sourceTree = "";
130 | };
131 | 51FEEDEF2215AB730012D2A8 /* SnakeUITests */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 51FEEDF02215AB730012D2A8 /* SnakeUITests.swift */,
135 | 51FEEDF22215AB730012D2A8 /* Info.plist */,
136 | );
137 | path = SnakeUITests;
138 | sourceTree = "";
139 | };
140 | /* End PBXGroup section */
141 |
142 | /* Begin PBXNativeTarget section */
143 | 51FEEDC62215AB720012D2A8 /* Snake */ = {
144 | isa = PBXNativeTarget;
145 | buildConfigurationList = 51FEEDF52215AB730012D2A8 /* Build configuration list for PBXNativeTarget "Snake" */;
146 | buildPhases = (
147 | 51FEEDC32215AB720012D2A8 /* Sources */,
148 | 51FEEDC42215AB720012D2A8 /* Frameworks */,
149 | 51FEEDC52215AB720012D2A8 /* Resources */,
150 | );
151 | buildRules = (
152 | );
153 | dependencies = (
154 | );
155 | name = Snake;
156 | productName = Snake;
157 | productReference = 51FEEDC72215AB720012D2A8 /* Snake.app */;
158 | productType = "com.apple.product-type.application";
159 | };
160 | 51FEEDE02215AB730012D2A8 /* SnakeTests */ = {
161 | isa = PBXNativeTarget;
162 | buildConfigurationList = 51FEEDF82215AB730012D2A8 /* Build configuration list for PBXNativeTarget "SnakeTests" */;
163 | buildPhases = (
164 | 51FEEDDD2215AB730012D2A8 /* Sources */,
165 | 51FEEDDE2215AB730012D2A8 /* Frameworks */,
166 | 51FEEDDF2215AB730012D2A8 /* Resources */,
167 | );
168 | buildRules = (
169 | );
170 | dependencies = (
171 | 51FEEDE32215AB730012D2A8 /* PBXTargetDependency */,
172 | );
173 | name = SnakeTests;
174 | productName = SnakeTests;
175 | productReference = 51FEEDE12215AB730012D2A8 /* SnakeTests.xctest */;
176 | productType = "com.apple.product-type.bundle.unit-test";
177 | };
178 | 51FEEDEB2215AB730012D2A8 /* SnakeUITests */ = {
179 | isa = PBXNativeTarget;
180 | buildConfigurationList = 51FEEDFB2215AB730012D2A8 /* Build configuration list for PBXNativeTarget "SnakeUITests" */;
181 | buildPhases = (
182 | 51FEEDE82215AB730012D2A8 /* Sources */,
183 | 51FEEDE92215AB730012D2A8 /* Frameworks */,
184 | 51FEEDEA2215AB730012D2A8 /* Resources */,
185 | );
186 | buildRules = (
187 | );
188 | dependencies = (
189 | 51FEEDEE2215AB730012D2A8 /* PBXTargetDependency */,
190 | );
191 | name = SnakeUITests;
192 | productName = SnakeUITests;
193 | productReference = 51FEEDEC2215AB730012D2A8 /* SnakeUITests.xctest */;
194 | productType = "com.apple.product-type.bundle.ui-testing";
195 | };
196 | /* End PBXNativeTarget section */
197 |
198 | /* Begin PBXProject section */
199 | 51FEEDBF2215AB720012D2A8 /* Project object */ = {
200 | isa = PBXProject;
201 | attributes = {
202 | LastSwiftUpdateCheck = 1010;
203 | LastUpgradeCheck = 1010;
204 | ORGANIZATIONNAME = "Jean-Charles Moussé";
205 | TargetAttributes = {
206 | 51FEEDC62215AB720012D2A8 = {
207 | CreatedOnToolsVersion = 10.1;
208 | };
209 | 51FEEDE02215AB730012D2A8 = {
210 | CreatedOnToolsVersion = 10.1;
211 | TestTargetID = 51FEEDC62215AB720012D2A8;
212 | };
213 | 51FEEDEB2215AB730012D2A8 = {
214 | CreatedOnToolsVersion = 10.1;
215 | TestTargetID = 51FEEDC62215AB720012D2A8;
216 | };
217 | };
218 | };
219 | buildConfigurationList = 51FEEDC22215AB720012D2A8 /* Build configuration list for PBXProject "Snake" */;
220 | compatibilityVersion = "Xcode 9.3";
221 | developmentRegion = en;
222 | hasScannedForEncodings = 0;
223 | knownRegions = (
224 | en,
225 | Base,
226 | );
227 | mainGroup = 51FEEDBE2215AB720012D2A8;
228 | productRefGroup = 51FEEDC82215AB720012D2A8 /* Products */;
229 | projectDirPath = "";
230 | projectRoot = "";
231 | targets = (
232 | 51FEEDC62215AB720012D2A8 /* Snake */,
233 | 51FEEDE02215AB730012D2A8 /* SnakeTests */,
234 | 51FEEDEB2215AB730012D2A8 /* SnakeUITests */,
235 | );
236 | };
237 | /* End PBXProject section */
238 |
239 | /* Begin PBXResourcesBuildPhase section */
240 | 51FEEDC52215AB720012D2A8 /* Resources */ = {
241 | isa = PBXResourcesBuildPhase;
242 | buildActionMask = 2147483647;
243 | files = (
244 | 51FEEDD62215AB720012D2A8 /* Main.storyboard in Resources */,
245 | 51FEEDCD2215AB720012D2A8 /* GameScene.sks in Resources */,
246 | 51FEEDD82215AB730012D2A8 /* Assets.xcassets in Resources */,
247 | 51FEEDDB2215AB730012D2A8 /* LaunchScreen.storyboard in Resources */,
248 | 51FEEDCF2215AB720012D2A8 /* Actions.sks in Resources */,
249 | );
250 | runOnlyForDeploymentPostprocessing = 0;
251 | };
252 | 51FEEDDF2215AB730012D2A8 /* Resources */ = {
253 | isa = PBXResourcesBuildPhase;
254 | buildActionMask = 2147483647;
255 | files = (
256 | );
257 | runOnlyForDeploymentPostprocessing = 0;
258 | };
259 | 51FEEDEA2215AB730012D2A8 /* Resources */ = {
260 | isa = PBXResourcesBuildPhase;
261 | buildActionMask = 2147483647;
262 | files = (
263 | );
264 | runOnlyForDeploymentPostprocessing = 0;
265 | };
266 | /* End PBXResourcesBuildPhase section */
267 |
268 | /* Begin PBXSourcesBuildPhase section */
269 | 51FEEDC32215AB720012D2A8 /* Sources */ = {
270 | isa = PBXSourcesBuildPhase;
271 | buildActionMask = 2147483647;
272 | files = (
273 | 51FEEDD12215AB720012D2A8 /* GameScene.swift in Sources */,
274 | 51FEEDFF2215AF960012D2A8 /* GameManager.swift in Sources */,
275 | 51FEEDD32215AB720012D2A8 /* GameViewController.swift in Sources */,
276 | 51FEEDCB2215AB720012D2A8 /* AppDelegate.swift in Sources */,
277 | );
278 | runOnlyForDeploymentPostprocessing = 0;
279 | };
280 | 51FEEDDD2215AB730012D2A8 /* Sources */ = {
281 | isa = PBXSourcesBuildPhase;
282 | buildActionMask = 2147483647;
283 | files = (
284 | 51FEEDE62215AB730012D2A8 /* SnakeTests.swift in Sources */,
285 | );
286 | runOnlyForDeploymentPostprocessing = 0;
287 | };
288 | 51FEEDE82215AB730012D2A8 /* Sources */ = {
289 | isa = PBXSourcesBuildPhase;
290 | buildActionMask = 2147483647;
291 | files = (
292 | 51FEEDF12215AB730012D2A8 /* SnakeUITests.swift in Sources */,
293 | );
294 | runOnlyForDeploymentPostprocessing = 0;
295 | };
296 | /* End PBXSourcesBuildPhase section */
297 |
298 | /* Begin PBXTargetDependency section */
299 | 51FEEDE32215AB730012D2A8 /* PBXTargetDependency */ = {
300 | isa = PBXTargetDependency;
301 | target = 51FEEDC62215AB720012D2A8 /* Snake */;
302 | targetProxy = 51FEEDE22215AB730012D2A8 /* PBXContainerItemProxy */;
303 | };
304 | 51FEEDEE2215AB730012D2A8 /* PBXTargetDependency */ = {
305 | isa = PBXTargetDependency;
306 | target = 51FEEDC62215AB720012D2A8 /* Snake */;
307 | targetProxy = 51FEEDED2215AB730012D2A8 /* PBXContainerItemProxy */;
308 | };
309 | /* End PBXTargetDependency section */
310 |
311 | /* Begin PBXVariantGroup section */
312 | 51FEEDD42215AB720012D2A8 /* Main.storyboard */ = {
313 | isa = PBXVariantGroup;
314 | children = (
315 | 51FEEDD52215AB720012D2A8 /* Base */,
316 | );
317 | name = Main.storyboard;
318 | sourceTree = "";
319 | };
320 | 51FEEDD92215AB730012D2A8 /* LaunchScreen.storyboard */ = {
321 | isa = PBXVariantGroup;
322 | children = (
323 | 51FEEDDA2215AB730012D2A8 /* Base */,
324 | );
325 | name = LaunchScreen.storyboard;
326 | sourceTree = "";
327 | };
328 | /* End PBXVariantGroup section */
329 |
330 | /* Begin XCBuildConfiguration section */
331 | 51FEEDF32215AB730012D2A8 /* Debug */ = {
332 | isa = XCBuildConfiguration;
333 | buildSettings = {
334 | ALWAYS_SEARCH_USER_PATHS = NO;
335 | CLANG_ANALYZER_NONNULL = YES;
336 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
337 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
338 | CLANG_CXX_LIBRARY = "libc++";
339 | CLANG_ENABLE_MODULES = YES;
340 | CLANG_ENABLE_OBJC_ARC = YES;
341 | CLANG_ENABLE_OBJC_WEAK = YES;
342 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
343 | CLANG_WARN_BOOL_CONVERSION = YES;
344 | CLANG_WARN_COMMA = YES;
345 | CLANG_WARN_CONSTANT_CONVERSION = YES;
346 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
347 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
348 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
349 | CLANG_WARN_EMPTY_BODY = YES;
350 | CLANG_WARN_ENUM_CONVERSION = YES;
351 | CLANG_WARN_INFINITE_RECURSION = YES;
352 | CLANG_WARN_INT_CONVERSION = YES;
353 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
354 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
355 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
356 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
357 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
358 | CLANG_WARN_STRICT_PROTOTYPES = YES;
359 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
360 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
361 | CLANG_WARN_UNREACHABLE_CODE = YES;
362 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
363 | CODE_SIGN_IDENTITY = "iPhone Developer";
364 | COPY_PHASE_STRIP = NO;
365 | DEBUG_INFORMATION_FORMAT = dwarf;
366 | ENABLE_STRICT_OBJC_MSGSEND = YES;
367 | ENABLE_TESTABILITY = YES;
368 | GCC_C_LANGUAGE_STANDARD = gnu11;
369 | GCC_DYNAMIC_NO_PIC = NO;
370 | GCC_NO_COMMON_BLOCKS = YES;
371 | GCC_OPTIMIZATION_LEVEL = 0;
372 | GCC_PREPROCESSOR_DEFINITIONS = (
373 | "DEBUG=1",
374 | "$(inherited)",
375 | );
376 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
377 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
378 | GCC_WARN_UNDECLARED_SELECTOR = YES;
379 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
380 | GCC_WARN_UNUSED_FUNCTION = YES;
381 | GCC_WARN_UNUSED_VARIABLE = YES;
382 | IPHONEOS_DEPLOYMENT_TARGET = 12.1;
383 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
384 | MTL_FAST_MATH = YES;
385 | ONLY_ACTIVE_ARCH = YES;
386 | SDKROOT = iphoneos;
387 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
388 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
389 | };
390 | name = Debug;
391 | };
392 | 51FEEDF42215AB730012D2A8 /* Release */ = {
393 | isa = XCBuildConfiguration;
394 | buildSettings = {
395 | ALWAYS_SEARCH_USER_PATHS = NO;
396 | CLANG_ANALYZER_NONNULL = YES;
397 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
398 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
399 | CLANG_CXX_LIBRARY = "libc++";
400 | CLANG_ENABLE_MODULES = YES;
401 | CLANG_ENABLE_OBJC_ARC = YES;
402 | CLANG_ENABLE_OBJC_WEAK = YES;
403 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
404 | CLANG_WARN_BOOL_CONVERSION = YES;
405 | CLANG_WARN_COMMA = YES;
406 | CLANG_WARN_CONSTANT_CONVERSION = YES;
407 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
408 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
409 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
410 | CLANG_WARN_EMPTY_BODY = YES;
411 | CLANG_WARN_ENUM_CONVERSION = YES;
412 | CLANG_WARN_INFINITE_RECURSION = YES;
413 | CLANG_WARN_INT_CONVERSION = YES;
414 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
415 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
416 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
417 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
418 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
419 | CLANG_WARN_STRICT_PROTOTYPES = YES;
420 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
421 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
422 | CLANG_WARN_UNREACHABLE_CODE = YES;
423 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
424 | CODE_SIGN_IDENTITY = "iPhone Developer";
425 | COPY_PHASE_STRIP = NO;
426 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
427 | ENABLE_NS_ASSERTIONS = NO;
428 | ENABLE_STRICT_OBJC_MSGSEND = YES;
429 | GCC_C_LANGUAGE_STANDARD = gnu11;
430 | GCC_NO_COMMON_BLOCKS = YES;
431 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
432 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
433 | GCC_WARN_UNDECLARED_SELECTOR = YES;
434 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
435 | GCC_WARN_UNUSED_FUNCTION = YES;
436 | GCC_WARN_UNUSED_VARIABLE = YES;
437 | IPHONEOS_DEPLOYMENT_TARGET = 12.1;
438 | MTL_ENABLE_DEBUG_INFO = NO;
439 | MTL_FAST_MATH = YES;
440 | SDKROOT = iphoneos;
441 | SWIFT_COMPILATION_MODE = wholemodule;
442 | SWIFT_OPTIMIZATION_LEVEL = "-O";
443 | VALIDATE_PRODUCT = YES;
444 | };
445 | name = Release;
446 | };
447 | 51FEEDF62215AB730012D2A8 /* Debug */ = {
448 | isa = XCBuildConfiguration;
449 | buildSettings = {
450 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
451 | CODE_SIGN_STYLE = Automatic;
452 | DEVELOPMENT_TEAM = 2S9LUT86C4;
453 | INFOPLIST_FILE = Snake/Info.plist;
454 | LD_RUNPATH_SEARCH_PATHS = (
455 | "$(inherited)",
456 | "@executable_path/Frameworks",
457 | );
458 | PRODUCT_BUNDLE_IDENTIFIER = com.pyozer.Snake;
459 | PRODUCT_NAME = "$(TARGET_NAME)";
460 | SWIFT_VERSION = 4.2;
461 | TARGETED_DEVICE_FAMILY = "1,2";
462 | };
463 | name = Debug;
464 | };
465 | 51FEEDF72215AB730012D2A8 /* Release */ = {
466 | isa = XCBuildConfiguration;
467 | buildSettings = {
468 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
469 | CODE_SIGN_STYLE = Automatic;
470 | DEVELOPMENT_TEAM = 2S9LUT86C4;
471 | INFOPLIST_FILE = Snake/Info.plist;
472 | LD_RUNPATH_SEARCH_PATHS = (
473 | "$(inherited)",
474 | "@executable_path/Frameworks",
475 | );
476 | PRODUCT_BUNDLE_IDENTIFIER = com.pyozer.Snake;
477 | PRODUCT_NAME = "$(TARGET_NAME)";
478 | SWIFT_VERSION = 4.2;
479 | TARGETED_DEVICE_FAMILY = "1,2";
480 | };
481 | name = Release;
482 | };
483 | 51FEEDF92215AB730012D2A8 /* Debug */ = {
484 | isa = XCBuildConfiguration;
485 | buildSettings = {
486 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
487 | BUNDLE_LOADER = "$(TEST_HOST)";
488 | CODE_SIGN_STYLE = Automatic;
489 | INFOPLIST_FILE = SnakeTests/Info.plist;
490 | LD_RUNPATH_SEARCH_PATHS = (
491 | "$(inherited)",
492 | "@executable_path/Frameworks",
493 | "@loader_path/Frameworks",
494 | );
495 | PRODUCT_BUNDLE_IDENTIFIER = com.pyozer.SnakeTests;
496 | PRODUCT_NAME = "$(TARGET_NAME)";
497 | SWIFT_VERSION = 4.2;
498 | TARGETED_DEVICE_FAMILY = "1,2";
499 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Snake.app/Snake";
500 | };
501 | name = Debug;
502 | };
503 | 51FEEDFA2215AB730012D2A8 /* Release */ = {
504 | isa = XCBuildConfiguration;
505 | buildSettings = {
506 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
507 | BUNDLE_LOADER = "$(TEST_HOST)";
508 | CODE_SIGN_STYLE = Automatic;
509 | INFOPLIST_FILE = SnakeTests/Info.plist;
510 | LD_RUNPATH_SEARCH_PATHS = (
511 | "$(inherited)",
512 | "@executable_path/Frameworks",
513 | "@loader_path/Frameworks",
514 | );
515 | PRODUCT_BUNDLE_IDENTIFIER = com.pyozer.SnakeTests;
516 | PRODUCT_NAME = "$(TARGET_NAME)";
517 | SWIFT_VERSION = 4.2;
518 | TARGETED_DEVICE_FAMILY = "1,2";
519 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Snake.app/Snake";
520 | };
521 | name = Release;
522 | };
523 | 51FEEDFC2215AB730012D2A8 /* Debug */ = {
524 | isa = XCBuildConfiguration;
525 | buildSettings = {
526 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
527 | CODE_SIGN_STYLE = Automatic;
528 | INFOPLIST_FILE = SnakeUITests/Info.plist;
529 | LD_RUNPATH_SEARCH_PATHS = (
530 | "$(inherited)",
531 | "@executable_path/Frameworks",
532 | "@loader_path/Frameworks",
533 | );
534 | PRODUCT_BUNDLE_IDENTIFIER = com.pyozer.SnakeUITests;
535 | PRODUCT_NAME = "$(TARGET_NAME)";
536 | SWIFT_VERSION = 4.2;
537 | TARGETED_DEVICE_FAMILY = "1,2";
538 | TEST_TARGET_NAME = Snake;
539 | };
540 | name = Debug;
541 | };
542 | 51FEEDFD2215AB730012D2A8 /* Release */ = {
543 | isa = XCBuildConfiguration;
544 | buildSettings = {
545 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
546 | CODE_SIGN_STYLE = Automatic;
547 | INFOPLIST_FILE = SnakeUITests/Info.plist;
548 | LD_RUNPATH_SEARCH_PATHS = (
549 | "$(inherited)",
550 | "@executable_path/Frameworks",
551 | "@loader_path/Frameworks",
552 | );
553 | PRODUCT_BUNDLE_IDENTIFIER = com.pyozer.SnakeUITests;
554 | PRODUCT_NAME = "$(TARGET_NAME)";
555 | SWIFT_VERSION = 4.2;
556 | TARGETED_DEVICE_FAMILY = "1,2";
557 | TEST_TARGET_NAME = Snake;
558 | };
559 | name = Release;
560 | };
561 | /* End XCBuildConfiguration section */
562 |
563 | /* Begin XCConfigurationList section */
564 | 51FEEDC22215AB720012D2A8 /* Build configuration list for PBXProject "Snake" */ = {
565 | isa = XCConfigurationList;
566 | buildConfigurations = (
567 | 51FEEDF32215AB730012D2A8 /* Debug */,
568 | 51FEEDF42215AB730012D2A8 /* Release */,
569 | );
570 | defaultConfigurationIsVisible = 0;
571 | defaultConfigurationName = Release;
572 | };
573 | 51FEEDF52215AB730012D2A8 /* Build configuration list for PBXNativeTarget "Snake" */ = {
574 | isa = XCConfigurationList;
575 | buildConfigurations = (
576 | 51FEEDF62215AB730012D2A8 /* Debug */,
577 | 51FEEDF72215AB730012D2A8 /* Release */,
578 | );
579 | defaultConfigurationIsVisible = 0;
580 | defaultConfigurationName = Release;
581 | };
582 | 51FEEDF82215AB730012D2A8 /* Build configuration list for PBXNativeTarget "SnakeTests" */ = {
583 | isa = XCConfigurationList;
584 | buildConfigurations = (
585 | 51FEEDF92215AB730012D2A8 /* Debug */,
586 | 51FEEDFA2215AB730012D2A8 /* Release */,
587 | );
588 | defaultConfigurationIsVisible = 0;
589 | defaultConfigurationName = Release;
590 | };
591 | 51FEEDFB2215AB730012D2A8 /* Build configuration list for PBXNativeTarget "SnakeUITests" */ = {
592 | isa = XCConfigurationList;
593 | buildConfigurations = (
594 | 51FEEDFC2215AB730012D2A8 /* Debug */,
595 | 51FEEDFD2215AB730012D2A8 /* Release */,
596 | );
597 | defaultConfigurationIsVisible = 0;
598 | defaultConfigurationName = Release;
599 | };
600 | /* End XCConfigurationList section */
601 | };
602 | rootObject = 51FEEDBF2215AB720012D2A8 /* Project object */;
603 | }
604 |
--------------------------------------------------------------------------------