Skip to content

Commit 0414a35

Browse files
committed
Merge branch 'updates/1.4'
2 parents 817c03b + 44a3d44 commit 0414a35

File tree

9 files changed

+207
-11
lines changed

9 files changed

+207
-11
lines changed

ios-spritekit-flappy-flying-bird.xcodeproj/project.pbxproj

+6-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
A903943A20AD9E7900376CC3 /* RainParticleEffect.sks in Resources */ = {isa = PBXBuildFile; fileRef = A903943820AD9E7900376CC3 /* RainParticleEffect.sks */; };
1414
A903943B20AD9E7900376CC3 /* Particles.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A903943920AD9E7900376CC3 /* Particles.xcassets */; };
1515
A903943F20ADB24000376CC3 /* ToggleButtonNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = A903943E20ADB24000376CC3 /* ToggleButtonNode.swift */; };
16+
A9092FA5216B35C800D773BC /* TriggleButtonNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9092FA4216B35C800D773BC /* TriggleButtonNode.swift */; };
1617
A92E72E2209D815B0015F647 /* PlayingState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92E72E1209D815B0015F647 /* PlayingState.swift */; };
1718
A92E72E4209D81820015F647 /* GameOverState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92E72E3209D81820015F647 /* GameOverState.swift */; };
1819
A92E72E6209D818B0015F647 /* PausedState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92E72E5209D818B0015F647 /* PausedState.swift */; };
@@ -110,6 +111,7 @@
110111
A903943820AD9E7900376CC3 /* RainParticleEffect.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = RainParticleEffect.sks; sourceTree = "<group>"; };
111112
A903943920AD9E7900376CC3 /* Particles.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Particles.xcassets; sourceTree = "<group>"; };
112113
A903943E20ADB24000376CC3 /* ToggleButtonNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleButtonNode.swift; sourceTree = "<group>"; };
114+
A9092FA4216B35C800D773BC /* TriggleButtonNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TriggleButtonNode.swift; sourceTree = "<group>"; };
113115
A92E72E1209D815B0015F647 /* PlayingState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayingState.swift; sourceTree = "<group>"; };
114116
A92E72E3209D81820015F647 /* GameOverState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameOverState.swift; sourceTree = "<group>"; };
115117
A92E72E5209D818B0015F647 /* PausedState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PausedState.swift; sourceTree = "<group>"; };
@@ -227,6 +229,7 @@
227229
children = (
228230
A92E72ED209D87570015F647 /* ButtonNode.swift */,
229231
A903943E20ADB24000376CC3 /* ToggleButtonNode.swift */,
232+
A9092FA4216B35C800D773BC /* TriggleButtonNode.swift */,
230233
);
231234
path = "UI Components";
232235
sourceTree = "<group>";
@@ -721,6 +724,7 @@
721724
A9EC756820A6E479007C42EC /* RoutingUtilityScene.swift in Sources */,
722725
A9D4CFD7209AF515006461AF /* SKScene+SpriteUploader.swift in Sources */,
723726
A92E72EE209D87570015F647 /* ButtonNode.swift in Sources */,
727+
A9092FA5216B35C800D773BC /* TriggleButtonNode.swift in Sources */,
724728
A992D8B620A03B90003A9998 /* SceneOverlay.swift in Sources */,
725729
A9ACB9232099A1F200966991 /* GameScene.swift in Sources */,
726730
A9ACB98D2099F0FC00966991 /* Touchable.swift in Sources */,
@@ -919,7 +923,7 @@
919923
"$(inherited)",
920924
"@executable_path/Frameworks",
921925
);
922-
PRODUCT_BUNDLE_IDENTIFIER = "eleev.astemir.io.ios-spritekit-flappy-fly-bird";
926+
PRODUCT_BUNDLE_IDENTIFIER = "eleev.astemir.io.ios-spritekit-flappy-fly-bird-";
923927
PRODUCT_NAME = "$(TARGET_NAME)";
924928
SWIFT_VERSION = 4.2;
925929
TARGETED_DEVICE_FAMILY = "1,2";
@@ -937,7 +941,7 @@
937941
"$(inherited)",
938942
"@executable_path/Frameworks",
939943
);
940-
PRODUCT_BUNDLE_IDENTIFIER = "eleev.astemir.io.ios-spritekit-flappy-fly-bird";
944+
PRODUCT_BUNDLE_IDENTIFIER = "eleev.astemir.io.ios-spritekit-flappy-fly-bird-";
941945
PRODUCT_NAME = "$(TARGET_NAME)";
942946
SWIFT_VERSION = 4.2;
943947
TARGETED_DEVICE_FAMILY = "1,2";
Binary file not shown.

ios-spritekit-flappy-flying-bird/Factories/PipeFactory.swift

+4-3
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ struct PipeFactory {
3535
let cleanUpAction = SKAction.run {
3636
targetNode.childNode(withName: pipeName)?.removeFromParent()
3737
}
38-
let waitAction = SKAction.wait(forDuration: 3.0)
38+
39+
let waitAction = SKAction.wait(forDuration: UserDefaults.standard.getDifficultyLevel().rawValue)
3940
let pipeMoveDuration: TimeInterval = 4.5
4041

4142
let producePipeAction = SKAction.run {
@@ -145,11 +146,11 @@ struct PipeFactory {
145146
}
146147

147148
// Threshold node
148-
let threshold = SKSpriteNode(color: .clear, size: CGSize(width: thresholdWidth, height: CGFloat.range(min: 800, max: 1100)))
149+
let threshold = SKSpriteNode(color: .clear, size: CGSize(width: thresholdWidth, height: CGFloat.range(min: 700, max: 1200)))
149150
threshold.position = CGPoint(x: pipeX, y: (pipeBottom?.size.height)! + threshold.size.height / 2)
150151

151152
threshold.physicsBody = SKPhysicsBody(rectangleOf: threshold.size)
152-
threshold.physicsBody?.categoryBitMask = PhysicsCategories.gap.rawValue
153+
threshold.physicsBody?.categoryBitMask = PhysicsCategories.gap.rawValue
153154
threshold.physicsBody?.contactTestBitMask = PhysicsCategories.player.rawValue
154155
threshold.physicsBody?.collisionBitMask = 0
155156
threshold.physicsBody?.isDynamic = false

ios-spritekit-flappy-flying-bird/Info.plist

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<key>CFBundlePackageType</key>
1818
<string>APPL</string>
1919
<key>CFBundleShortVersionString</key>
20-
<string>1.3.1</string>
20+
<string>1.4.0</string>
2121
<key>CFBundleVersion</key>
2222
<string>1</string>
2323
<key>LSRequiresIPhoneOS</key>

ios-spritekit-flappy-flying-bird/Nodes/UI Components/ButtonNode.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,11 @@ enum ButtonIdentifier: String {
2727
case scores = "Scores"
2828
case sound = "Sound"
2929
case characters = "Characters"
30+
case difficulty = "Difficulty"
3031

3132
/// Convenience array of all available button identifiers.
3233
static let allButtonIdentifiers: [ButtonIdentifier] = [
33-
.play, .pause, .resume, .menu, .settings, .home, .retry, .cancel, .scores, sound, .characters
34+
.play, .pause, .resume, .menu, .settings, .home, .retry, .cancel, .scores, sound, .characters, .difficulty
3435
]
3536

3637
/// The name of the texture to use for a button when the button is selected.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
//
2+
// TriggleButtonNode.swift
3+
// ios-spritekit-flappy-flying-bird
4+
//
5+
// Created by Astemir Eleev on 08/10/2018.
6+
// Copyright © 2018 Astemir Eleev. All rights reserved.
7+
//
8+
9+
import SpriteKit
10+
11+
/// A type that can respond to `TriggleButtonNode` button press events.
12+
protocol TriggleButtonNodeResponderType: class {
13+
/// Responds to a button press.
14+
func triggleButtonTriggered(triggle: TriggleButtonNode)
15+
}
16+
17+
class TriggleButtonNode: ButtonNode {
18+
19+
// MARK: - Custom types
20+
21+
enum TriggleState {
22+
case off
23+
case switched
24+
case on
25+
26+
static func convert(from difficultyLevel: Difficulty) -> TriggleState {
27+
switch difficultyLevel {
28+
case .easy:
29+
return .off
30+
case .medium:
31+
return .switched
32+
case .hard:
33+
return .on
34+
}
35+
}
36+
}
37+
38+
struct Triggle {
39+
40+
// MARK: - Properties
41+
42+
private(set) var off: Bool
43+
private(set) var switched: Bool
44+
private(set) var on: Bool
45+
private var lastTriggleState: TriggleState
46+
47+
// MARK: - Initializers
48+
49+
init(state: TriggleState) {
50+
switch state {
51+
case .off:
52+
off = true
53+
switched = false
54+
on = false
55+
lastTriggleState = .off
56+
case .switched:
57+
off = false
58+
switched = true
59+
on = false
60+
lastTriggleState = .switched
61+
case .on:
62+
off = false
63+
switched = false
64+
on = true
65+
lastTriggleState = .on
66+
}
67+
}
68+
69+
// MARK: - Methods
70+
71+
mutating func switchState() {
72+
if off {
73+
off = !off
74+
switched = !switched
75+
lastTriggleState = .switched
76+
} else if switched {
77+
switched = !switched
78+
on = !on
79+
lastTriggleState = .on
80+
} else if on {
81+
on = !on
82+
off = !off
83+
lastTriggleState = .off
84+
}
85+
}
86+
87+
func state() -> TriggleState {
88+
return lastTriggleState
89+
}
90+
91+
func toDifficultyLevel() -> Difficulty {
92+
switch lastTriggleState {
93+
case .off:
94+
return Difficulty.easy
95+
case .switched:
96+
return Difficulty.medium
97+
case .on:
98+
return Difficulty.hard
99+
}
100+
}
101+
102+
}
103+
104+
// MARK: - Properties
105+
106+
var triggle: Triggle {
107+
didSet {
108+
guard let off = state.off, let switched = state.switched, let on = state.on else {
109+
return
110+
}
111+
on.isHidden = !triggle.on
112+
off.isHidden = !triggle.off
113+
switched.isHidden = !triggle.switched
114+
115+
if isUserInteractionEnabled {
116+
triggleResponder.triggleButtonTriggered(triggle: self)
117+
}
118+
}
119+
}
120+
121+
private var state: (off: SKLabelNode?, switched: SKLabelNode?, on: SKLabelNode?) = (off: nil, switched: nil, on: nil)
122+
123+
var triggleResponder: TriggleButtonNodeResponderType {
124+
guard let responder = scene as? TriggleButtonNodeResponderType else {
125+
fatalError("ButtonNode may only be used within a `ButtonNodeResponderType` scene.")
126+
}
127+
return responder
128+
}
129+
130+
131+
// MARK: - Initialisers
132+
133+
required init?(coder aDecoder: NSCoder) {
134+
let difficultyLevel = UserDefaults.standard.getDifficultyLevel()
135+
triggle = .init(state: TriggleState.convert(from: difficultyLevel))
136+
137+
super.init(coder: aDecoder)
138+
139+
guard let offState = childNode(withName: "Easy") as? SKLabelNode else {
140+
fatalError("Could not find SKLabel node")
141+
}
142+
state.off = offState
143+
144+
guard let switchedState = childNode(withName: "Medium") as? SKLabelNode else {
145+
fatalError("Could not find SKLabel node")
146+
}
147+
state.switched = switchedState
148+
149+
guard let onState = childNode(withName: "Hard") as? SKLabelNode else {
150+
fatalError("Could not find SKLabel node")
151+
}
152+
state.on = onState
153+
154+
}
155+
156+
// MARK: - Methods
157+
158+
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
159+
super.touchesBegan(touches, with: event)
160+
triggle.switchState()
161+
}
162+
}

ios-spritekit-flappy-flying-bird/Scenes/RoutingUtilityScene.swift

-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ class RoutingUtilityScene: SKScene, ButtonNodeResponderType {
2020
// MARK: - Conformance to ButtonNodeResponderType
2121

2222
func buttonTriggered(button: ButtonNode) {
23-
debugPrint(#function + " button was triggered with identifier of : ", button.buttonIdentifier)
24-
2523
guard let identifier = button.buttonIdentifier else {
2624
return
2725
}

ios-spritekit-flappy-flying-bird/Scenes/SettingsScene.swift

+15-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import SpriteKit
1010

11-
class SettingsScene: RoutingUtilityScene, ToggleButtonNodeResponderType {
11+
class SettingsScene: RoutingUtilityScene, ToggleButtonNodeResponderType, TriggleButtonNodeResponderType {
1212

1313
// MARK: - Overrides
1414

@@ -17,11 +17,25 @@ class SettingsScene: RoutingUtilityScene, ToggleButtonNodeResponderType {
1717

1818
let soundButton = scene?.childNode(withName: "Sound") as? ToggleButtonNode
1919
soundButton?.isOn = UserDefaults.standard.bool(for: .isSoundOn)
20+
21+
let difficultyButton = scene?.childNode(withName: "Difficulty") as? TriggleButtonNode
22+
let difficultyLevel = UserDefaults.standard.getDifficultyLevel()
23+
let difficultyState = TriggleButtonNode.TriggleState.convert(from: difficultyLevel)
24+
difficultyButton?.triggle = .init(state: difficultyState)
2025
}
2126

2227
// MARK: - Confrormance to ToggleButtonResponderType
2328

2429
func toggleButtonTriggered(toggle: ToggleButtonNode) {
2530
UserDefaults.standard.set(toggle.isOn, for: .isSoundOn)
2631
}
32+
33+
// MARK: - Conformance to TriggleButtonResponderType
34+
35+
func triggleButtonTriggered(triggle: TriggleButtonNode) {
36+
debugPrint("triggleButtonTriggered")
37+
let diffuculty = triggle.triggle.toDifficultyLevel()
38+
UserDefaults.standard.set(difficultyLevel: diffuculty)
39+
}
40+
2741
}

ios-spritekit-flappy-flying-bird/Utils/UserDefaults.swift

+17-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ extension UserDefaults {
3838
func set(_ playableCharacter: PlayableCharacter, for setting: Setting) {
3939
set(playableCharacter.rawValue, forKey: setting.rawValue)
4040
}
41+
42+
func set(difficultyLevel level: Difficulty) {
43+
set(level.rawValue, forKey: Setting.difficulty.rawValue)
44+
}
45+
46+
func getDifficultyLevel() -> Difficulty {
47+
let value = double(forKey: Setting.difficulty.rawValue)
48+
return Difficulty(rawValue: value) ?? .medium
49+
}
4150
}
4251

4352

@@ -49,6 +58,7 @@ enum Setting: String {
4958
case lastScore
5059
case isSoundOn
5160
case character
61+
case difficulty
5262

5363
// MARK: - Methods
5464

@@ -57,11 +67,17 @@ enum Setting: String {
5767
Setting.bestScore.rawValue: 0,
5868
Setting.lastScore.rawValue: 0,
5969
Setting.isSoundOn.rawValue: true,
60-
Setting.character.rawValue: PlayableCharacter.bird.rawValue
70+
Setting.character.rawValue: PlayableCharacter.bird.rawValue,
71+
Setting.difficulty.rawValue: Difficulty.medium.rawValue
6172
])
6273
}
6374
}
6475

76+
enum Difficulty: Double {
77+
case easy = 4.0
78+
case medium = 3.5
79+
case hard = 3.0
80+
}
6581

6682
enum PlayableCharacter: String {
6783
case bird = "bird"

0 commit comments

Comments
 (0)