Skip to content

Commit 1712f4c

Browse files
committed
Update KeyboardControlledForceComponent.swift
Adopt AcceleratedValue
1 parent 427984f commit 1712f4c

File tree

1 file changed

+44
-32
lines changed

1 file changed

+44
-32
lines changed

Sources/OctopusKit/Components/Input/Keyboard/KeyboardControlledForceComponent.swift

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import GameplayKit
1919
@available(macOS 10.15, *)
2020
public final class KeyboardControlledForceComponent: OctopusComponent, OctopusUpdatableComponent {
2121

22+
// TODO: Tests
23+
2224
public override var requiredComponents: [GKComponent.Type]? {
2325
[KeyboardEventComponent.self,
2426
PhysicsComponent.self]
@@ -33,44 +35,57 @@ public final class KeyboardControlledForceComponent: OctopusComponent, OctopusUp
3335
/// Change this to a different code to customize the keys.
3436
public var arrowLeft: UInt16 = .arrowLeft
3537

36-
public var baseMagnitude: CGFloat
37-
public var maximumMagnitude: CGFloat
38-
public var acceleratedMagnitude: CGFloat = 0
39-
40-
/// The amount to increase `acceleratedMagnitude` by, per update, while there is keyboard input. `acceleratedMagnitude` is reset to `baseMagnitude` when there is no keyboard input.
41-
public var acceleration: CGFloat
42-
43-
public var horizontalFactor: CGFloat = 1
44-
public var verticalFactor: CGFloat = 1
38+
public var magnitude: AcceleratedValue<CGFloat>
39+
40+
public var horizontalFactor: CGFloat
41+
public var verticalFactor: CGFloat
4542

4643
/// Specifies a fixed or variable timestep for per-update changes.
4744
///
4845
/// For physics effects, a per-second timestep may be suitable.
49-
public var timestep: TimeStep
46+
public var timestep: TimeStep
5047

5148
/// - Parameters:
52-
/// - baseMagnitude: The minimum magnitude to apply to the physics body on every update. Affected by `timestep`.
53-
/// - maximumMagnitude: The maximum magnitude to allow after acceleration has been applied.
54-
/// - acceleration: The amount to increase the magnitude by, per update, while there is keyboard input. The magnitude is reset to the `baseMagnitude` when there is no keyboard input. Affected by `timestep`.
55-
/// - horizontalFactor: Multiply the X axis force by this factor. Default: `1`. To reverse the X axis, specify a negative value like `-1`. To disable the X axis, specify `0`.
56-
/// - verticalFactor: Multiply the Y axis force by this factor. Default: `1`. To reverse the Y axis, specify a negative value like `-1`. To disable the Y axis, specify `0`.
49+
/// - magnitude: The magnitude to apply to the physics body on every update. Affected by `timestep`.
50+
/// - horizontalFactor: Multiply the X axis force by this factor. Default: `1.0`. To reverse the X axis, specify a negative value like `-1`. To disable the X axis, specify `0`.
51+
/// - verticalFactor: Multiply the Y axis force by this factor. Default: `1.0`. To reverse the Y axis, specify a negative value like `-1`. To disable the Y axis, specify `0`.
5752
/// - timestep: Specifies a fixed or variable timestep for per-update changes. Default: `.perSecond`
58-
public init(baseMagnitude: CGFloat = 600, // ÷ 60 = 10 per frame
59-
maximumMagnitude: CGFloat = 1200, // ÷ 60 = 20 per frame
60-
acceleration: CGFloat = 600,
61-
horizontalFactor: CGFloat = 1,
62-
verticalFactor: CGFloat = 1,
53+
public init(magnitude: AcceleratedValue<CGFloat>,
54+
horizontalFactor: CGFloat = 1.0,
55+
verticalFactor: CGFloat = 1.0,
6356
timestep: TimeStep = .perSecond)
6457
{
65-
self.baseMagnitude = baseMagnitude
66-
self.maximumMagnitude = maximumMagnitude
67-
self.acceleration = acceleration
58+
self.magnitude = magnitude
6859
self.horizontalFactor = horizontalFactor
6960
self.verticalFactor = verticalFactor
7061
self.timestep = timestep
7162
super.init()
7263
}
7364

65+
/// - Parameters:
66+
/// - baseMagnitude: The minimum magnitude to apply to the physics body on every update. Affected by `timestep`.
67+
/// - maximumMagnitude: The maximum magnitude to allow after acceleration has been applied.
68+
/// - acceleration: The amount to increase the magnitude by, per update, while there is keyboard input. The magnitude is reset to the `baseMagnitude` when there is no keyboard input. Affected by `timestep`.
69+
/// - horizontalFactor: Multiply the X axis force by this factor. Default: `1.0`. To reverse the X axis, specify a negative value like `-1`. To disable the X axis, specify `0`.
70+
/// - verticalFactor: Multiply the Y axis force by this factor. Default: `1.0`. To reverse the Y axis, specify a negative value like `-1`. To disable the Y axis, specify `0`.
71+
/// - timestep: Specifies a fixed or variable timestep for per-update changes. Default: `.perSecond`
72+
public convenience init(baseMagnitude: CGFloat = 600, // ÷ 60 = 10 per frame
73+
maximumMagnitude: CGFloat = 1200, // ÷ 60 = 20 per frame
74+
acceleration: CGFloat = 600,
75+
horizontalFactor: CGFloat = 1.0,
76+
verticalFactor: CGFloat = 1.0,
77+
timestep: TimeStep = .perSecond)
78+
{
79+
self.init(magnitude: AcceleratedValue<CGFloat>(base: baseMagnitude,
80+
current: baseMagnitude,
81+
maximum: maximumMagnitude,
82+
minimum: 0,
83+
acceleration: acceleration),
84+
horizontalFactor: horizontalFactor,
85+
verticalFactor: verticalFactor,
86+
timestep: timestep)
87+
}
88+
7489
public required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
7590

7691
@inlinable
@@ -81,15 +96,15 @@ public final class KeyboardControlledForceComponent: OctopusComponent, OctopusUp
8196
!keyboardEventComponent.codesPressed.isEmpty,
8297
let physicsBody = coComponent(PhysicsComponent.self)?.physicsBody ?? entityNode?.physicsBody
8398
else {
84-
acceleratedMagnitude = baseMagnitude // TODO: PERFORMANCE: Figure out a better way than setting this every update.
99+
magnitude.reset() // TODO: PERFORMANCE: Figure out a better way than setting this every update.
85100
return
86101
}
87102

88103
// Did player press a directional arrow key?
89104
// ❕ NOTE: Don't use `switch` or `else` because we want to process multiple keypresses, to generate diagonal forces and also cancel out opposing directions.
90105

91106
let codesPressed = keyboardEventComponent.codesPressed
92-
let magnitudeForCurrentUpdate = timestep.applying(acceleratedMagnitude, deltaTime: CGFloat(seconds))
107+
let magnitudeForCurrentUpdate = timestep.applying(magnitude.current, deltaTime: CGFloat(seconds))
93108
var vector = CGVector.zero
94109

95110
if codesPressed.contains(self.arrowUp) { vector.dy += magnitudeForCurrentUpdate } // ⬆️
@@ -105,19 +120,16 @@ public final class KeyboardControlledForceComponent: OctopusComponent, OctopusUp
105120
// Apply the final vector to the body.
106121

107122
#if LOGINPUTEVENTS
108-
debugLog("acceleratedMagnitude: \(acceleratedMagnitude), magnitudeForCurrentUpdate: \(magnitudeForCurrentUpdate), acceleration: \(acceleration), horizontalFactor: \(horizontalFactor), verticalFactor: \(horizontalFactor), force: \(vector)")
123+
debugLog("magnitude: \(magnitude), magnitudeForCurrentUpdate: \(magnitudeForCurrentUpdate), horizontalFactor: \(horizontalFactor), verticalFactor: \(horizontalFactor), force: \(vector)")
109124
#endif
110125

111126
physicsBody.applyForce(vector)
112127

113128
// Apply acceleration for the next update.
114129

115-
if acceleratedMagnitude < maximumMagnitude {
116-
timestep.apply(acceleration, to: &acceleratedMagnitude, deltaTime: CGFloat(seconds))
117-
118-
if acceleratedMagnitude > maximumMagnitude {
119-
acceleratedMagnitude = maximumMagnitude
120-
}
130+
if magnitude.isWithinBounds {
131+
magnitude.update(timestep: timestep, deltaTime: CGFloat(seconds))
132+
magnitude.clamp()
121133
}
122134
}
123135
}

0 commit comments

Comments
 (0)