I'm trying to recreate a popular game: Heads up, basically the user has to try to guess the name putting the phone on his head, with friends' suggestions...if he raises the head he skips the word, if he lowers the head it means he guessed the name and he earns a point. He has limited time. I need that every time the user raises/lowers his head, the array's name changes, and each name must appear only once. Any suggestions?
This is my code:
import SwiftUI
import CoreMotion
struct ContentView: View {
let motionManager = CMMotionManager()
let queue = OperationQueue()
@State private var roll = Double.zero
@State private var people = ["John", "Marcus", "Steve", "Eric", "Philip"].shuffled()
@State private var randomPerson = Int.random(in: 0...4)
let timer = Timer.publish(every: 1, tolerance: 0.5, on: .main, in: .common).autoconnect()
@State private var timeRemaining = 10
@State private var score = 0
var body: some View {
NavigationView {
ZStack {
//Show a red background and "SKIP" if the user raises head
if roll < 1 {
Color.red
.ignoresSafeArea()
Text("SKIP")
.font(.largeTitle)
.bold()
.foregroundColor(.white)
} else if roll > 2.1 {
//Show a green background and "CORRECT" if user lowers head
Color.green
.ignoresSafeArea()
Text("CORRECT")
.font(.largeTitle)
.bold()
.foregroundColor(.white)
.onAppear {
score += 1
}
} else {
//Otherwise show a cyan back with array's name
Color.cyan
.ignoresSafeArea()
Text(people[randomPerson])
.font(.largeTitle)
.bold()
.foregroundColor(.white)
}
Text("\(timeRemaining)")
.font(.system(size: 39))
.padding(.bottom, 200)
.onReceive(timer) { _ in
if timeRemaining > 0 {
timeRemaining -= 1
}
}
Text("Score: \(score)")
.font(.largeTitle)
.bold()
.foregroundColor(.white)
.padding(.top, 200)
}
.onAppear {
//Detect device motion
self.motionManager.startDeviceMotionUpdates(to: self.queue) { (data: CMDeviceMotion?, error: Error?) in
guard let data = data else {
print("Error: \(error!)")
return
}
let attitude: CMAttitude = data.attitude
DispatchQueue.main.async {
self.roll = attitude.roll
}
}
}
}
.navigationViewStyle(.stack)
}
}
You can do like this:
@State private var currerntPerson : String = ""
getRandomPerson()
Text(currerntPerson) .font(.largeTitle) .bold() .foregroundColor(.white) .onAppear { getRandomPerson() }
==== All code here:
let motionManager = CMMotionManager()
let queue = OperationQueue()
@State private var roll = Double.zero
@State private var people = ["John", "Marcus", "Steve", "Eric", "Philip"].shuffled()
@State private var randomPerson = Int.random(in: 0...4)
let timer = Timer.publish(every: 1, tolerance: 0.5, on: .main, in: .common).autoconnect()
@State private var timeRemaining = 10
@State private var score = 0
@State private var currerntPerson : String = ""
var body: some View {
NavigationView {
ZStack {
//Show a red background and "SKIP" if the user raises head
if roll < 1 {
Color.red
.ignoresSafeArea()
Text("SKIP")
.font(.largeTitle)
.bold()
.foregroundColor(.white)
} else if roll > 2.1 {
//Show a green background and "CORRECT" if user lowers head
Color.green
.ignoresSafeArea()
Text("CORRECT")
.font(.largeTitle)
.bold()
.foregroundColor(.white)
.onAppear {
score += 1
}
} else {
//Otherwise show a cyan back with array's name
Color.cyan
.ignoresSafeArea()
Text(currerntPerson)
.font(.largeTitle)
.bold()
.foregroundColor(.white)
.onAppear {
getRandomPerson()
}
}
Text("\(timeRemaining)")
.font(.system(size: 39))
.padding(.bottom, 200)
.onReceive(timer) { _ in
if timeRemaining > 0 {
timeRemaining -= 1
}
}
Text("Score: \(score)")
.font(.largeTitle)
.bold()
.foregroundColor(.white)
.padding(.top, 200)
}
.onAppear {
//Detect device motion
self.motionManager.startDeviceMotionUpdates(to: self.queue) { (data: CMDeviceMotion?, error: Error?) in
guard let data = data else {
print("Error: \(error!)")
return
}
let attitude: CMAttitude = data.attitude
DispatchQueue.main.async {
self.roll = attitude.roll
}
}
}
}
.navigationViewStyle(.stack)
}
func getRandomPerson() {
if people.count > 0 {
let index = Int.random(in: 0..<people.count)
currerntPerson = people[index]
people.remove(at: index)
}
}