Mercurial > public > geoquiz
comparison GeoQuiz/Logic/GameProtocol+Extension.swift @ 10:a793f33f05fb
refactor code and fix layout
author | Dennis C. M. <dennis@denniscm.com> |
---|---|
date | Sat, 08 Oct 2022 21:36:40 +0200 |
parents | GeoQuiz/Logic/Game.swift@3540c7efc216 |
children | 136928bae534 |
comparison
equal
deleted
inserted
replaced
9:3540c7efc216 | 10:a793f33f05fb |
---|---|
1 // | |
2 // GameProtocol+Extension.swift | |
3 // GeoQuiz | |
4 // | |
5 // Created by Dennis Concepción Martín on 18/9/22. | |
6 // | |
7 | |
8 import Foundation | |
9 import SwiftUI | |
10 import AVFAudio | |
11 | |
12 protocol Game: ObservableObject { | |
13 | |
14 // Define generic type | |
15 associatedtype T: Equatable | |
16 | |
17 // Game | |
18 var data: [String: T] { get set} | |
19 var dataAsked: [String: T] { get set } | |
20 var correctAnswer: (key: String, value: T) { get set } | |
21 | |
22 // User | |
23 var userChoices: [String: T] { get set } | |
24 var userScore: Int { get set } | |
25 var userLives: Int { get set } | |
26 var correctAnswers: [String: T] { get set } | |
27 var wrongAnswers: [String: T] { get set } | |
28 | |
29 // Alerts | |
30 var alertTitle: String { get set } | |
31 var alertMessage: String { get set } | |
32 var showingGameOverAlert: Bool { get set } | |
33 var showingEndGameAlert: Bool { get set } | |
34 var showingWrongAnswerAlert: Bool { get set } | |
35 var showingExitGameAlert: Bool { get set } | |
36 | |
37 // Animations | |
38 var scoreScaleAmount: Double { get set } | |
39 var livesScaleAmount: Double { get set } | |
40 | |
41 // Sound effects | |
42 var player: AVAudioPlayer? { get set } | |
43 | |
44 func selector() | |
45 } | |
46 | |
47 extension Game { | |
48 var questionCounter: Int { | |
49 dataAsked.count | |
50 } | |
51 | |
52 func askQuestion(selector: () -> Void) { | |
53 guard questionCounter < data.count else { | |
54 alertTitle = "⭐️ Congratulations ⭐️" | |
55 alertMessage = "You completed the game." | |
56 showingEndGameAlert = true | |
57 | |
58 return | |
59 } | |
60 | |
61 selector() | |
62 } | |
63 | |
64 func answer(_ choice: (key: String, value: T), selector: () -> Void) { | |
65 let haptics = Haptics() | |
66 | |
67 if correctAnswer == choice { | |
68 haptics.success() | |
69 playSound("correctAnswer") | |
70 | |
71 withAnimation(.easeIn(duration: 0.5)) { | |
72 scoreScaleAmount += 1 | |
73 userScore += 1 | |
74 } | |
75 | |
76 correctAnswers[correctAnswer.key] = correctAnswer.value | |
77 askQuestion { | |
78 selector() | |
79 } | |
80 } else { | |
81 haptics.error() | |
82 playSound("wrongAnswer") | |
83 | |
84 withAnimation(.easeIn(duration: 0.5)) { | |
85 livesScaleAmount += 1 | |
86 userLives -= 1 | |
87 } | |
88 | |
89 wrongAnswers[choice.key] = choice.value | |
90 | |
91 if userLives == 0 { | |
92 alertTitle = "🤕 Game over 🤕" | |
93 alertMessage = "Get up and try again." | |
94 showingGameOverAlert = true | |
95 } else { | |
96 alertTitle = "🔴 Wrong 🔴" | |
97 alertMessage = "You have \(userLives) lives left." | |
98 showingWrongAnswerAlert = true | |
99 } | |
100 } | |
101 | |
102 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [self] in | |
103 withAnimation(.easeIn(duration: 0.5)) { | |
104 scoreScaleAmount = 1 | |
105 livesScaleAmount = 1 | |
106 } | |
107 } | |
108 } | |
109 | |
110 func reset(selector: () -> Void) { | |
111 dataAsked = [String: T]() | |
112 userScore = 0 | |
113 userLives = 3 | |
114 correctAnswers = [String: T]() | |
115 wrongAnswers = [String: T]() | |
116 askQuestion { | |
117 selector() | |
118 } | |
119 } | |
120 | |
121 private func playSound(_ filename: String) { | |
122 let user = User() | |
123 | |
124 if user.settings.sound { | |
125 guard let soundFileURL = Bundle.main.url(forResource: filename, withExtension: "wav") else { | |
126 fatalError("Sound file \(filename) couldn't be found") | |
127 } | |
128 | |
129 do { | |
130 try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.ambient) | |
131 try AVAudioSession.sharedInstance().setActive(true) | |
132 } catch { | |
133 fatalError("Couldn't activate session") | |
134 } | |
135 | |
136 do { | |
137 player = try AVAudioPlayer(contentsOf: soundFileURL) | |
138 player?.play() | |
139 } catch { | |
140 fatalError("Couldn't play sound effect") | |
141 } | |
142 } | |
143 } | |
144 } |