Skip to content

Commit

Permalink
Update GamePadViewer
Browse files Browse the repository at this point in the history
  • Loading branch information
tekezo committed Oct 8, 2023
1 parent 4803a0c commit 402213b
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 77 deletions.
117 changes: 47 additions & 70 deletions appendix/GamePadViewer/src/StickManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,14 @@ import SwiftUI
public class StickManager: ObservableObject {
public static let shared = StickManager()

struct Event {
var timeStamp: Date
var value: Double
var acceleration: Double

func attenuatedAcceleration(_ now: Date) -> Double {
let attenuation = 5 * now.timeIntervalSince(timeStamp)
if abs(acceleration) < attenuation {
return 0
}
if acceleration > 0 {
return acceleration - attenuation
} else {
return acceleration + attenuation
}
}
struct History {
let timeStamp: Date
let radian: Double
var magnitude: Double
}

class StickSensor: ObservableObject {
@Published var lastDoubleValue = 0.0
@Published var lastTimeStamp = Date()
@Published var lastInterval = 0.0
@Published var lastAcceleration = 0.0
var eventHistories: [Event] = []

@MainActor
func add(
Expand All @@ -36,56 +20,9 @@ public class StickManager: ObservableObject {
_ integerValue: Int64
) {
if logicalMax != logicalMin {
let previousDoubleValue = lastDoubleValue
let previousTimeStamp = lastTimeStamp

let now = Date()

// -1.0 ... 1.0
lastDoubleValue =
(Double(integerValue - logicalMin) / Double(logicalMax - logicalMin) - 0.5) * 2.0

lastTimeStamp = now

lastInterval = max(
now.timeIntervalSince(previousTimeStamp),
0.001 // 1 ms
)

// -1000.0 ... 1000.0
let acceleration = (lastDoubleValue - previousDoubleValue) / lastInterval

eventHistories.append(
Event(
timeStamp: now,
value: lastDoubleValue,
acceleration: acceleration))
}
}

@MainActor
func update() {
guard let last = eventHistories.last else {
lastAcceleration = 0.0
return
}

let deadzone = 0.1
if abs(last.value) < deadzone {
eventHistories.removeAll()
lastAcceleration = 0.0
} else {
let now = Date()
var sum = 0.0
eventHistories.forEach { e in
sum += e.attenuatedAcceleration(now)
}
lastAcceleration = sum

eventHistories.removeAll(where: {
let attenuatedAcceleration = $0.attenuatedAcceleration(now)
return attenuatedAcceleration == 0 || sum * attenuatedAcceleration < 0
})
}
}
}
Expand All @@ -95,14 +32,54 @@ public class StickManager: ObservableObject {
@Published var vertical = StickSensor()
@Published var radian = 0.0
@Published var magnitude = 0.0
@Published var holdingAcceleration = 0.0
@Published var holdingMagnitude = 0.0
var histories: [History] = []

@MainActor
func update() {
radian = atan2(vertical.lastDoubleValue, horizontal.lastDoubleValue)
magnitude = sqrt(pow(vertical.lastDoubleValue, 2) + pow(horizontal.lastDoubleValue, 2))
magnitude = min(
1.0,
sqrt(pow(vertical.lastDoubleValue, 2) + pow(horizontal.lastDoubleValue, 2)))

let deadzone = 0.1
if abs(vertical.lastDoubleValue) < deadzone && abs(horizontal.lastDoubleValue) < deadzone {
histories.removeAll()
holdingAcceleration = 0.0
holdingMagnitude = 0.0
return
}

let now = Date()

histories.removeAll(where: {
return now.timeIntervalSince($0.timeStamp) > 0.02 // 20 ms
})

histories.append(
History(
timeStamp: now,
radian: radian,
magnitude: magnitude))

let minMagnitude = histories.min(by: { $0.magnitude < $1.magnitude })
let maxMagnitude = histories.max(by: { $0.magnitude < $1.magnitude })
let a = (maxMagnitude?.magnitude ?? 0) - (minMagnitude?.magnitude ?? 0)

if holdingAcceleration < a {
// Increase acceleration if magnitude is increased.
if magnitude > holdingMagnitude {
holdingAcceleration = a
}
} else {
// Decrease acceleration if magnitude is decreased.
if magnitude < holdingMagnitude {
holdingAcceleration = a
}
}

horizontal.update()
vertical.update()
holdingMagnitude = magnitude
}
}

Expand Down
15 changes: 8 additions & 7 deletions appendix/GamePadViewer/src/View/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ struct ContentView: View {

let circleSize = 100.0
let indicatorSize = 10.0
let stickDivider = 50.0
let accelerationScale = 10.0

var body: some View {
VStack {
VStack(alignment: .leading) {
Text("counter: \(eventObserver.counter)")
Text("Right Stick radian: \(stickManager.rightStick.radian)")
Text("Right Stick magnitude: \(stickManager.rightStick.magnitude)")
Text("Right stick holding acceleration: \(stickManager.rightStick.holdingAcceleration)")
Text("Right stick holding magnitude: \(stickManager.rightStick.holdingMagnitude)")

StickSensorInfo(label: "Right Stick X", stick: stickManager.rightStick.horizontal)
StickSensorInfo(label: "Right Stick Y", stick: stickManager.rightStick.vertical)
Expand Down Expand Up @@ -43,10 +45,11 @@ struct ContentView: View {
path.move(to: CGPoint(x: circleSize / 2.0, y: circleSize / 2.0))
path.addLine(
to: CGPoint(
x: stickManager.rightStick.horizontal.lastAcceleration / stickDivider * circleSize
+ circleSize / 2.0,
y: stickManager.rightStick.vertical.lastAcceleration / stickDivider * circleSize
+ circleSize / 2.0
x: circleSize / 2.0 + cos(stickManager.rightStick.radian)
* stickManager.rightStick.holdingAcceleration * accelerationScale * circleSize
/ 2.0,
y: circleSize / 2.0 + sin(stickManager.rightStick.radian)
* stickManager.rightStick.holdingAcceleration * accelerationScale * circleSize / 2.0
))
}
.stroke(Color.red, lineWidth: 2)
Expand All @@ -72,8 +75,6 @@ struct StickSensorInfo: View {
VStack(alignment: .leading) {
Text("\(label):")
Text(" value: \(stick.lastDoubleValue)")
Text(" interval: \(stick.lastInterval)")
Text(" acceleration: \(stick.lastAcceleration)")
}
}
}
Expand Down

0 comments on commit 402213b

Please sign in to comment.