@@ -39,8 +39,9 @@ type Camera struct {
39
39
// If ShakeEnabled is false, AddTrauma() has no effect and shake is always 0.
40
40
//
41
41
// The default value is false
42
- ShakeEnabled bool
43
-
42
+ ShakeEnabled bool
43
+ XAxisSmoothingDisabled bool
44
+ YAxisSmoothingDisabled bool
44
45
// ShakeOptions holds the camera shake options.
45
46
ShakeOptions * ShakeOptions
46
47
@@ -92,90 +93,129 @@ func DefaultCameraShakeOptions() *ShakeOptions {
92
93
return opt
93
94
}
94
95
95
- // smoothDamp gradually changes a value towards a desired goal over time.
96
- func (cam * Camera ) smoothDamp (targetX , targetY float64 ) ( float64 , float64 ) {
97
- // Ensure smooth times are not too small to avoid division by zero
96
+ // smoothDampX gradually changes a value towards a desired goal over time for X axis .
97
+ func (cam * Camera ) smoothDampX (targetX float64 ) float64 {
98
+ // Ensure smooth time is not too small to avoid division by zero
98
99
smoothTimeX := math .Max (0.0001 , cam .SmoothOptions .SmoothDampTimeX )
99
- smoothTimeY := math .Max (0.0001 , cam .SmoothOptions .SmoothDampTimeY )
100
100
101
- // Calculate exponential decay factors for X and Y
101
+ // Calculate exponential decay factor for X
102
102
omegaX := 2.0 / smoothTimeX
103
- omegaY := 2.0 / smoothTimeY
104
-
105
103
xX := omegaX * 0.016666666666666666
106
- xY := omegaY * 0.016666666666666666
107
-
108
104
expX := 1.0 / (1.0 + xX + 0.48 * xX * xX + 0.235 * xX * xX * xX )
109
- expY := 1.0 / (1.0 + xY + 0.48 * xY * xY + 0.235 * xY * xY * xY )
110
105
111
- // Calculate change with independent max speeds
106
+ // Calculate change with max speed
112
107
changeX := cam .tempTargetX - targetX
113
- changeY := cam .tempTargetY - targetY
114
-
115
108
originalToX := targetX
116
- originalToY := targetY
117
-
118
109
maxChangeX := cam .SmoothOptions .SmoothDampMaxSpeedX * smoothTimeX
119
- maxChangeY := cam .SmoothOptions .SmoothDampMaxSpeedY * smoothTimeY
120
-
121
110
maxChangeXSq := maxChangeX * maxChangeX
122
- maxChangeYSq := maxChangeY * maxChangeY
123
111
124
- // Limit change independently for X and Y
112
+ // Limit change
125
113
if changeX * changeX > maxChangeXSq {
126
114
changeX = math .Copysign (maxChangeX , changeX )
127
115
}
128
116
117
+ targetX = cam .tempTargetX - changeX
118
+
119
+ // Calculate velocity and output with exponential decay
120
+ tempVelocityX := (cam .currentVelocityX + changeX * omegaX ) * 0.016666666666666666
121
+ cam .currentVelocityX = (cam .currentVelocityX - tempVelocityX * omegaX ) * expX
122
+ outputX := targetX + (changeX + tempVelocityX )* expX
123
+
124
+ // Check if we've overshot the target
125
+ origMinusCurrentX := originalToX - cam .tempTargetX
126
+ outMinusOrigX := outputX - originalToX
127
+
128
+ if origMinusCurrentX * outMinusOrigX > 0 {
129
+ outputX = originalToX
130
+ cam .currentVelocityX = (outputX - originalToX ) / 0.016666666666666666
131
+ }
132
+
133
+ return outputX
134
+ }
135
+
136
+ // smoothDampY gradually changes a value towards a desired goal over time for Y axis.
137
+ func (cam * Camera ) smoothDampY (targetY float64 ) float64 {
138
+ // Ensure smooth time is not too small to avoid division by zero
139
+ smoothTimeY := math .Max (0.0001 , cam .SmoothOptions .SmoothDampTimeY )
140
+
141
+ // Calculate exponential decay factor for Y
142
+ omegaY := 2.0 / smoothTimeY
143
+ xY := omegaY * 0.016666666666666666
144
+ expY := 1.0 / (1.0 + xY + 0.48 * xY * xY + 0.235 * xY * xY * xY )
145
+
146
+ // Calculate change with max speed
147
+ changeY := cam .tempTargetY - targetY
148
+ originalToY := targetY
149
+ maxChangeY := cam .SmoothOptions .SmoothDampMaxSpeedY * smoothTimeY
150
+ maxChangeYSq := maxChangeY * maxChangeY
151
+
152
+ // Limit change
129
153
if changeY * changeY > maxChangeYSq {
130
154
changeY = math .Copysign (maxChangeY , changeY )
131
155
}
132
156
133
- targetX = cam .tempTargetX - changeX
134
157
targetY = cam .tempTargetY - changeY
135
158
136
- // Calculate velocity and output with independent exponential decay
137
- tempVelocityX := (cam .currentVelocityX + changeX * omegaX ) * 0.016666666666666666
159
+ // Calculate velocity and output with exponential decay
138
160
tempVelocityY := (cam .currentVelocityY + changeY * omegaY ) * 0.016666666666666666
139
-
140
- cam .currentVelocityX = (cam .currentVelocityX - tempVelocityX * omegaX ) * expX
141
161
cam .currentVelocityY = (cam .currentVelocityY - tempVelocityY * omegaY ) * expY
142
-
143
- outputX := targetX + (changeX + tempVelocityX )* expX
144
162
outputY := targetY + (changeY + tempVelocityY )* expY
145
163
146
- origMinusCurrentX := originalToX - cam . tempTargetX
164
+ // Check if we've overshot the target
147
165
origMinusCurrentY := originalToY - cam .tempTargetY
148
-
149
- outMinusOrigX := outputX - originalToX
150
166
outMinusOrigY := outputY - originalToY
151
167
152
- dot := origMinusCurrentX * outMinusOrigX + origMinusCurrentY * outMinusOrigY
153
-
154
- if dot > 0 {
155
- outputX = originalToX
168
+ if origMinusCurrentY * outMinusOrigY > 0 {
156
169
outputY = originalToY
157
- cam .currentVelocityX = (outputX - originalToX ) / 0.016666666666666666
158
170
cam .currentVelocityY = (outputY - originalToY ) / 0.016666666666666666
159
171
}
160
172
161
- return outputX , outputY
173
+ return outputY
162
174
}
163
175
164
176
// LookAt aligns the midpoint of the camera viewport to the target.
165
177
// Use this function only once in Update() and change only the (targetX, targetY)
166
178
func (cam * Camera ) LookAt (targetX , targetY float64 ) {
167
179
switch cam .SmoothType {
168
180
case SmoothDamp :
169
- cam .tempTargetX , cam .tempTargetY = cam .smoothDamp (targetX , targetY )
170
- cam .topLeftX = cam .tempTargetX
171
- cam .topLeftY = cam .tempTargetY
172
-
181
+ if ! cam .XAxisSmoothingDisabled && ! cam .YAxisSmoothingDisabled {
182
+ cam .tempTargetX = cam .smoothDampX (targetX )
183
+ cam .tempTargetY = cam .smoothDampY (targetY )
184
+ cam .topLeftX = cam .tempTargetX
185
+ cam .topLeftY = cam .tempTargetY
186
+ } else if ! cam .XAxisSmoothingDisabled && cam .YAxisSmoothingDisabled {
187
+ cam .tempTargetX = cam .smoothDampX (targetX )
188
+ cam .topLeftX = cam .tempTargetX
189
+ cam .topLeftY = targetY
190
+ } else if cam .XAxisSmoothingDisabled && ! cam .YAxisSmoothingDisabled {
191
+ cam .tempTargetY = cam .smoothDampY (targetY )
192
+ cam .topLeftY = cam .tempTargetY
193
+ cam .topLeftX = targetX
194
+ } else {
195
+ cam .topLeftX = targetX
196
+ cam .topLeftY = targetY
197
+ }
173
198
case Lerp :
174
- cam .tempTargetX = lerp (cam .tempTargetX , targetX , cam .SmoothOptions .LerpSpeedX )
175
- cam .tempTargetY = lerp (cam .tempTargetY , targetY , cam .SmoothOptions .LerpSpeedY )
176
- cam .topLeftX , cam .topLeftY = cam .tempTargetX , cam .tempTargetY
199
+ if ! cam .XAxisSmoothingDisabled && ! cam .YAxisSmoothingDisabled {
200
+ cam .tempTargetX = lerp (cam .tempTargetX , targetX , cam .SmoothOptions .LerpSpeedX )
201
+ cam .tempTargetY = lerp (cam .tempTargetY , targetY , cam .SmoothOptions .LerpSpeedY )
202
+ cam .topLeftX = cam .tempTargetX
203
+ cam .topLeftY = cam .tempTargetY
204
+ } else if ! cam .XAxisSmoothingDisabled && cam .YAxisSmoothingDisabled {
205
+ cam .tempTargetX = lerp (cam .tempTargetX , targetX , cam .SmoothOptions .LerpSpeedX )
206
+ cam .topLeftX = cam .tempTargetX
207
+ cam .topLeftY = targetY
208
+ } else if cam .XAxisSmoothingDisabled && ! cam .YAxisSmoothingDisabled {
209
+ cam .tempTargetY = lerp (cam .tempTargetY , targetY , cam .SmoothOptions .LerpSpeedY )
210
+ cam .topLeftY = cam .tempTargetY
211
+ cam .topLeftX = targetX
212
+ } else {
213
+ cam .topLeftX = targetX
214
+ cam .topLeftY = targetY
215
+ }
177
216
default :
178
- cam .topLeftX , cam .topLeftY = targetX , targetY
217
+ cam .topLeftX = targetX
218
+ cam .topLeftY = targetY
179
219
}
180
220
if cam .ShakeEnabled {
181
221
if cam .trauma > 0 {
0 commit comments