Mercurial > public > geoquiz
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GeoQuiz/Logic/GameProtocol+Extension.swift Sat Oct 08 21:36:40 2022 +0200 @@ -0,0 +1,144 @@ +// +// GameProtocol+Extension.swift +// GeoQuiz +// +// Created by Dennis Concepción Martín on 18/9/22. +// + +import Foundation +import SwiftUI +import AVFAudio + +protocol Game: ObservableObject { + + // Define generic type + associatedtype T: Equatable + + // Game + var data: [String: T] { get set} + var dataAsked: [String: T] { get set } + var correctAnswer: (key: String, value: T) { get set } + + // User + var userChoices: [String: T] { get set } + var userScore: Int { get set } + var userLives: Int { get set } + var correctAnswers: [String: T] { get set } + var wrongAnswers: [String: T] { get set } + + // Alerts + var alertTitle: String { get set } + var alertMessage: String { get set } + var showingGameOverAlert: Bool { get set } + var showingEndGameAlert: Bool { get set } + var showingWrongAnswerAlert: Bool { get set } + var showingExitGameAlert: Bool { get set } + + // Animations + var scoreScaleAmount: Double { get set } + var livesScaleAmount: Double { get set } + + // Sound effects + var player: AVAudioPlayer? { get set } + + func selector() +} + +extension Game { + var questionCounter: Int { + dataAsked.count + } + + func askQuestion(selector: () -> Void) { + guard questionCounter < data.count else { + alertTitle = "⭐️ Congratulations ⭐️" + alertMessage = "You completed the game." + showingEndGameAlert = true + + return + } + + selector() + } + + func answer(_ choice: (key: String, value: T), selector: () -> Void) { + let haptics = Haptics() + + if correctAnswer == choice { + haptics.success() + playSound("correctAnswer") + + withAnimation(.easeIn(duration: 0.5)) { + scoreScaleAmount += 1 + userScore += 1 + } + + correctAnswers[correctAnswer.key] = correctAnswer.value + askQuestion { + selector() + } + } else { + haptics.error() + playSound("wrongAnswer") + + withAnimation(.easeIn(duration: 0.5)) { + livesScaleAmount += 1 + userLives -= 1 + } + + wrongAnswers[choice.key] = choice.value + + if userLives == 0 { + alertTitle = "🤕 Game over 🤕" + alertMessage = "Get up and try again." + showingGameOverAlert = true + } else { + alertTitle = "🔴 Wrong 🔴" + alertMessage = "You have \(userLives) lives left." + showingWrongAnswerAlert = true + } + } + + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [self] in + withAnimation(.easeIn(duration: 0.5)) { + scoreScaleAmount = 1 + livesScaleAmount = 1 + } + } + } + + func reset(selector: () -> Void) { + dataAsked = [String: T]() + userScore = 0 + userLives = 3 + correctAnswers = [String: T]() + wrongAnswers = [String: T]() + askQuestion { + selector() + } + } + + private func playSound(_ filename: String) { + let user = User() + + if user.settings.sound { + guard let soundFileURL = Bundle.main.url(forResource: filename, withExtension: "wav") else { + fatalError("Sound file \(filename) couldn't be found") + } + + do { + try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.ambient) + try AVAudioSession.sharedInstance().setActive(true) + } catch { + fatalError("Couldn't activate session") + } + + do { + player = try AVAudioPlayer(contentsOf: soundFileURL) + player?.play() + } catch { + fatalError("Couldn't play sound effect") + } + } + } +}